diff --git a/bf.kp b/bf.kp index dcfb8a2..6cb76b5 100644 --- a/bf.kp +++ b/bf.kp @@ -1,34 +1,33 @@ ; Now we have native BF support (def! with_update (fn* [arr idx val] - (if - (= idx 0) - (cons val (rest arr)) - (cons (first arr) (with_update (rest arr) (- idx 1) val))))) + (if (= idx 0) + (cons val (rest arr)) + (cons (first arr) (with_update (rest arr) (- idx 1) val))))) -(add_grammer_rule :bfs_atom ["<"] (fn* [xs] (list 'left))) -(add_grammer_rule :bfs_atom [">"] (fn* [xs] (list 'right))) -(add_grammer_rule :bfs_atom ["\\+"] (fn* [xs] (list 'plus))) -(add_grammer_rule :bfs_atom ["-"] (fn* [xs] (list 'minus))) -(add_grammer_rule :bfs_atom [","] (fn* [xs] (list 'in))) -(add_grammer_rule :bfs_atom ["."] (fn* [xs] (list 'out))) +(add_grammer_rule 'bfs_atom ["<"] (fn* [xs] (list 'left))) +(add_grammer_rule 'bfs_atom [">"] (fn* [xs] (list 'right))) +(add_grammer_rule 'bfs_atom ["\\+"] (fn* [xs] (list 'plus))) +(add_grammer_rule 'bfs_atom ["-"] (fn* [xs] (list 'minus))) +(add_grammer_rule 'bfs_atom [","] (fn* [xs] (list 'in))) +(add_grammer_rule 'bfs_atom ["."] (fn* [xs] (list 'out))) -(add_grammer_rule :non_empty_bfs_list [:bfs_atom] (fn* [xs] (list (nth xs 0)))) -(add_grammer_rule :non_empty_bfs_list [:bfs_atom :optional_WS :non_empty_bfs_list] (fn* [xs] (cons (nth xs 0) (nth xs 2)))) +(add_grammer_rule 'non_empty_bfs_list ['bfs_atom] (fn* [xs] (list (nth xs 0)))) +(add_grammer_rule 'non_empty_bfs_list ['bfs_atom 'optional_WS 'non_empty_bfs_list] (fn* [xs] (cons (nth xs 0) (nth xs 2)))) -(add_grammer_rule :bfs_list [] (fn* [xs] xs)) -(add_grammer_rule :bfs_list [:non_empty_bfs_list] (fn* [xs] (nth xs 0))) +(add_grammer_rule 'bfs_list [] (fn* [xs] xs)) +(add_grammer_rule 'bfs_list ['non_empty_bfs_list] (fn* [xs] (nth xs 0))) -(add_grammer_rule :bfs_atom ["\\[" :bfs_list "]"] (fn* [xs] +(add_grammer_rule 'bfs_atom ["\\[" 'bfs_list "]"] (fn* [xs] `(let* (f (fn* [] (if (= 0 (nth (deref arr) (deref ptr))) nil (do ,(nth xs 1) (f))))) (f)))) -(add_grammer_rule :bfs [:bfs_list] (fn* [xs] (nth xs 0))) +(add_grammer_rule 'bfs ['bfs_list] (fn* [xs] (nth xs 0))) -(add_grammer_rule :form ["bf" :optional_WS "{" :optional_WS :bfs :optional_WS "}"] +(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"] (fn* [xs] `(fn* [input] (let* ( diff --git a/k_prime.krak b/k_prime.krak index 9e51425..915c70f 100644 --- a/k_prime.krak +++ b/k_prime.krak @@ -7,38 +7,6 @@ import map:* import fungll:* -fun create_map(values: vec): MalResult { - var to_ret = map() - if values.size & 1 == 1 { - return MalResult::Err(MalValue::String(str("odd number of keys/values"))) - } - for (var i = 0; i < values.size; i+=2;) { - to_ret.set(values[i], values[i+1]) - } - return MalResult::Ok(MalValue::Map(to_ret)) -} -fun is_map(m: MalValue): bool { - match (m) { - MalValue::Map(m) { - return true - } - MalValue::Nil() { - return true - } - } - return false -} -fun get_map(m: MalValue): map { - match (m) { - MalValue::Map(m) { - return m - } - MalValue::Nil() { - return map() - } - } - error("can't get_map not a map") -} fun read_str(grammer: ref Grammer, s: str): pair { var BSR = fungll(grammer, grammer.start_symbol, s) var longest = -1 @@ -56,7 +24,6 @@ fun read_str(grammer: ref Grammer, s: str): pair, Vector: vec, - Map: map, Function: MalFunction, BuiltinFunction: MalBuiltinFunction, Atom: *MalValue @@ -125,21 +90,9 @@ fun equals_MalValue(a: MalValue, b: MalValue): bool { return true } } } - MalValue::Map(d) { match (b) { MalValue::Map(db) { - if d.size() != db.size() { - return false - } - for (var i = 0; i < d.keys.size; i++;) { - if !db.contains_key(d.keys[i]) || !equals_MalValue(d.values[i], db[d.keys[i]]) { - return false - } - } - return true - } } } MalValue::String(d) { match (b) { MalValue::String(db) { return d == db; } } } MalValue::Int(d) { match (b) { MalValue::Int(db) { return d == db; } } } MalValue::Symbol(d) { match (b) { MalValue::Symbol(db) { return d == db; } } } - MalValue::Keyword(d) { match (b) { MalValue::Keyword(db) { return d == db; } } } MalValue::Function(d) { match (b) { MalValue::Function(db) { return d == db; } } } MalValue::BuiltinFunction(d) { match (b) { MalValue::BuiltinFunction(db) { return d == db; } } } MalValue::Atom(d) { match (b) { MalValue::Atom(db) { return d == db; } } } @@ -149,36 +102,6 @@ fun equals_MalValue(a: MalValue, b: MalValue): bool { } return false } -fun is_keyword(v: MalValue): bool { - match (v) { - MalValue::Keyword(k) { - return true - } - } - return false -} -fun is_keyword_or_string(v: MalValue): bool { - match (v) { - MalValue::Keyword(k) { - return true - } - MalValue::String(s) { - return true - } - } - return false -} -fun get_keyword_or_string_text(v: MalValue): str { - match (v) { - MalValue::Keyword(k) { - return k - } - MalValue::String(s) { - return s - } - } - error("Tried to get_keyword_or_string_text on not a keyword or string!") -} fun is_list(v: MalValue): bool { match (v) { MalValue::List(l) { @@ -593,18 +516,6 @@ fun pr_str(v: MalValue, print_readably: bool): str { } return to_ret + "]" } - MalValue::Map(m) { - var to_ret = str("{") - for (var i = 0; i < m.keys.size; i++;) { - if (i != 0) { - to_ret += " " - } - to_ret += pr_str(m.keys[i], print_readably) - to_ret += str(" ") - to_ret += pr_str(m.values[i], print_readably) - } - return to_ret + "}" - } MalValue::Int(i) { return to_string(i) } @@ -630,9 +541,6 @@ fun pr_str(v: MalValue, print_readably: bool): str { MalValue::Symbol(s) { return s } - MalValue::Keyword(k) { - return str(":") + k - } MalValue::BuiltinFunction(f) { return str("builtin function") } @@ -692,17 +600,6 @@ fun eval_ast(env: *Env, ast: MalValue): MalResult { } return MalResult::Ok(MalValue::Vector(to_ret)) } - MalValue::Map(l) { - var to_ret = map() - for (var i = 0; i < l.keys.size; i++;) { - var mid = EVAL(env, l.values[i]) - if is_err(mid) { - return mid - } - to_ret.set(l.keys[i], get_value(mid)) - } - return MalResult::Ok(MalValue::Map(to_ret)) - } MalValue::Symbol(s) { return env->get(s) } @@ -951,7 +848,7 @@ fun main(argc: int, argv: **char): int { var atom = grammer.add_new_nonterminal("atom", vec(grammer.add_terminal("-?[0-9]+", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Int(string_to_num(input.slice(l,r)))); })), MalValue::Nil(), ret_0_sym) grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("\"([#-[]| |[]-~]|(\\\\)|(\\n)|(\\t)|(\\\*)|(\\0)| -|[ -!]|(\\\\\"))*\"", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { +|[ -!]|(\\\\\"))*\"", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { //" var to_ret = str() for (var i = l+1; i < r-1; i++;) { if input[i] == '\\' { @@ -968,9 +865,8 @@ fun main(argc: int, argv: **char): int { to_ret += input[i] } } - /*return MalResult::Ok(MalValue::String(input.slice(l+1,r-1)));*/ return MalResult::Ok(MalValue::String(to_ret)); - })), MalValue::Nil(), ret_0_sym) //" + })), MalValue::Nil(), ret_0_sym) grammer.add_to_nonterminal(atom, vec(grammer.add_terminal("-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|<|>)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>)*)", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { var s = input.slice(l,r) if s == "true" { @@ -983,7 +879,6 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(MalValue::Symbol(input.slice(l,r))); } })), MalValue::Nil(), ret_0_sym) - grammer.add_to_nonterminal(atom, vec(grammer.add_terminal(":([a-z]|[A-Z]|_)([a-z]|[A-Z]|_|[0-9])*", MalValue::Nil(), fun(_: ref MalValue, input: ref str, l: int, r: int): MalResult { return MalResult::Ok(MalValue::Keyword(input.slice(l,r))); })), MalValue::Nil(), ret_0_sym) var form = grammer.add_new_nonterminal("form", vec(atom), MalValue::Nil(), ret_0_sym) var space_forms = grammer.add_new_nonterminal("space_forms", vec(), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { @@ -1024,46 +919,6 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(MalValue::Vector(get_list(get_value(x[2])))) }) - var doubled_space_forms = grammer.add_new_nonterminal("doubled_space_forms", vec(), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { - return MalResult::Ok(MalValue::List(vec())) - }) - grammer.add_to_nonterminal(doubled_space_forms, vec(form, WS, form), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { - if is_err(x[0]) { - return x[0] - } - if is_err(x[2]) { - return x[2] - } - return MalResult::Ok(MalValue::List(vec(get_value(x[0]), get_value(x[2])))) - }) - grammer.add_to_nonterminal(doubled_space_forms, vec(form, WS, form, WS, doubled_space_forms), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { - if is_err(x[0]) { - return x[0] - } - if is_err(x[2]) { - return x[2] - } - if is_err(x[4]) { - return x[4] - } - return MalResult::Ok(MalValue::List(vec(get_value(x[0]), get_value(x[2])) + get_list(get_value(x[4])))) - }) - grammer.add_to_nonterminal(form, vec(grammer.add_terminal("{", MalValue::Nil(), ret_nil_term), - optional_WS, - doubled_space_forms, - optional_WS, - grammer.add_terminal("}", MalValue::Nil(), ret_nil_term)), MalValue::Nil(), fun(_: ref MalValue, x: ref vec): MalResult { - if is_err(x[2]) { - return x[2] - } - - var to_ret = map() - var values = get_list(get_value(x[2])) - for (var i = 0; i < values.size; i+=2;) { - to_ret.set(values[i], values[i+1]) - } - return MalResult::Ok(MalValue::Map(to_ret)) - }) grammer.set_start_symbol(form) @@ -1370,20 +1225,6 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(MalValue::Symbol(get_string(params[0]))) } })); - env->set(str("keyword?"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 1 { - return MalResult::Err(MalValue::String(str("keyword? called with wrong number of params"))) - } else { - return MalResult::Ok(bool_to_MalValue(is_keyword(params[0]))) - } - })); - env->set(str("keyword"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 1 || !is_keyword_or_string(params[0]) { - return MalResult::Err(MalValue::String(str("keyword called with wrong number or type of params"))) - } else { - return MalResult::Ok(MalValue::Keyword(get_keyword_or_string_text(params[0]))) - } - })); env->set(str("vector"), make_builtin_function(fun(params: vec): MalResult { return MalResult::Ok(MalValue::Vector(params)) })); @@ -1403,89 +1244,6 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(bool_to_MalValue(is_list_or_vec(params[0]))) } })); - env->set(str("hash-map"), make_builtin_function(fun(params: vec): MalResult { - return create_map(params) - })); - env->set(str("map?"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 1 { - return MalResult::Err(MalValue::String(str("map? called with wrong number of params"))) - } else { - return MalResult::Ok(bool_to_MalValue(is_map(params[0]))) - } - })); - env->set(str("assoc"), make_builtin_function(fun(params: vec): MalResult { - if params.size & 1 != 1 || !is_map(params[0]) { - return MalResult::Err(MalValue::String(str("assoc? called with wrong number or type of params"))) - } else { - var base = get_map(params[0]) - var new = create_map(params.slice(1,-1)) - if is_err(new) { - return new - } - var new_map = get_map(get_value(new)) - for (var i = 0; i < new_map.keys.size; i++;) { - base.set(new_map.keys[i], new_map.values[i]) - } - return MalResult::Ok(MalValue::Map(base)) - } - })); - env->set(str("dissoc"), make_builtin_function(fun(params: vec): MalResult { - if params.size < 2 || !is_map(params[0]) { - return MalResult::Err(MalValue::String(str("dissoc? called with wrong number or type of params"))) - } else { - var base = get_map(params[0]) - var remove = vec() - if params.size != 2 || !is_list(params[1]) { - remove = params.slice(1,-1) - } else { - remove = get_list(params[1]) - } - for (var i = 0; i < remove.size; i++;) { - if base.contains_key(remove[i]) { - base.remove(remove[i]) - } - } - return MalResult::Ok(MalValue::Map(base)) - } - })); - env->set(str("get"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 2 || !is_map(params[0]) || !is_keyword_or_string(params[1]) { - return MalResult::Err(MalValue::String(str("get called with wrong number or type of params"))) - } else { - var base = get_map(params[0]) - if base.contains_key(params[1]) { - return MalResult::Ok(base.get(params[1])) - } else { - return MalResult::Ok(MalValue::Nil()) - } - } - })); - env->set(str("contains?"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 2 || !is_map(params[0]) || !is_keyword_or_string(params[1]) { - return MalResult::Err(MalValue::String(str("contains? called with wrong number or type of params"))) - } else { - var base = get_map(params[0]) - if base.contains_key(params[1]) { - return MalResult::Ok(MalValue::True()) - } else { - return MalResult::Ok(MalValue::False()) - } - } - })); - env->set(str("keys"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 1 || !is_map(params[0]) { - return MalResult::Err(MalValue::String(str("keys called with wrong number or type of params"))) - } else { - return MalResult::Ok(MalValue::List(get_map(params[0]).keys)) - } - })); - env->set(str("vals"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 1 || !is_map(params[0]) { - return MalResult::Err(MalValue::String(str("vals called with wrong number or type of params"))) - } else { - return MalResult::Ok(MalValue::List(get_map(params[0]).values)) - } - })); env->set(str("readline"), make_builtin_function(fun(params: vec): MalResult { if params.size != 1 || !is_string(params[0]) { return MalResult::Err(MalValue::String(str("readline called with wrong number or type of params"))) @@ -1529,19 +1287,19 @@ fun main(argc: int, argv: **char): int { } })); env->set(str("add_grammer_rule"), make_builtin_function(fun(params: vec): MalResult { - if params.size != 3 || !is_keyword(params[0]) || !is_vector(params[1]) { + if params.size != 3 || !is_symbol(params[0]) || !is_vector(params[1]) { return MalResult::Err(MalValue::String(str("add_grammer_rule called with wrong number or type of params"))) } else { - var nonterminal_str = get_keyword_or_string_text(params[0]).slice(1,-1) + var nonterminal_str = get_symbol_text(params[0]) var rule = get_list_or_vec(params[1]) var int_rule = vec() for (var i = 0; i < rule.size; i++;) { if is_int(rule[i]) { int_rule.add(get_int(rule[i])) - } else if is_keyword(rule[i]) { - var sub_nonterminal_idx = grammer.nonterminal_names.find(get_keyword_or_string_text(rule[i]).slice(1,-1)) + } else if is_symbol(rule[i]) { + var sub_nonterminal_idx = grammer.nonterminal_names.find(get_symbol_text(rule[i])) if sub_nonterminal_idx == -1 { - return MalResult::Err(MalValue::String(str("Couldn't find nonterminal: ") + get_keyword_or_string_text(rule[i]).slice(1,-1))) + return MalResult::Err(MalValue::String(str("Couldn't find nonterminal: ") + get_symbol_text(rule[i]))) } var sub_nonterminal = -1*(sub_nonterminal_idx+1) int_rule.add(sub_nonterminal) @@ -1550,7 +1308,7 @@ fun main(argc: int, argv: **char): int { return MalResult::Ok(MalValue::String(input.slice(l,r))) })) } else { - return MalResult::Err(MalValue::String(str("add_grammer_rule called with not keyword, int, or string in rule"))) + return MalResult::Err(MalValue::String(str("add_grammer_rule called with not symbol, int, or string in rule"))) } } grammer.add_to_or_create_nonterminal(nonterminal_str, int_rule, params[2], fun(f: ref MalValue, x: ref vec): MalResult { @@ -1620,14 +1378,14 @@ fun main(argc: int, argv: **char): int { } })); // reader macros - rep(grammer, env, str("(add_grammer_rule :atom [\"'\" :form] (fn* (xs) (quasiquote (quote (unquote (nth xs 1))))))")) //' - rep(grammer, env, str("(add_grammer_rule :atom [\"`\" :form] (fn* (xs) (quasiquote (quasiquote (unquote (nth xs 1))))))")) - rep(grammer, env, str("(add_grammer_rule :atom [\"~\" :form] (fn* (xs) (list (quote unquote) (nth xs 1))))")) + rep(grammer, env, str("(add_grammer_rule (quote atom) [\"'\" (quote form)] (fn* (xs) (quasiquote (quote (unquote (nth xs 1))))))")) //' + rep(grammer, env, str("(add_grammer_rule 'atom [\"`\" 'form] (fn* (xs) (quasiquote (quasiquote (unquote (nth xs 1))))))")) + rep(grammer, env, str("(add_grammer_rule 'atom [\"~\" 'form] (fn* (xs) (list (quote unquote) (nth xs 1))))")) // the standard appears to be for splice-unquote to be , but unquote deref is a reasonable // sequence of characters and causes ambigious parses! So I chose the other common unquote symbol to be splice-unquote - rep(grammer, env, str("(add_grammer_rule :atom [\",\" :form] (fn* (xs) (list (quote splice-unquote) (nth xs 1))))")) + rep(grammer, env, str("(add_grammer_rule 'atom [\",\" 'form] (fn* (xs) (list (quote splice-unquote) (nth xs 1))))")) // let's use the new reader macros in another reader macro - rep(grammer, env, str("(add_grammer_rule :atom [\"@\" :form] (fn* (xs) `(deref ~(nth xs 1))))")) + rep(grammer, env, str("(add_grammer_rule 'atom [\"@\" 'form] (fn* (xs) `(deref ~(nth xs 1))))")) //" rep(grammer, env, str("(def! not (fn* (a) (if a false true)))")) rep(grammer, env, str("(def! load-file (fn* (f) (eval-read-string (slurp f))))"))