implement cond vector len idx concat - =, all as builtins, as an excercise implemented quote let1 apply rest map lambda fun, all in k_prime itself, proving you don't absolutly need wrap or apply as builtins (eval and vector manipulation functions suffice)

This commit is contained in:
Nathan Braswell
2020-07-13 00:48:01 -04:00
parent 38bf5edc35
commit 41c02d43ff

View File

@@ -66,6 +66,8 @@ obj KPEnv (Object) {
if (env != null<KPEnv>()) { if (env != null<KPEnv>()) {
return KPResult::Ok(env->data.get(key)) return KPResult::Ok(env->data.get(key))
} else { } else {
println(key + "wasn't found in:")
println(to_string())
return KPResult::Err(kpString(str("'") + key + "' not found")) return KPResult::Err(kpString(str("'") + key + "' not found"))
} }
} }
@@ -380,7 +382,7 @@ fun kpTrue(): KPValue {
fun kpFalse(): KPValue { fun kpFalse(): KPValue {
return nmMV(KPValue_int::False()) return nmMV(KPValue_int::False())
} }
fun bool_to_KPValue(b: bool): KPValue { fun kpBool(b: bool): KPValue {
if b { if b {
return nmMV(KPValue_int::True()) return nmMV(KPValue_int::True())
} else { } else {
@@ -446,7 +448,6 @@ fun get_err(r: KPResult): KPValue {
return e return e
} }
} }
/*return kpSymbol(str("get-err-not-error"))*/
error("get-err-not-error") error("get-err-not-error")
} }
fun get_value(r: KPResult): KPValue { fun get_value(r: KPResult): KPValue {
@@ -455,7 +456,6 @@ fun get_value(r: KPResult): KPValue {
return v return v
} }
} }
/*return kpSymbol(str("get-value-is-error"))*/
error("get-value-is-error") error("get-value-is-error")
} }
fun pr_str(v: KPValue, print_readably: bool): str { fun pr_str(v: KPValue, print_readably: bool): str {
@@ -500,7 +500,7 @@ fun pr_str(v: KPValue, print_readably: bool): str {
} }
} }
KPValue_int::BuiltinCombiner(f) { KPValue_int::BuiltinCombiner(f) {
return str("builtin combiner") return "builtin_combiner_" + f.name
} }
KPValue_int::Combiner(f) { KPValue_int::Combiner(f) {
return str("combiner") return str("combiner")
@@ -542,11 +542,11 @@ fun EVAL(env: *KPEnv, ast: KPValue): KPResult {
if (l.get().size == 0) { if (l.get().size == 0) {
return KPResult::Err(kpString(str("Eval a zero length vector"))) return KPResult::Err(kpString(str("Eval a zero length vector")))
} else { } else {
// this breaks tco?
var combiner = EVAL(env, l.get()[0]) var combiner = EVAL(env, l.get()[0])
if is_err(combiner) { if is_err(combiner) {
return combiner return combiner
} }
/*println("About to call combiner evaled from " + pr_str(l.get()[0], true))*/
match (get_value(combiner).internal) { match (get_value(combiner).internal) {
KPValue_int::BuiltinCombiner(f) { KPValue_int::BuiltinCombiner(f) {
return f.call(l.get().slice(1,-1), kpEnv(env)) return f.call(l.get().slice(1,-1), kpEnv(env))
@@ -761,13 +761,75 @@ fun main(argc: int, argv: **char): int {
return KPResult::Ok(kpNil()) return KPResult::Ok(kpNil())
})); }));
env->set(str("+"), make_builtin_combiner(str("+"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult { env->set(str("cond"), make_builtin_combiner(str("cond"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
var to_ret = 0 if (params.size % 2) != 0 {
return KPResult::Err(kpString(str("Need even number of params to cond")))
}
for (var i = 0; i < params.size; i+=2;) {
var ip = EVAL(dynamic_env, params[i])
if is_err(ip) {
return ip
}
if get_value(ip).is_truthy() {
return EVAL(dynamic_env, params[i+1])
}
}
return KPResult::Ok(kpNil())
}));
env->set(str("vector"), make_builtin_combiner(str("vector"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
var evaled_params = vec<KPValue>()
for (var i = 0; i < params.size; i++;) { for (var i = 0; i < params.size; i++;) {
var ip = EVAL(dynamic_env, params[i]) var ip = EVAL(dynamic_env, params[i])
if is_err(ip) { if is_err(ip) {
return ip return ip
} }
evaled_params.add(get_value(ip))
}
return KPResult::Ok(kpVector(evaled_params))
}));
env->set(str("len"), make_builtin_combiner(str("len"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
if params.size != 1 {
return KPResult::Err(kpString(str("Need 1 param to len")))
}
var v = EVAL(dynamic_env, params[0]);
if is_err(v) { return v; }
return KPResult::Ok(kpInt(get_value(v).get_vector_rc().get().size))
}));
env->set(str("idx"), make_builtin_combiner(str("idx"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
if params.size != 2 {
return KPResult::Err(kpString(str("Need 2 params to idx")))
}
var v = EVAL(dynamic_env, params[0]);
if is_err(v) { return v; }
var vv = get_value(v)
if !vv.is_vector() { return KPResult::Err(kpString(str("Param 1 to idx is not vector"))); }
var i = EVAL(dynamic_env, params[1]);
if is_err(i) { return i; }
var iv = get_value(i)
if !iv.is_int() { return KPResult::Err(kpString(str("Param 2 to idx is not int"))); }
return KPResult::Ok(vv.get_vector_rc().get()[iv.get_int()])
}));
env->set(str("concat"), make_builtin_combiner(str("concat"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
var to_ret = vec<KPValue>()
for (var i = 0; i < params.size; i++;) {
var ip = EVAL(dynamic_env, params[i])
if is_err(ip) {
return ip
}
var v = get_value(ip)
if !v.is_vector() { return KPResult::Err(kpString(str("Param ") + i + " to concat is not vector")); }
to_ret += v.get_vector_rc().get()
}
return KPResult::Ok(kpVector(to_ret))
}));
env->set(str("+"), make_builtin_combiner(str("+"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
var to_ret = 0
for (var i = 0; i < params.size; i++;) {
var ip = EVAL(dynamic_env, params[i])
if is_err(ip) { return ip; }
match (get_value(ip).internal) { match (get_value(ip).internal) {
KPValue_int::Int(v) { KPValue_int::Int(v) {
to_ret += v to_ret += v
@@ -778,16 +840,49 @@ fun main(argc: int, argv: **char): int {
} }
return KPResult::Ok(kpInt(to_ret)) return KPResult::Ok(kpInt(to_ret))
})); }));
env->set(str("-"), make_builtin_combiner(str("-"), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
var to_ret = 0
for (var i = 0; i < params.size; i++;) {
var ip = EVAL(dynamic_env, params[i])
if is_err(ip) { return ip; }
match (get_value(ip).internal) {
KPValue_int::Int(v) {
if i == 0 {
to_ret += v
} else {
to_ret -= v
}
continue
}
}
return KPResult::Err(kpString(str("called - with not an int: ") + pr_str(get_value(ip), false)))
}
return KPResult::Ok(kpInt(to_ret))
}));
env->set(str("="), make_builtin_combiner(str("="), fun(params: vec<KPValue>, dynamic_env: *KPEnv): KPResult {
if params.size != 2 {
return KPResult::Err(kpString(str("Need 2 params to =")))
}
var a = EVAL(dynamic_env, params[0]);
if is_err(a) { return a; }
var b = EVAL(dynamic_env, params[1]);
if is_err(b) { return b; }
return KPResult::Ok(kpBool(get_value(a).equals(get_value(b))))
}));
// 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)))")))
println(rep(grammar, env, str("(set! apply (vau de (f p) (eval (concat (vector (eval f de)) (eval p de)) de)))")))
println(rep(grammar, env, str("(set! rest (vau de (rl) (apply (vau _ (f & r) r) (eval rl de))))")))
println(rep(grammar, env, str("(set! map (vau de (f ml) (let1 f (eval f de) (let1 iml (eval ml de) (cond (= 0 (len iml)) (vector) true (concat (vector (f (idx iml 0))) (map f (rest iml))))))))")))
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)))")))
if argc == 3 && str(argv[1]) == "-C" { if argc == 3 && str(argv[1]) == "-C" {
error("-C not implemented") error("-C not implemented")
//env->set(str("*ARGV*"), kpNil())
//var evaled = ERS(vec(kpString(str(argv[2]))))
//if is_err(evaled) {
// printlnerr(str("Exception: ") + pr_str(get_err(evaled), true))
//} else {
// println("Result: " + pr_str(get_value(evaled), true))
//}
} else if argc >= 2 { } else if argc >= 2 {
var params = vec<KPValue>() var params = vec<KPValue>()
for (var i = 2; i < argc; i++;) { for (var i = 2; i < argc; i++;) {