Add names to BuiltinFunctions so they can be compiled when used by reference, much less hacky and allows our new BF version to be compiled

This commit is contained in:
Nathan Braswell
2020-05-10 21:33:47 -04:00
parent f10630c66c
commit 9aeadfc224
2 changed files with 209 additions and 94 deletions

56
bf.kp
View File

@@ -83,6 +83,58 @@
((meta b))
(println b)))
; Use the power of GLL reader macros to implement
; BF support
; Define our tokens as BF atoms
; Ugly b/c using 1-length vectors as atoms
(add_grammer_rule 'bfs_atom ["<"] (fn* (xs) '(set-nth! cursor 0 (- (nth cursor 0) 1))))
(add_grammer_rule 'bfs_atom [">"] (fn* (xs) '(set-nth! cursor 0 (+ (nth cursor 0) 1))))
(add_grammer_rule 'bfs_atom ["\\+"] (fn* (xs) '(set-nth! tape (nth cursor 0) (+ (nth tape (nth cursor 0)) 1))))
(add_grammer_rule 'bfs_atom ["-"] (fn* (xs) '(set-nth! tape (nth cursor 0) (- (nth tape (nth cursor 0)) 1))))
(add_grammer_rule 'bfs_atom [","] (fn* (xs) '(let* (value (nth input (nth inptr 0))) (do (set-nth! inptr 0 (+ 1 (nth inptr 0))) (do (set-nth! tape (nth cursor 0) value))))))
(add_grammer_rule 'bfs_atom ["."] (fn* (xs) '(set-nth! output 0 (cons (nth tape (nth cursor 0)) (nth output 0)))))
; Define strings of BF atoms
(add_grammer_rule 'non_empty_bfs_list ['bfs_atom] (fn* (xs) (vector (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 loop as an atom
(add_grammer_rule 'bfs_atom ["\\[" 'bfs_list "]"] (fn* (xs)
`(let* (f (fn* (f)
(if (= 0 (nth tape (nth cursor 0)))
nil
(do ,(nth xs 1) (f f)))))
(f f))))
; Top level BFS rule
(add_grammer_rule 'bfs ['bfs_list] (fn* (xs) (nth xs 0)))
; For now, stick BFS rule inside an unambigious BFS block
; and add compilation/implementation
; Note that this compilation into the underlying Lisp
; happens at macro evaluation time. If this code were
; to be compiled to C, it would be compiled all the way
; to C code with no trace of the original BF code.
(add_grammer_rule 'form ["bf" 'optional_WS "{" 'optional_WS 'bfs 'optional_WS "}"]
(fn* (xs)
`(fn* (input)
(let* (
tape (vector 0 0 0 0 0)
cursor (vector 0)
inptr (vector 0)
output (vector (vector))
)
(do ,(nth xs 4) (nth output 0))))))
; Let's try it out! This BF program prints the input 3 times
;(println (bf { ,>+++[<.>-] } [1337]))
;(println "BF: " (bf { ++-. } [1337]))
(def! our_obj (with-meta [0] (fn* () (set-nth! our_obj 0 (+ 1 (nth our_obj 0))))))
(def! main (fn* () (let* ( a 7
@@ -106,6 +158,7 @@
(println our_obj)
((meta our_obj))
(println our_obj)
(println (bf { ,>+++[<.>-] } [1337]))
a)))
)))))
(do
@@ -113,6 +166,3 @@
(main)
(println "done interp-main")
nil)

View File

