1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-11 13:55:55 +03:00

Python: metadata on builtin funcs. Support python3.

This commit is contained in:
Joel Martin 2014-04-16 22:42:17 -05:00
parent b3402a82d3
commit a05f7822b1
17 changed files with 70 additions and 37 deletions

View File

@ -4,6 +4,8 @@
MAL_IMPL = js
PYTHON = python
#
# Settings
#
@ -54,7 +56,7 @@ make_RUNTEST = ../runtest.py $(4) ../$(1) -- make -f ../$(2) $(5)
mal_RUNTEST = $(call $(MAL_IMPL)_RUNTEST,$(1),$(call $(MAL_IMPL)_STEP_TO_PROG,stepA),stepA,--start-timeout 30 --test-timeout 120,../$(2))
php_RUNTEST = ../runtest.py $(4) ../$(1) -- php ../$(2) $(5)
ps_RUNTEST = ../runtest.py $(4) ../$(1) -- "gs -q -dNODISPLAY -- ../$(2) $(5)"
python_RUNTEST = ../runtest.py $(4) ../$(1) -- python ../$(2) $(5)
python_RUNTEST = ../runtest.py $(4) ../$(1) -- $(PYTHON) ../$(2) $(5)
ruby_RUNTEST = ../runtest.py $(4) ../$(1) -- ruby ../$(2) $(5)

View File

@ -135,7 +135,7 @@ cd ps
gs -q -dNODISPLAY stepX_YYY.ps
```
### Python 2.X
### Python (2 or 3)
```
cd python

View File

