From 9caf220aa1e4b5711460f43ee9a0b0f1556c7029 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 21 Jul 2020 22:56:29 -0400 Subject: [PATCH] Added print / string stuff, meta and with-meta, and the old add_grammer_rule --- k_prime.krak | 180 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 5 deletions(-) diff --git a/k_prime.krak b/k_prime.krak index 873b121..d62569c 100644 --- a/k_prime.krak +++ b/k_prime.krak @@ -603,15 +603,23 @@ fun function_call(f: KPValue, params: ref vec, env: KPValue): KPResult return KPResult::Err(kpString(str("trying to apply not a combiner: ") + pr_str(f ,true))) } -fun print_wrapper(params: ref vec, sep: *char, print_readably: bool): str { +fun str_wrapper(params: ref vec, dynamic_env: *KPEnv, sep: *char, print_readably: bool): KPResult { var to_ret = str() for (var i = 0; i < params.size; i++;) { - to_ret += pr_str(params[i], print_readably) + var ip = EVAL(dynamic_env, params[i]) + if is_err(ip) { return ip; } + to_ret += pr_str(get_value(ip), print_readably) if i != params.size-1 { to_ret += sep } } - return to_ret + return KPResult::Ok(kpString(to_ret)) +} + +var tmp_idx: int = 0 +fun new_tmp(): str { + tmp_idx += 1 + return str("x") + tmp_idx } fun main(argc: int, argv: **char): int { @@ -725,7 +733,6 @@ fun main(argc: int, argv: **char): int { var to_ret.construct(dynamic_env, dynamic_env_name, parameters, is_variadic, params[2]) : KPCombiner return KPResult::Ok(nmMV(KPValue_int::Combiner(to_ret))) })); - env->set(str("eval"), make_builtin_combiner(str("eval"), fun(params: vec, dynamic_env: *KPEnv): KPResult { var evaled_params = vec() for (var i = 0; i < params.size; i++;) { @@ -933,7 +940,6 @@ fun main(argc: int, argv: **char): int { if is_err(b) { return b; } return KPResult::Ok(kpBool(!get_value(a).equals(get_value(b)))) })); - env->set(str("<"), make_builtin_combiner(str("<"), fun(params: vec, dynamic_env: *KPEnv): KPResult { if params.size != 2 { return KPResult::Err(kpString(str("Need 2 params to <"))) @@ -1014,6 +1020,168 @@ fun main(argc: int, argv: **char): int { return KPResult::Ok(kpFalse()) })); + env->set(str("pr-str"), make_builtin_combiner(str("pr-str"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + return str_wrapper(params, dynamic_env, " ", true) + })); + env->set(str("str"), make_builtin_combiner(str("str"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + return str_wrapper(params, dynamic_env, "", false) + })); + env->set(str("prn"), make_builtin_combiner(str("prn"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + var to_print = str_wrapper(params, dynamic_env, " ", true) + if is_err(to_print) { return to_print; } + println(get_value(to_print).get_string()) + return KPResult::Ok(kpNil()) + })); + env->set(str("println"), make_builtin_combiner(str("println"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + var to_print = str_wrapper(params, dynamic_env, " ", false) + if is_err(to_print) { return to_print; } + println(get_value(to_print).get_string()) + return KPResult::Ok(kpNil()) + })); + + env->set(str("meta"), make_builtin_combiner(str("meta"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + if params.size != 1 { + return KPResult::Err(kpString(str("meta called with not one argument"))) + } else { + var or = EVAL(dynamic_env, params[0]) + if is_err(or) { return or; } + var o = get_value(or) + if o.meta != null() { + return KPResult::Ok(*o.meta) + } else { + return KPResult::Ok(kpNil()) + } + } + })); + env->set(str("with-meta"), make_builtin_combiner(str("with-meta"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + if params.size != 2 { + return KPResult::Err(kpString(str("with-meta called with not two arguments"))) + } else { + var or = EVAL(dynamic_env, params[0]) + if is_err(or) { return or; } + var mr = EVAL(dynamic_env, params[1]) + if is_err(mr) { return mr; } + var new_meta = new() + new_meta->copy_construct(&get_value(mr)) + var new_value = get_value(or).deep_clone(); + new_value.meta = new_meta + return KPResult::Ok(new_value) + } + })); + + // self-modifying grammar + env->set(str("add_terminal"), make_builtin_combiner(str("add_terminal"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + if params.size != 2 { + return KPResult::Err(kpString(str("add_terminal called with wrong number (not 2) params"))) + } else { + var namer = EVAL(dynamic_env, params[0]); + if is_err(namer) { return namer; } + var namev = get_value(namer) + if !namev.is_string() { + return KPResult::Err(kpString(str("add_terminal called with wrong number (not 2) params"))) + } + var funcr = EVAL(dynamic_env, params[1]); + if is_err(funcr) { return funcr; } + return KPResult::Ok(kpInt(grammar.add_terminal(namev.get_string(), get_value(funcr), fun(f: ref KPValue, input: ref str, l: int, r: int): KPResult { + return function_call(f, vec(kpString(input.slice(l,r))), kpEnv(env)) + }))) + } + })); + var add_grammer_rule_helper: fun(str, vec, KPValue, fun(ref KPValue, ref vec): KPResult): KPResult = fun(nonterminal_str: str, rule: vec, data: KPValue, f: fun(ref KPValue, ref vec): KPResult): KPResult { + var int_rule = vec() + for (var i = 0; i < rule.size; i++;) { + if rule[i].is_int() { + int_rule.add(rule[i].get_int()) + } else if rule[i].is_symbol() { + var sub_nonterminal_idx = grammar.nonterminal_names.find(rule[i].get_symbol_text()) + if sub_nonterminal_idx == -1 { + return KPResult::Err(kpString(str("Couldn't find nonterminal: ") + rule[i].get_symbol_text())) + } + var sub_nonterminal = -1*(sub_nonterminal_idx+1) + int_rule.add(sub_nonterminal) + } else if rule[i].is_string() { + int_rule.add(grammar.add_terminal(rule[i].get_string(), kpNil(), fun(f: ref KPValue, input: ref str, l: int, r: int): KPResult { + return KPResult::Ok(kpString(input.slice(l,r))) + })) + } else if rule[i].is_vector() { + // A sequence! + var sub_rule_names = nonterminal_str + "_seq_" + new_tmp() + var inner_rule = add_grammer_rule_helper(sub_rule_names, rule[i].get_vector_rc().get(), kpNil(), fun(_: ref KPValue, seq: ref vec): KPResult { + var to_ret = vec() + for (var i = 0; i < seq.size; i++;) { + if is_err(seq[i]) { + return seq[i] + } + to_ret.add(get_value(seq[i])) + } + return KPResult::Ok(kpVector(to_ret)) + }) + if is_err(inner_rule) { + return inner_rule + } + int_rule.add(get_value(inner_rule).get_int()) + } else { + match (rule[i].internal) { + KPValue_int::BuiltinCombiner(f) { + if f.name == "+" || f.name == "*" { + if int_rule.size == 0 { + return KPResult::Err(kpString(str("add_grammar_rule has + or * in first position, with nothing to repeat"))) + } + var current = int_rule.last() + var sub_rule_names = nonterminal_str + "_" + new_tmp() + var new = grammar.add_to_or_create_nonterminal(sub_rule_names + "_one_or_more", vec(current), kpNil(), fun(f: ref KPValue, x: ref vec): KPResult { + if is_err(x[0]) { return x[0]; } + return KPResult::Ok(kpVector(vec(get_value(x[0])))) + }) + grammar.add_to_nonterminal(new, vec(current, new), kpNil(), fun(f: ref KPValue, x: ref vec): KPResult { + if is_err(x[0]) { return x[0]; } + if is_err(x[1]) { return x[1]; } + return KPResult::Ok(kpVector(vec(get_value(x[0])) + get_value(x[1]).get_vector_rc().get())) + }) + if f.name == "*" { + new = grammar.add_to_or_create_nonterminal(sub_rule_names + "_zero_or_more", vec(new), kpNil(), fun(f: ref KPValue, x: ref vec): KPResult { + if is_err(x[0]) { return x[0]; } + return KPResult::Ok(get_value(x[0])) + }) + grammar.add_to_nonterminal(new, vec(), kpNil(), fun(f: ref KPValue, x: ref vec): KPResult { + return KPResult::Ok(kpVector(vec())) + }) + } + int_rule.last() = new + continue + } + } + } + return KPResult::Err(kpString(str("add_grammar_rule called with not symbol, int, or string in rule"))) + } + } + return KPResult::Ok(kpInt(grammar.add_to_or_create_nonterminal(nonterminal_str, int_rule, data, f))) + } + env->set(str("add_grammar_rule"), make_builtin_combiner(str("add_grammar_rule"), fun(params: vec, dynamic_env: *KPEnv): KPResult { + var params_evaled = vec() + for (var i = 0; i < params.size; i++;) { + var ip = EVAL(dynamic_env, params[i]) + if is_err(ip) { return ip; } + params_evaled.add(get_value(ip)) + } + if params_evaled.size != 3 || !params_evaled[0].is_symbol() || !params_evaled[1].is_vector() { + return KPResult::Err(kpString(str("add_grammar_rule called with wrong number or type of params_evaled"))) + } else { + var nonterminal_str = params_evaled[0].get_symbol_text() + var rule = params_evaled[1].get_vector_rc().get() + return add_grammer_rule_helper(nonterminal_str, rule, params_evaled[2], fun(f: ref KPValue, x: ref vec): KPResult { + var params = vec() + for (var i = 0; i < x.size; i++;) { + if is_err(x[i]) { + return x[i] + } + params.add(get_value(x[i])) + } + return function_call(f, params, kpEnv(env)) + }) + } + })); + // self-implementation fun println(rep(grammar, env, str("(set! quote (vau _ (x) x))"))) println(rep(grammar, env, str("(set! let1 (vau de (s v b) (eval (vector (vector vau (quote _) (vector s) b) (eval v de)) de)))"))) @@ -1023,6 +1191,8 @@ fun main(argc: int, argv: **char): int { println(rep(grammar, env, str("(set! lambda (vau se (p b) (let1 f (eval (vector vau (quote _) p b) se) (vau de (& op) (apply f (map (vau dde (ip) (eval (eval ip dde) de)) op))))))"))) println(rep(grammar, env, str("(set! fun (vau se (n p b) (eval (vector set! n (vector lambda p b)) se)))"))) + println(rep(grammar, env, str("(add_grammar_rule (quote form) (quote ( \"'\" optional_WS form )) (vau _ (_ _ f) (vector quote f)))"))) + if argc == 3 && str(argv[1]) == "-C" { error("-C not implemented")