@@ -370,15 +370,19 @@ obj Env (Object) {
}
}
obj MalBuiltinFunction (Object) {
var name: str
var fp: fun(vec<MalValue>): MalResult
fun construct(fp: fun(vec<MalValue>): MalResult): *MalBuiltinFunction {
fun construct(name: ref str, fp: fun(vec<MalValue>): MalResult): *MalBuiltinFunction {
this->name.copy_construct(&name)
this->fp = fp
return this
}
fun copy_construct(old: *MalBuiltinFunction): void {
this->fp = old->fp
this->name.copy_construct(&old->name)
}
fun destruct(): void {
this->name.destruct()
}
fun operator=(other:ref MalBuiltinFunction):void {
destruct()
@@ -391,8 +395,8 @@ obj MalBuiltinFunction (Object) {
return fp(params)
}
}
fun make_builtin_function(f: fun(vec<MalValue>): MalResult): MalValue {
var to_ret.construct(f): MalBuiltinFunction
fun make_builtin_function(name: str, f: fun(vec<MalValue>): MalResult): MalValue {
var to_ret.construct(name, f): MalBuiltinFunction
return nmMV(MalValue_int::BuiltinFunction(to_ret))
}
obj MalFunction (Object) {
@@ -892,7 +896,7 @@ fun main(argc: int, argv: **char): int {
var env = new<Env>()->construct()
env->set(str("+"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("+"), make_builtin_function(str("+"), fun(params: vec<MalValue>): MalResult {
var to_ret = 0
for (var i = 0; i < params.size; i++;) {
match (params[i].internal) {
@@ -905,7 +909,7 @@ fun main(argc: int, argv: **char): int {
}
return MalResult::Ok(malInt(to_ret))
}));
env->set(str("-"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("-"), make_builtin_function(str("-"), fun(params: vec<MalValue>): MalResult {
var to_ret = 0
for (var i = 0; i < params.size; i++;) {
match (params[i].internal) {
@@ -922,7 +926,7 @@ fun main(argc: int, argv: **char): int {
}
return MalResult::Ok(malInt(to_ret))
}));
env->set(str("*"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("*"), make_builtin_function(str("*"), fun(params: vec<MalValue>): MalResult {
var to_ret = 1
for (var i = 0; i < params.size; i++;) {
match (params[i].internal) {
@@ -935,7 +939,7 @@ fun main(argc: int, argv: **char): int {
}
return MalResult::Ok(malInt(to_ret))
}));
env->set(str("/"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("/"), make_builtin_function(str("/"), fun(params: vec<MalValue>): MalResult {
var to_ret = 1
for (var i = 0; i < params.size; i++;) {
match (params[i].internal) {
@@ -952,105 +956,105 @@ fun main(argc: int, argv: **char): int {
}
return MalResult::Ok(malInt(to_ret))
}));
env->set(str("="), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("="), make_builtin_function(str("="), fun(params: vec<MalValue>): MalResult {
if params.size != 2 {
return MalResult::Err(malString(str("= with not two parameters")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].equals(params[1])))
}
}));
env->set(str("<"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("<"), make_builtin_function(str("<"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_int() || !params[1].is_int() {
return MalResult::Err(malString(str("< with not two numbers")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].get_int() < params[1].get_int()))
}
}));
env->set(str("<="), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("<="), make_builtin_function(str("<="), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_int() || !params[1].is_int() {
return MalResult::Err(malString(str("<= with not two numbers")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].get_int() <= params[1].get_int()))
}
}));
env->set(str(">"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str(">"), make_builtin_function(str(">"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_int() || !params[1].is_int() {
return MalResult::Err(malString(str("> with not two numbers")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].get_int() > params[1].get_int()))
}
}));
env->set(str(">="), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str(">="), make_builtin_function(str(">="), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_int() || !params[1].is_int() {
return MalResult::Err(malString(str(">= with not two numbers")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].get_int() >= params[1].get_int()))
}
}));
env->set(str("str"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("str"), make_builtin_function(str("str"), fun(params: vec<MalValue>): MalResult {
return MalResult::Ok(malString(print_wrapper(params, "", false)))
}));
env->set(str("prn"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("prn"), make_builtin_function(str("prn"), fun(params: vec<MalValue>): MalResult {
if params.size == 0 {
return MalResult::Err(malString(str("Called prn with 0 parameters")))
}
println(pr_str(params[0], true))
return MalResult::Ok(malNil())
}));
env->set(str("pr-str"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("pr-str"), make_builtin_function(str("pr-str"), fun(params: vec<MalValue>): MalResult {
return MalResult::Ok(malString(print_wrapper(params, " ", true)))
}));
env->set(str("prn"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("prn"), make_builtin_function(str("prn"), fun(params: vec<MalValue>): MalResult {
println(print_wrapper(params, " ", true))
return MalResult::Ok(malNil())
}));
env->set(str("println"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("println"), make_builtin_function(str("println"), fun(params: vec<MalValue>): MalResult {
println(print_wrapper(params, " ", false))
return MalResult::Ok(malNil())
}));
env->set(str("empty?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("empty?"), make_builtin_function(str("empty?"), fun(params: vec<MalValue>): MalResult {
if params.size == 0 || !params[0].is_vector() {
return MalResult::Err(malString(str("first parameter of empty? is not a list")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].get_vector_rc().get().size == 0))
}
}));
env->set(str("count"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("count"), make_builtin_function(str("count"), fun(params: vec<MalValue>): MalResult {
if params.size == 0 || !params[0].is_vector() {
return MalResult::Err(malString(str("first parameter of count is not a list")))
} else {
return MalResult::Ok(malInt(params[0].get_vector_rc().get().size))
}
}));
env->set(str("read-string"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("read-string"), make_builtin_function(str("read-string"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_string() {
return MalResult::Err(malString(str("read-string with not a single string")))
} else {
return READ(grammer, params[0].get_string())
}
}));
env->set(str("slurp"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("slurp"), make_builtin_function(str("slurp"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_string() {
return MalResult::Err(malString(str("slurp with not a single string")))
} else {
return MalResult::Ok(malString(read_file(params[0].get_string())))
}
}));
env->set(str("eval"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("eval"), make_builtin_function(str("eval"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("eval with wrong number of params")))
} else {
return EVAL(env, params[0])
}
}));
env->set(str("cons"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("cons"), make_builtin_function(str("cons"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[1].is_vector() {
return MalResult::Err(malString(str("cons called with wrong number of params or second not an list/vec")))
} else {
return MalResult::Ok(malVector(vec(params[0]) + params[1].get_vector_rc().get()))
}
}));
env->set(str("concat"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("concat"), make_builtin_function(str("concat"), fun(params: vec<MalValue>): MalResult {
var to_ret = vec<MalValue>()
for (var i = 0; i < params.size; i++;) {
if !params[i].is_vector() {
@@ -1060,7 +1064,7 @@ fun main(argc: int, argv: **char): int {
}
return MalResult::Ok(malVector(to_ret))
}));
env->set(str("nth"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("nth"), make_builtin_function(str("nth"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_vector() || !params[1].is_int() {
return MalResult::Err(malString(str("nth called with wrong number or type of params")))
} else {
@@ -1072,7 +1076,7 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(list.get()[idx])
}
}));
env->set(str("set-nth!"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("set-nth!"), make_builtin_function(str("set-nth!"), fun(params: vec<MalValue>): MalResult {
if params.size != 3 || !params[0].is_vector() || !params[1].is_int() {
return MalResult::Err(malString(str("set-nth! called with wrong number or type of params")))
} else {
@@ -1085,7 +1089,7 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(malNil())
}
}));
env->set(str("first"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("first"), make_builtin_function(str("first"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_vector() {
return MalResult::Err(malString(str("first called with wrong number or type of params") + pr_str(params[0], true)))
} else {
@@ -1096,7 +1100,7 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(list.get()[0])
}
}));
env->set(str("rest"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("rest"), make_builtin_function(str("rest"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_vector() {
return MalResult::Err(malString(str("rest called with wrong number or type of params")))
} else {
@@ -1107,14 +1111,14 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(malVector(list.get().slice(1,-1)))
}
}));
env->set(str("throw"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("throw"), make_builtin_function(str("throw"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("throw called with wrong number or type of params")))
} else {
return MalResult::Err(params[0])
}
}));
env->set(str("apply"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("apply"), make_builtin_function(str("apply"), fun(params: vec<MalValue>): MalResult {
if params.size < 2 || !params[params.size-1].is_vector() {
return MalResult::Err(malString(str("apply called with wrong number or type of params")))
} else {
@@ -1122,7 +1126,7 @@ fun main(argc: int, argv: **char): int {
return function_call(params[0], inner_params)
}
}));
env->set(str("map"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("map"), make_builtin_function(str("map"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[1].is_vector() {
return MalResult::Err(malString(str("map called with wrong number or type of params")))
} else {
@@ -1138,31 +1142,31 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(malVector(to_ret))
}
}));
env->set(str("symbol?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("symbol?"), make_builtin_function(str("symbol?"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("symbol? called with wrong number of params")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].is_symbol()))
}
}));
env->set(str("symbol"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("symbol"), make_builtin_function(str("symbol"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_string() {
return MalResult::Err(malString(str("symbol called with wrong number or type of params")))
} else {
return MalResult::Ok(malSymbol(params[0].get_string()))
}
}));
env->set(str("vector"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("vector"), make_builtin_function(str("vector"), fun(params: vec<MalValue>): MalResult {
return MalResult::Ok(malVector(params))
}));
env->set(str("vector?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("vector?"), make_builtin_function(str("vector?"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("vector? called with wrong number of params")))
} else {
return MalResult::Ok(bool_to_MalValue(params[0].is_vector()))
}
}));
env->set(str("sequential?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("sequential?"), make_builtin_function(str("sequential?"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("sequential? called with wrong number of params")))
} else if params[0].is_nil() {
@@ -1171,7 +1175,7 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(bool_to_MalValue(params[0].is_vector()))
}
}));
env->set(str("readline"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("readline"), make_builtin_function(str("readline"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 || !params[0].is_string() {
return MalResult::Err(malString(str("readline called with wrong number or type of params")))
} else {
@@ -1182,7 +1186,7 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(malString(entered))
}
}));
env->set(str("meta"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("meta"), make_builtin_function(str("meta"), fun(params: vec<MalValue>): MalResult {
if params.size != 1 {
return MalResult::Err(malString(str("meta called with not one argument")))
} else {
@@ -1193,7 +1197,7 @@ fun main(argc: int, argv: **char): int {
}
}
}));
env->set(str("with-meta"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("with-meta"), make_builtin_function(str("with-meta"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 {
return MalResult::Err(malString(str("with-meta called with not two arguments")))
} else {
@@ -1204,14 +1208,14 @@ fun main(argc: int, argv: **char): int {
return MalResult::Ok(new_value)
}
}));
env->set(str("fn?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("fn?"), make_builtin_function(str("fn?"), fun(params: vec<MalValue>): MalResult {
return MalResult::Err(malString(str("not implemented")))
}));
env->set(str("string?"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("string?"), make_builtin_function(str("string?"), fun(params: vec<MalValue>): MalResult {
return MalResult::Err(malString(str("not implemented")))
}));
// self-modifying grammer
env->set(str("add_terminal"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("add_terminal"), make_builtin_function(str("add_terminal"), fun(params: vec<MalValue>): MalResult {
if params.size != 2 || !params[0].is_string() {
return MalResult::Err(malString(str("add_terminal called with wrong number or type of params")))
} else {
@@ -1220,7 +1224,7 @@ fun main(argc: int, argv: **char): int {
})))
}
}));
env->set(str("add_grammer_rule"), make_builtin_function(fun(params: vec<MalValue>): MalResult {
env->set(str("add_grammer_rule"), make_builtin_function(str("add_grammer_rule"), fun(params: vec<MalValue>): MalResult {
if params.size != 3 || !params[0].is_symbol() || !params[1].is_vector() {
return MalResult::Err(malString(str("add_grammer_rule called with wrong number or type of params")))
} else {
@@ -1306,7 +1310,7 @@ fun main(argc: int, argv: **char): int {
return current_ret
}
}
env->set(str("eval-read-string"), make_builtin_function(ERS));
env->set(str("eval-read-string"), make_builtin_function(str("eval-read-string"), ERS));
// reader macros
/*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 (quote atom) (vector \"'\" (quote form)) (fn* (xs) (quasiquote (quote (unquote (nth xs 1))))))")) //'
@@ -1315,15 +1319,15 @@ fun main(argc: int, argv: **char): int {
rep(grammer, env, str("(add_grammer_rule 'form (vector \"\\\\[\" 'optional_WS 'space_forms 'optional_WS \"\\\\]\") (fn* (xs) (quasiquote (vector (splice-unquote (nth xs 2))))))")) //'
// now we can use ' for the rest
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 'atom [\"~\" 'form] (fn* (xs) (vector (quote unquote) (nth xs 1))))"))
// the standard appears to be for splice-unquote to be <symbol-for-unqoute><symbol-for-deref>, 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) (vector (quote splice-unquote) (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))))"))
rep(grammer, env, str("(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)))))))"))
rep(grammer, env, str("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (vector 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"))
rep(grammer, env, str("(def! nil? (fn* (a) (= nil a)))"))
var params = vec<MalValue>()
if argc == 3 && str(argv[1]) == "-C" {
@@ -1339,7 +1343,11 @@ fun main(argc: int, argv: **char): int {
params.add(malString(str(argv[i])))
}
env->set(str("*ARGV*"), malVector(params))
println(rep(grammer, env, str("(load-file \"") + argv[1] + "\")"))
var eval_result_str = rep(grammer, env, str("(load-file \"") + argv[1] + "\")")
println(eval_result_str)
if eval_result_str.slice(0,11) == "Exception: " {
error("aborting compile")
}
// check for compile
var main = env->get(str("main"))
if !is_err(main) {
@@ -1476,6 +1484,39 @@ fun main(argc: int, argv: **char): int {
}
closure _set_nth_closure = (closure){ _set_nth_impl, NULL};
size_t _cons_impl(size_t* _, size_t num, size_t* args) {
check_num_params(num, 2, "cons");
check_vector(args[1], "cons");
size_t* old_vec = (size_t*)(args[1]>>3);
size_t new_size = old_vec[1] + 1;
size_t *vec = malloc(sizeof(size_t)*(new_size + 2));
vec[0] = 0x2F;
vec[1] = new_size;
vec[2] = args[0];
for (int i = 0; i < old_vec[1]; i++)
vec[i+3] = old_vec[i+2];
return ((((size_t)vec)<<3)|0x2);
}
closure _cons_closure = (closure){ _cons_impl, NULL};
size_t _concat_impl(size_t* _, size_t num, size_t* args) {
check_num_params(num, 2, "concat");
check_vector(args[0], "concat");
check_vector(args[1], "concat");
size_t* vec1 = (size_t*)(args[0]>>3);
size_t* vec2 = (size_t*)(args[1]>>3);
size_t new_size = vec1[1] + vec2[1];
size_t *vec = malloc(sizeof(size_t)*(new_size + 2));
vec[0] = 0x2F;
vec[1] = new_size;
for (int i = 0; i < vec1[1]; i++)
vec[i+2] = vec1[i+2];
for (int i = 0; i < vec2[1]; i++)
vec[vec1[1]+i+2] = vec1[i+2];
return ((((size_t)vec)<<3)|0x2);
}
closure _concat_closure = (closure){ _concat_impl, NULL};
size_t _with_meta_impl(size_t* _, size_t num, size_t* args) {
check_num_params(num, 2, "with-meta");
check_vector(args[0], "with-meta");
@@ -1635,6 +1676,27 @@ fun find_closed_vars(defined: set<str>, env: *Env, ast: MalValue): set<str> {
}
error("Can't get closure_vars for " + pr_str(ast, true))
}
fun c_legal(s: ref str): str {
var to_ret = str()
for (var i = 0; i < s.length(); i++;) {
if s[i] == '!' {
to_ret += "_bang_"
} else if s[i] == '-' {
to_ret += "_dash_"
} else if s[i] == '+' {
to_ret += "_plus_"
} else if s[i] == '*' {
to_ret += "_star_"
} else if s[i] == '/' {
to_ret += "_div_"
} else if s[i] == '=' {
to_ret += "_eq_"
} else {
to_ret += s[i]
}
}
return to_ret
}
fun compile_value(top_decs: *str, top_defs: *str, main_init: *str, defs: *str, env: *Env, ast: MalValue, quoted: bool): str {
match (ast.internal) {
MalValue_int::Nil() {
@@ -1646,11 +1708,49 @@ fun compile_value(top_decs: *str, top_defs: *str, main_init: *str, defs: *str, e
MalValue_int::False() {
return str("0x1F")
}
MalValue_int::BuiltinFunction(f) {
if (f.name == "+") {
return str("((((size_t)&_plus_closure)<<3)|0x6)")
} else if (f.name == "-") {
return str("((((size_t)&_minus_closure)<<3)|0x6)")
} else if (f.name == "*") {
return str("((((size_t)&_mult_closure)<<3)|0x6)")
} else if (f.name == "/") {
return str("((((size_t)&_div_closure)<<3)|0x6)")
} else if (f.name == "=") {
return str("((((size_t)&_eq_closure)<<3)|0x6)")
} else if (f.name == "<") {
return str("((((size_t)&_lt_closure)<<3)|0x6)")
} else if (f.name == "<=") {
return str("((((size_t)&_lte_closure)<<3)|0x6)")
} else if (f.name == ">") {
return str("((((size_t)&_gt_closure)<<3)|0x6)")
} else if (f.name == ">=") {
return str("((((size_t)&_gte_closure)<<3)|0x6)")
} else if (f.name == "print") {
return str("((((size_t)&_print_closure)<<3)|0x6)")
} else if (f.name == "println") {
return str("((((size_t)&_println_closure)<<3)|0x6)")
} else if (f.name == "vector") {
return str("((((size_t)&_vector_closure)<<3)|0x6)")
} else if (f.name == "nth") {
return str("((((size_t)&_nth_closure)<<3)|0x6)")
} else if (f.name == "set-nth!") {
return str("((((size_t)&_set_nth_closure)<<3)|0x6)")
} else if (f.name == "throw") {
return str("((((size_t)&_throw_closure)<<3)|0x6)")
} else if (f.name == "with-meta") {
return str("((((size_t)&_with_meta_closure)<<3)|0x6)")
} else if (f.name == "meta") {
return str("((((size_t)&_meta_closure)<<3)|0x6)")
} else if (f.name == "cons") {
return str("((((size_t)&_cons_closure)<<3)|0x6)")
} else if (f.name == "concat") {
return str("((((size_t)&_concat_closure)<<3)|0x6)")
}
error("cannot yet compile builtin function: " + f.name)
}
MalValue_int::Function(f) {
/*if quoted {*/
/*error("cannot compile quoted function - does this even make sense?")*/
/*}*/
var fun_name = "fun_" + new_tmp()
*top_decs += "size_t " + fun_name + "(size_t*, size_t, size_t*);\n"
var function = "size_t " + fun_name + "(size_t* closed_vars, size_t num, size_t* args) {\n"
@@ -1688,55 +1788,20 @@ fun compile_value(top_decs: *str, top_defs: *str, main_init: *str, defs: *str, e
*defs += "*" + val_name + " = " + s.length() + ";\n"
*defs += "strcpy(((char*)(" + val_name + "+1)), \"" + s + "\");\n"
return "((((size_t)" + val_name + ")<<3)|0x5)"
}
if (s == "+") {
return str("((((size_t)&_plus_closure)<<3)|0x6)")
} else if (s == "-") {
return str("((((size_t)&_minus_closure)<<3)|0x6)")
} else if (s == "*") {
return str("((((size_t)&_mult_closure)<<3)|0x6)")
} else if (s == "/") {
return str("((((size_t)&_div_closure)<<3)|0x6)")
} else if (s == "=") {
return str("((((size_t)&_eq_closure)<<3)|0x6)")
} else if (s == "<") {
return str("((((size_t)&_lt_closure)<<3)|0x6)")
} else if (s == "<=") {
return str("((((size_t)&_lte_closure)<<3)|0x6)")
} else if (s == ">") {
return str("((((size_t)&_gt_closure)<<3)|0x6)")
} else if (s == ">=") {
return str("((((size_t)&_gte_closure)<<3)|0x6)")
} else if (s == "print") {
return str("((((size_t)&_print_closure)<<3)|0x6)")
} else if (s == "println") {
return str("((((size_t)&_println_closure)<<3)|0x6)")
} else if (s == "vector") {
return str("((((size_t)&_vector_closure)<<3)|0x6)")
} else if (s == "nth") {
return str("((((size_t)&_nth_closure)<<3)|0x6)")
} else if (s == "set-nth!") {
return str("((((size_t)&_set_nth_closure)<<3)|0x6)")
} else if (s == "throw") {
return str("((((size_t)&_throw_closure)<<3)|0x6)")
} else if (s == "with-meta") {
return str("((((size_t)&_with_meta_closure)<<3)|0x6)")
} else if (s == "meta") {
return str("((((size_t)&_meta_closure)<<3)|0x6)")
} else {
var c_legal_s = c_legal(s)
var e = env->find(s);
if e != null<Env>() && e->outer == null<Env>() {
println(s + " found in outer-est scope!")
var v = e->get(s)
e->remove(s)
var x = str()
/*var value = compile(top_decs, top_defs, main_init, &x, e, get_value(v))*/
var value = compile_value(top_decs, top_defs, main_init, &x, e, get_value(v), true)
*top_decs += "size_t " + s + ";\n"
*top_decs += "size_t " + c_legal_s + ";\n"
*main_init += x
*main_init += s + " = " + value + ";\n"
*main_init += c_legal_s + " = " + value + ";\n"
}
return s
return c_legal_s
}
}
MalValue_int::String(s) {