@ -17,12 +17,12 @@ def do_str(*args):
return "".join(map(lambda exp: printer._pr_str(exp, False), args))
def prn(*args):
print " ".join(map(lambda exp: printer._pr_str(exp, True), args))
print(" ".join(map(lambda exp: printer._pr_str(exp, True), args)))
return None
def println(*args):
line = " ".join(map(lambda exp: printer._pr_str(exp, False), args))
print line.replace('\\n', '\n')
print(line.replace('\\n', '\n'))
return None
@ -85,10 +85,7 @@ def mapf(f, lst): return List(map(f, lst))
# Metadata functions
def with_meta(obj, meta):
if type(obj) == type(lambda x:x):
new_obj = obj.__copy__()
else:
new_obj = copy.copy(obj)
new_obj = types._clone(obj)
new_obj.__meta__ = meta
return new_obj
@ -126,7 +123,7 @@ ns = {
'+': lambda a,b: a+b,
'-': lambda a,b: a-b,
'*': lambda a,b: a*b,
'/': lambda a,b: a/b,
'/': lambda a,b: int(a/b),
'list': types._list,
'list?': types._list_Q,

View File

@ -1,7 +1,11 @@
import os, readline as pyreadline
import os, sys, readline as pyreadline
history_loaded = False
histfile = os.path.expanduser("~/.mal-history")
if sys.version_info[0] >= 3:
rl = input
else:
rl = raw_input
def readline(prompt="user> "):
if not history_loaded:
@ -15,7 +19,7 @@ def readline(prompt="user> "):
pass
try:
line = raw_input(prompt)
line = rl(prompt)
pyreadline.add_history(line)
with open(histfile, "a") as hf:
hf.write(line + "\n")

View File

@ -1,3 +1,9 @@
import sys, copy, types as pytypes
if sys.version_info[0] >= 3:
str_types = [str]
else:
str_types = [str, unicode]
# General functions
def _equal_Q(a, b):
@ -26,11 +32,26 @@ def _equal_Q(a, b):
def _sequential_Q(seq): return _list_Q(seq) or _vector_Q(seq)
def _clone(obj):
#if type(obj) == type(lambda x:x):
if type(obj) == pytypes.FunctionType:
if obj.__code__:
return pytypes.FunctionType(
obj.__code__, obj.__globals__, name = obj.__name__,
argdefs = obj.__defaults__, closure = obj.__closure__)
else:
return pytypes.FunctionType(
obj.func_code, obj.func_globals, name = obj.func_name,
argdefs = obj.func_defaults, closure = obj.func_closure)
else:
return copy.copy(obj)
# Scalars
def _nil_Q(exp): return exp is None
def _true_Q(exp): return exp is True
def _false_Q(exp): return exp is False
def _string_Q(exp): return type(exp) in [str, unicode]
def _string_Q(exp): return type(exp) in str_types
# Symbols
class Symbol(str): pass
@ -39,15 +60,12 @@ def _symbol_Q(exp): return type(exp) == Symbol
# Functions
def _function(Eval, Env, ast, env, params):
def gen_fn():
def fn(*args):
return Eval(ast, Env(env, params, args))
fn.__meta__ = None
fn.__ast__ = ast
fn.__gen_env__ = lambda args: Env(env, params, args)
fn.__copy__ = gen_fn
return fn
return gen_fn()
def fn(*args):
return Eval(ast, Env(env, params, args))
fn.__meta__ = None
fn.__ast__ = ast
fn.__gen_env__ = lambda args: Env(env, params, args)
return fn
def _function_Q(f): return type(f) == type(function_Q)
# lists

View File

@ -13,7 +13,7 @@ def _pr_str(obj, print_readably=True):
return "{" + " ".join(ret) + "}"
elif types._string_Q(obj):
if print_readably:
return '"' + obj.encode('unicode_escape').replace('"', '\\"') + '"'
return '"' + obj.encode('unicode_escape').decode('latin1').replace('"', '\\"') + '"'
else:
return obj
elif types._nil_Q(obj):

View File

@ -27,4 +27,4 @@ while True:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -48,7 +48,7 @@ def REP(str):
repl_env['+'] = lambda a,b: a+b
repl_env['-'] = lambda a,b: a-b
repl_env['*'] = lambda a,b: a*b
repl_env['/'] = lambda a,b: a/b
repl_env['/'] = lambda a,b: int(a/b)
while True:
try:
@ -58,4 +58,4 @@ while True:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -62,7 +62,7 @@ def _ref(k,v): repl_env.set(k, v)
_ref('+', lambda a,b: a+b)
_ref('-', lambda a,b: a-b)
_ref('*', lambda a,b: a*b)
_ref('/', lambda a,b: a/b)
_ref('/', lambda a,b: int(a/b))
while True:
try:
@ -72,4 +72,4 @@ while True:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -88,4 +88,4 @@ while True:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -95,4 +95,4 @@ while True:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -103,4 +103,4 @@ else:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -125,4 +125,4 @@ else:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -145,4 +145,4 @@ else:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -154,4 +154,4 @@ else:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -89,7 +89,10 @@ def EVAL(ast, env):
elif 'macroexpand' == a0:
return macroexpand(ast[1], env)
elif "py!*" == a0:
exec compile(ast[1], '', 'single') in globals()
if sys.version_info[0] >= 3:
exec(compile(ast[1], '', 'single'), globals())
else:
exec(compile(ast[1], '', 'single') in globals())
return None
elif "py*" == a0:
return eval(ast[1])
@ -103,7 +106,7 @@ def EVAL(ast, env):
try:
return EVAL(a1, env);
except Exception as exc:
exc = exc.message
exc = exc.args[0]
catch_env = Env(env, [a2[1]], [exc])
return EVAL(a2[2], catch_env)
else:
@ -168,4 +171,4 @@ else:
print(REP(line))
except reader.Blank: continue
except Exception as e:
print "".join(traceback.format_exception(*sys.exc_info()))
print("".join(traceback.format_exception(*sys.exc_info())))

View File

@ -209,7 +209,7 @@
(meta l-wm)
;=>{"b" 2}
;; Testing metadata on functions
(def! f-wm (with-meta (fn* [a] (+ 1 a)) {"abc" 1}))
(meta f-wm)
;=>{"abc" 1}
@ -224,6 +224,15 @@
(meta f-wm2)
;=>{"abc" 1}
;; Testing metadata on builtin functions
(meta +)
;=>nil
(def! f-wm3 ^{"def" 2} +)
(meta f-wm3)
;=>{"def" 2}
(meta +)
;=>nil
;;
;; Make sure closures and metadata co-exist
(def! gen-plusX (fn* (x) (with-meta (fn* (b) (+ x b)) {"meta" 1})))