aboutsummaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/core.py10
-rw-r--r--python/mal_types.py7
-rw-r--r--python/printer.py4
-rw-r--r--python/reader.py3
-rw-r--r--python/step3_env.py8
-rw-r--r--python/step4_if_fn_do.py2
-rw-r--r--python/step5_tco.py2
-rw-r--r--python/step6_file.py6
-rw-r--r--python/step7_quote.py6
-rw-r--r--python/step8_macros.py6
-rw-r--r--python/step9_try.py8
-rw-r--r--python/stepA_interop.py6
12 files changed, 41 insertions, 27 deletions
diff --git a/python/core.py b/python/core.py
index d10047d..4a64594 100644
--- a/python/core.py
+++ b/python/core.py
@@ -60,7 +60,9 @@ def cons(x, seq): return List([x]) + List(seq)
def concat(*lsts): return List(chain(*lsts))
-def nth(lst, idx): return lst[idx]
+def nth(lst, idx):
+ if idx < len(lst): return lst[idx]
+ else: throw("nth: index out of range")
def first(lst): return lst[0]
@@ -68,7 +70,9 @@ def rest(lst): return List(lst[1:])
def empty_Q(lst): return len(lst) == 0
-def count(lst): return len(lst)
+def count(lst):
+ if types._nil_Q(lst): return 0
+ else: return len(lst)
# retains metadata
def conj(lst, *args):
@@ -114,6 +118,8 @@ ns = {
'false?': types._false_Q,
'symbol': types._symbol,
'symbol?': types._symbol_Q,
+ 'keyword': types._keyword,
+ 'keyword?': types._keyword_Q,
'pr-str': pr_str,
'str': do_str,
diff --git a/python/mal_types.py b/python/mal_types.py
index e6bd70d..5fb9bba 100644
--- a/python/mal_types.py
+++ b/python/mal_types.py
@@ -58,6 +58,13 @@ class Symbol(str): pass
def _symbol(str): return Symbol(str)
def _symbol_Q(exp): return type(exp) == Symbol
+# Keywords
+# A specially prefixed string
+def _keyword(str):
+ if str[0] == u"\u029e": return str
+ else: return u"\u029e" + str
+def _keyword_Q(exp): return _string_Q(exp) and exp[0] == u"\u029e"
+
# Functions
def _function(Eval, Env, ast, env, params):
def fn(*args):
diff --git a/python/printer.py b/python/printer.py
index 65bf256..78a2fcf 100644
--- a/python/printer.py
+++ b/python/printer.py
@@ -12,7 +12,9 @@ def _pr_str(obj, print_readably=True):
ret.extend((_pr_str(k), _pr_str(obj[k],_r)))
return "{" + " ".join(ret) + "}"
elif types._string_Q(obj):
- if print_readably:
+ if len(obj) > 0 and obj[0] == u'\u029e':
+ return ':' + obj[1:]
+ elif print_readably:
return '"' + obj.encode('unicode_escape').decode('latin1').replace('"', '\\"') + '"'
else:
return obj
diff --git a/python/reader.py b/python/reader.py
index 13b1f7b..71ad3d6 100644
--- a/python/reader.py
+++ b/python/reader.py
@@ -1,5 +1,5 @@
import re
-from mal_types import (_symbol, _list, _vector, _hash_map)
+from mal_types import (_symbol, _keyword, _list, _vector, _hash_map)
class Blank(Exception): pass
@@ -29,6 +29,7 @@ def read_atom(reader):
if re.match(int_re, token): return int(token)
elif re.match(float_re, token): return int(token)
elif token[0] == '"': return token[1:-1].replace('\\"', '"')
+ elif token[0] == ':': return _keyword(token[1:])
elif token == "nil": return None
elif token == "true": return True
elif token == "false": return False
diff --git a/python/step3_env.py b/python/step3_env.py
index 4565011..86dc176 100644
--- a/python/step3_env.py
+++ b/python/step3_env.py
@@ -58,10 +58,10 @@ repl_env = Env()
def REP(str):
return PRINT(EVAL(READ(str), repl_env))
-repl_env.set('+', lambda a,b: a+b)
-repl_env.set('-', lambda a,b: a-b)
-repl_env.set('*', lambda a,b: a*b)
-repl_env.set('/', lambda a,b: int(a/b))
+repl_env.set(types._symbol('+'), lambda a,b: a+b)
+repl_env.set(types._symbol('-'), lambda a,b: a-b)
+repl_env.set(types._symbol('*'), lambda a,b: a*b)
+repl_env.set(types._symbol('/'), lambda a,b: int(a/b))
# repl loop
while True:
diff --git a/python/step4_if_fn_do.py b/python/step4_if_fn_do.py
index e99cfcf..39b9dd6 100644
--- a/python/step4_if_fn_do.py
+++ b/python/step4_if_fn_do.py
@@ -74,7 +74,7 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
# core.mal: defined using the language itself
REP("(def! not (fn* (a) (if a false true)))")
diff --git a/python/step5_tco.py b/python/step5_tco.py
index cbb92c9..da338d4 100644
--- a/python/step5_tco.py
+++ b/python/step5_tco.py
@@ -83,7 +83,7 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
# core.mal: defined using the language itself
REP("(def! not (fn* (a) (if a false true)))")
diff --git a/python/step6_file.py b/python/step6_file.py
index 9d84d1f..5d10b46 100644
--- a/python/step6_file.py
+++ b/python/step6_file.py
@@ -83,9 +83,9 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
-repl_env.set('eval', lambda ast: EVAL(ast, repl_env))
-repl_env.set('*ARGV*', types._list(*sys.argv[2:]))
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
+repl_env.set(types._symbol('eval'), lambda ast: EVAL(ast, repl_env))
+repl_env.set(types._symbol('*ARGV*'), types._list(*sys.argv[2:]))
# core.mal: defined using the language itself
REP("(def! not (fn* (a) (if a false true)))")
diff --git a/python/step7_quote.py b/python/step7_quote.py
index de19c6d..7c97c23 100644
--- a/python/step7_quote.py
+++ b/python/step7_quote.py
@@ -106,9 +106,9 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
-repl_env.set('eval', lambda ast: EVAL(ast, repl_env))
-repl_env.set('*ARGV*', types._list(*sys.argv[2:]))
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
+repl_env.set(types._symbol('eval'), lambda ast: EVAL(ast, repl_env))
+repl_env.set(types._symbol('*ARGV*'), types._list(*sys.argv[2:]))
# core.mal: defined using the language itself
REP("(def! not (fn* (a) (if a false true)))")
diff --git a/python/step8_macros.py b/python/step8_macros.py
index 80ca239..da863c1 100644
--- a/python/step8_macros.py
+++ b/python/step8_macros.py
@@ -126,9 +126,9 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
-repl_env.set('eval', lambda ast: EVAL(ast, repl_env))
-repl_env.set('*ARGV*', types._list(*sys.argv[2:]))
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
+repl_env.set(types._symbol('eval'), lambda ast: EVAL(ast, repl_env))
+repl_env.set(types._symbol('*ARGV*'), types._list(*sys.argv[2:]))
# core.mal: defined using the language itself
REP("(def! not (fn* (a) (if a false true)))")
diff --git a/python/step9_try.py b/python/step9_try.py
index 65da08c..e01f42c 100644
--- a/python/step9_try.py
+++ b/python/step9_try.py
@@ -143,12 +143,11 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
-repl_env.set('eval', lambda ast: EVAL(ast, repl_env))
-repl_env.set('*ARGV*', types._list(*sys.argv[2:]))
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
+repl_env.set(types._symbol('eval'), lambda ast: EVAL(ast, repl_env))
+repl_env.set(types._symbol('*ARGV*'), types._list(*sys.argv[2:]))
# core.mal: defined using the language itself
-REP("(def! *host-language* \"python\")")
REP("(def! not (fn* (a) (if a false true)))")
REP("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))")
REP("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))")
@@ -159,7 +158,6 @@ if len(sys.argv) >= 2:
sys.exit(0)
# repl loop
-REP("(println (str \"Mal [\" *host-language* \"]\"))")
while True:
try:
line = mal_readline.readline("user> ")
diff --git a/python/stepA_interop.py b/python/stepA_interop.py
index 723f0ed..93cdb2e 100644
--- a/python/stepA_interop.py
+++ b/python/stepA_interop.py
@@ -149,9 +149,9 @@ def REP(str):
return PRINT(EVAL(READ(str), repl_env))
# core.py: defined using python
-for k, v in core.ns.items(): repl_env.set(k, v)
-repl_env.set('eval', lambda ast: EVAL(ast, repl_env))
-repl_env.set('*ARGV*', types._list(*sys.argv[2:]))
+for k, v in core.ns.items(): repl_env.set(types._symbol(k), v)
+repl_env.set(types._symbol('eval'), lambda ast: EVAL(ast, repl_env))
+repl_env.set(types._symbol('*ARGV*'), types._list(*sys.argv[2:]))
# core.mal: defined using the language itself
REP("(def! *host-language* \"python\")")