Started working on basic wasm encoding/serialization. Added binary_file_writing, generalized arity comparison operators, bitwise operators, parsing of hex numbers, and wasm w/ memory section deserialization
This commit is contained in:
11
comp_wasm.kp
Normal file
11
comp_wasm.kp
Normal file
@@ -0,0 +1,11 @@
|
||||
(with_import "./wasm.kp"
|
||||
(let (
|
||||
_ (println "args" *ARGV*)
|
||||
(_ _ in out) (cond (!= (len *ARGV*) 4) (error "wrong number of params")
|
||||
true *ARGV*)
|
||||
_ (println "in" in "out" out)
|
||||
wasm_code [
|
||||
]
|
||||
_ (write_file out (wasm_to_binary wasm_code))
|
||||
return_code 0
|
||||
) return_code ))
|
||||
117
k_prime.krak
117
k_prime.krak
@@ -716,7 +716,7 @@ fun main(argc: int, argv: **char): int {
|
||||
}
|
||||
return KPResult::Ok(kpString(to_ret));
|
||||
})), kpNil(), ret_0_sym)
|
||||
grammar.add_to_nonterminal(atom, vec(grammar.add_terminal("-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|<|>|%)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>|%)*)", kpNil(), fun(_: ref KPValue, input: ref str, l: int, r: int): KPResult {
|
||||
grammar.add_to_nonterminal(atom, vec(grammar.add_terminal("-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|\\||<|>|%)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|\\||<|>|%)*)", kpNil(), fun(_: ref KPValue, input: ref str, l: int, r: int): KPResult {
|
||||
var s = input.slice(l,r)
|
||||
if s == "true" {
|
||||
return KPResult::Ok(kpTrue());
|
||||
@@ -1005,6 +1005,39 @@ fun main(argc: int, argv: **char): int {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpInt(to_ret)))
|
||||
}));
|
||||
|
||||
env->set(str("&"), make_builtin_combiner(str("&"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to &"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called & with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called & with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpInt(params[0].get_int() & params[1].get_int())))
|
||||
}));
|
||||
env->set(str("|"), make_builtin_combiner(str("|"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to |"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called | with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called | with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpInt(params[0].get_int() | params[1].get_int())))
|
||||
}));
|
||||
env->set(str("<<"), make_builtin_combiner(str("<<"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to <<"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called << with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called << with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpInt(params[0].get_int() << params[1].get_int())))
|
||||
}));
|
||||
env->set(str(">>"), make_builtin_combiner(str(">>"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to >>"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called >> with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called >> with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpInt(params[0].get_int() >> params[1].get_int())))
|
||||
}));
|
||||
|
||||
env->set(str("="), make_builtin_combiner(str("="), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to ="))))
|
||||
@@ -1018,36 +1051,56 @@ fun main(argc: int, argv: **char): int {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(!params[0].equals(params[1]))))
|
||||
}));
|
||||
env->set(str("<"), make_builtin_combiner(str("<"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to <"))))
|
||||
if params.size <= 1 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 or more params to <"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called < with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called < with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(params[0].get_int() < params[1].get_int())))
|
||||
for (var i = 0; i < params.size - 1; i++;) {
|
||||
if !params[i+1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called < with not an int")))); }
|
||||
if !(params[i].get_int() < params[i+1].get_int()) {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(false)))
|
||||
}
|
||||
}
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(true)))
|
||||
}));
|
||||
env->set(str("<="), make_builtin_combiner(str("<="), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to <="))))
|
||||
if params.size <= 1 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 or more params to <="))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called <= with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called <= with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(params[0].get_int() <= params[1].get_int())))
|
||||
for (var i = 0; i < params.size - 1; i++;) {
|
||||
if !params[i+1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called <= with not an int")))); }
|
||||
if !(params[i].get_int() <= params[i+1].get_int()) {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(false)))
|
||||
}
|
||||
}
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(true)))
|
||||
}));
|
||||
env->set(str(">"), make_builtin_combiner(str(">"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to >"))))
|
||||
if params.size <= 1 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 or more params to >"))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called > with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called > with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(params[0].get_int() > params[1].get_int())))
|
||||
for (var i = 0; i < params.size - 1; i++;) {
|
||||
if !params[i+1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called > with not an int")))); }
|
||||
if !(params[i].get_int() > params[i+1].get_int()) {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(false)))
|
||||
}
|
||||
}
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(true)))
|
||||
}));
|
||||
env->set(str(">="), make_builtin_combiner(str(">="), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 params to >="))))
|
||||
if params.size <= 1 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("Need 2 or more params to >="))))
|
||||
}
|
||||
if !params[0].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called >= with first not an int")))); }
|
||||
if !params[1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called >= with second not an int")))); }
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(params[0].get_int() >= params[1].get_int())))
|
||||
for (var i = 0; i < params.size - 1; i++;) {
|
||||
if !params[i+1].is_int() { return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("called >= with not an int")))); }
|
||||
if !(params[i].get_int() >= params[i+1].get_int()) {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(false)))
|
||||
}
|
||||
}
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpBool(true)))
|
||||
}));
|
||||
|
||||
env->set(str("and"), make_builtin_combiner(str("and"), 0, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
@@ -1319,6 +1372,36 @@ fun main(argc: int, argv: **char): int {
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpString(get_line(params[0].get_string(), 1024))))
|
||||
}
|
||||
}));
|
||||
env->set(str("write_file"), make_builtin_combiner(str("write_file"), 1, false, fun(params: vec<KPValue>, dynamic_env: *KPEnv): pair<*KPEnv, KPResult> {
|
||||
if params.size != 2 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("write_file with not a two params"))))
|
||||
} else {
|
||||
if !params[0].is_string() {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("write_file with first param not a (path) string"))))
|
||||
}
|
||||
if params[1].is_string() {
|
||||
write_file(params[0].get_string(), params[1].get_string())
|
||||
} else if params[1].is_array() {
|
||||
var arc = params[1].get_array_rc()
|
||||
var size = arc.get().size
|
||||
var out_vec = vec<char>()
|
||||
for (var i = 0; i < size; i++;) {
|
||||
if !arc.get()[i].is_int() {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("write_file with vec member ") + i + "(" + pr_str(arc.get()[i], true) + ") isn't int")))
|
||||
}
|
||||
var int_out = arc.get()[i].get_int()
|
||||
if int_out < 0 || int_out > 255 {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("write_file with vec member ") + i + "(" + int_out + ") is out of 0-255 byte range " + int_out)))
|
||||
}
|
||||
out_vec.add((int_out) cast char)
|
||||
}
|
||||
write_file_binary(params[0].get_string(), out_vec)
|
||||
} else {
|
||||
return make_pair(null<KPEnv>(), KPResult::Err(kpString(str("write_file with second param not a string or array"))))
|
||||
}
|
||||
return make_pair(null<KPEnv>(), KPResult::Ok(kpNil()))
|
||||
}
|
||||
}));
|
||||
env->set(str("empty_env"), kpEnv(new<KPEnv>()->construct()))
|
||||
|
||||
// Launch into new kraken for interface and self-hosting features
|
||||
|
||||
27
prelude.kp
27
prelude.kp
@@ -138,16 +138,27 @@
|
||||
|
||||
|
||||
string-to-int (lambda (s) (let (
|
||||
helper (rec-lambda recurse (s i result)
|
||||
c0 (idx "0" 0)
|
||||
c9 (idx "9" 0)
|
||||
ca (idx "a" 0)
|
||||
cz (idx "z" 0)
|
||||
cA (idx "A" 0)
|
||||
cZ (idx "Z" 0)
|
||||
helper (rec-lambda recurse (s i radix result)
|
||||
(if (< i (len s))
|
||||
(recurse s (+ i 1) (+ (* 10 result) (- (idx s i) (idx "0" 0))))
|
||||
(let (c (idx s i))
|
||||
(cond (<= c0 c c9) (recurse s (+ i 1) radix (+ (* radix result) (- (idx s i) c0)))
|
||||
(<= ca c cz) (recurse s (+ i 1) radix (+ (* radix result) (+ 10 (- (idx s i) ca))))
|
||||
(<= cA c cZ) (recurse s (+ i 1) radix (+ (* radix result) (+ 10 (- (idx s i) cA))))
|
||||
true (error "Impossible char in string-to-int"))
|
||||
)
|
||||
result
|
||||
)
|
||||
))
|
||||
(if (= (idx s 0) (idx "-" 0))
|
||||
(- (helper s 1 0))
|
||||
(helper s 0 0)
|
||||
)))
|
||||
(cond (= (idx s 0) (idx "-" 0)) (- (helper s 1 10 0))
|
||||
(and (> (len s) 2) (or (= "0x" (slice s 0 2)) (= "0X" (slice s 0 2)))) (helper s 2 16 0)
|
||||
true (helper s 0 10 0))
|
||||
))
|
||||
|
||||
unescape-str (lambda (s) (let (
|
||||
helper (rec-lambda recurse (s i r)
|
||||
@@ -168,10 +179,10 @@
|
||||
(array (quote WS) (array "( | |
|
||||
|(;[ -~]*
|
||||
))+") (lambda (x) nil))
|
||||
(array (quote number) (array "-?[0-9]+") (lambda (x) (string-to-int x)))
|
||||
(array (quote number) (array "(0(x|X)([0-9]|[a-f]|[A-F])+)|(-?[0-9]+)") (lambda (x) (string-to-int x)))
|
||||
(array (quote string) (array "\"([#-[]| |[]-~]|(\\\\\\\\)|(\\\\n)|(\\\\t)|(\\*)|(\\\\0)|
|
||||
|[ -!]|(\\\\\"))*\"") (lambda (x) (unescape-str x)))
|
||||
(array (quote bool_nil_symbol) (array "-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|<|>|%)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|<|>|%)*)") (lambda (x) (cond (= "true" x) true
|
||||
(array (quote bool_nil_symbol) (array "-|(([a-z]|[A-Z]|_|\\*|/|\\?|\\+|!|=|&|\\||<|>|%)([a-z]|[A-Z]|_|[0-9]|\\*|\\?|\\+|-|!|=|&|\\||<|>|%)*)") (lambda (x) (cond (= "true" x) true
|
||||
(= "false" x) false
|
||||
(= "nil" x) nil
|
||||
true (str-to-symbol x))))
|
||||
|
||||
@@ -125,7 +125,7 @@ fun write_file_binary(path: str::str, vdata: vec::vec<char>) {
|
||||
defer delete(char_path)
|
||||
var data = vdata.getBackingMemory()
|
||||
var size = vdata.size
|
||||
var fp = fopen(char_path, "w")
|
||||
var fp = fopen(char_path, "wb")
|
||||
fwrite((data) cast *void, (1) cast ulong, (size) cast ulong, fp)
|
||||
fclose(fp)
|
||||
}
|
||||
|
||||
46
wasm.kp
Normal file
46
wasm.kp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
(let (
|
||||
; Vectors and Values
|
||||
; Bytes encode themselves
|
||||
encode_u_LEB128 (rec-lambda recurse (x)
|
||||
(cond (< x 0x80) [x]
|
||||
true (cons (| (& x 0x7F) 0x1) (recurse (>> x 8))))
|
||||
)
|
||||
encode_s8_LEB128 (lambda (x) (encode_u_LEB128 (& x 255)))
|
||||
encode_vector (lambda (enc v)
|
||||
(concat (encode_u_LEB128 (len v)) (flat_map enc v) )
|
||||
)
|
||||
encode_floating_point (lambda (x) (error "unimplemented"))
|
||||
encode_name (lambda (name)
|
||||
(encode_vector (lambda (x) [x]) name)
|
||||
)
|
||||
|
||||
; Types
|
||||
; TODO
|
||||
encode_limits (lambda (x)
|
||||
(cond (= 1 (len x)) (concat [0x00] (encode_u_LEB128 (idx x 0)))
|
||||
(= 2 (len x)) (concat [0x01] (encode_u_LEB128 (idx x 0)) (encode_u_LEB128 (idx x 1)))
|
||||
true (error "trying to encode bad limits"))
|
||||
)
|
||||
|
||||
; Instructions
|
||||
; TODO
|
||||
|
||||
; Modules
|
||||
encode_memory_section (lambda (x)
|
||||
(let (
|
||||
encoded (encode_vector encode_limits x)
|
||||
) (concat [0x05] (encode_u_LEB128 (len encoded)) encoded ))
|
||||
)
|
||||
|
||||
|
||||
wasm_to_binary (lambda (wasm_code)
|
||||
(let (
|
||||
magic [ 0x00 0x61 0x73 0x6D ]
|
||||
version [ 0x01 0x00 0x00 0x00 ]
|
||||
memory (encode_memory_section [ [0x20 0x30] ])
|
||||
) (concat magic version memory))
|
||||
)
|
||||
)
|
||||
(provide wasm_to_binary)
|
||||
)
|
||||
Reference in New Issue
Block a user