Compare commits

..

No commits in common. "20cbcf79637d9f512ce5be602c81c08f2d8c5d90" and "53f4dc5b13f5090c8fe1a7a1f2e033c340e88d41" have entirely different histories.

2 changed files with 780 additions and 802 deletions

View File

@ -2,10 +2,10 @@
(fn Emitter (ast filename) (do (fn Emitter (ast filename) (do
(let output (list)) (let output (list))
(let (enter_scope leave_scope define_sym get_sym print_syms) (Syms)) (let (enter_scope leave_scope define_sym get_sym print_syms) (call Syms))
(let (let_node_reg_count let_node_reg_increment) (Counter)) (let (let_node_reg_count let_node_reg_increment) (call Counter))
(let (sym_id_count sym_id_increment) (Counter)) (let (sym_id_count sym_id_increment) (call Counter))
(let builtin_syms (list (let builtin_syms (list
(list "format" "builtinFormat") (list "format" "builtinFormat")
@ -25,25 +25,25 @@
)) ))
(fn generate () (do (fn generate () (do
(emit "#!/usr/bin/env node\n") (call emit "#!/usr/bin/env node\n")
(emit "import { Runtime } from \"./runtime.js\";\n") (call emit "import { Runtime } from \"./runtime.js\";\n")
(emit "const runtime = new Runtime({ filename: \"") (call emit "const runtime = new Runtime({ filename: \"")
(emit filename) (call emit filename)
(emit "\" });\n") (call emit "\" });\n")
(for (ident builtin_id) builtin_syms (do (for (ident builtin_id) builtin_syms (do
(define_builtin ident builtin_id) (call define_builtin ident builtin_id)
)) ))
(discover_syms ast) (call discover_syms ast)
(emit_exprs ast) (call emit_exprs ast)
(return (strings_join output)) (return (call strings_join output))
)) ))
(fn emit_exprs (exprs) (do (fn emit_exprs (exprs) (do
(for expr exprs (do (for expr exprs (do
(emit_expr expr) (call emit_expr expr)
(emit ";\n") (call emit ";\n")
)) ))
)) ))
@ -52,11 +52,11 @@
(let (ty line) expr) (let (ty line) expr)
(if (!= ty "list") (return)) (if (!= ty "list") (return))
(let (_ _ s) expr) (let (_ _ s) expr)
(if (== (len s) 0) (return)) (if (== (call len s) 0) (return))
(let ((_ _ id)) s) (let ((_ _ id)) s)
(if (== id "fn") (do (if (== id "fn") (do
(let (_ (_ _ ident) (_ _ params) body) s) (let (_ (_ _ ident) (_ _ params) body) s)
(define_fn ident line) (call define_fn ident line)
)) ))
)) ))
)) ))
@ -64,247 +64,236 @@
(fn emit_expr (expr) (do (fn emit_expr (expr) (do
(let (ty line) expr) (let (ty line) expr)
(if (== ty "list") (do (if (== ty "list") (do
(emit_list expr) (call emit_list expr)
) (if (== ty "int") (do ) (if (== ty "int") (do
(let (_ _ value) expr) (let (_ _ value) expr)
(emit (format "({ type: \"int\", value: % })" value)) (call emit (call format "({ type: \"int\", value: % })" value))
) (if (== ty "string") (do ) (if (== ty "string") (do
(let (_ _ value) expr) (let (_ _ value) expr)
(emit (format "({ type: \"string\", value: \"%\" })" (string_escape value))) (call emit (call format "({ type: \"string\", value: \"%\" })" (call string_escape value)))
) (if (== ty "ident") (do ) (if (== ty "ident") (do
(let (_ _ value) expr) (let (_ _ value) expr)
(if (== value "null") (do (if (== value "null") (do
(emit "({ type: \"null\" })") (call emit "({ type: \"null\" })")
(return) (return)
) (if (== value "false") (do ) (if (== value "false") (do
(emit "({ type: \"bool\", value: false })") (call emit "({ type: \"bool\", value: false })")
(return) (return)
) (if (== value "true") (do ) (if (== value "true") (do
(emit "({ type: \"bool\", value: true })") (call emit "({ type: \"bool\", value: true })")
(return) (return)
)))) ))))
(let sym (get_sym value)) (let sym (call get_sym value))
(if (== sym null) (do (if (== sym null) (do
(panic "undefined symbol '%' on line %" value line) (call panic "undefined symbol '%' on line %" value line)
)) ))
(let (sym_id sym_ty) sym) (let (sym_id sym_ty) sym)
(if (== sym_ty "builtin") (do (if (== sym_ty "builtin") (do
(let (_ _ id) sym) (let (_ _ id) sym)
(emit (format "((...args) => runtime.%(...args))" id)) (call emit (call format "((...args) => runtime.%(...args))" id))
) (if (== sym_ty "fn") (do ) (if (== sym_ty "fn") (do
(emit (format "_%%" value sym_id)) (call emit (call format "_%%" value sym_id))
) (if (== sym_ty "param") (do ) (if (== sym_ty "param") (do
(emit (format "_%%" value sym_id)) (call emit (call format "_%%" value sym_id))
) (if (== sym_ty "let") (do ) (if (== sym_ty "let") (do
(emit (format "_%%" value sym_id)) (call emit (call format "_%%" value sym_id))
) (do ) (do
(panic "not implemented '%'" sym_ty) (call panic "not implemented '%'" sym_ty)
))))) )))))
) (do ) (do
(panic "unknown expr type '%' on line %" ty line) (call panic "unknown expr type '%' on line %" ty line)
))))) )))))
)) ))
(fn emit_list (expr) (do (fn emit_list (expr) (do
(let (ty line s) expr) (let (ty line s) expr)
(if (== (len s) 0) (do (if (== (call len s) 0) (do
(panic "illegal function on line %" line) (call emit "({ type: \"list\", values: [] })")
(call println "warning: deprecated list syntax on line %" line)
(return)
)) ))
(let ((id_ty _ id)) s) (let ((id_ty _ id)) s)
(if (!= id_ty "ident") (do (if (!= id_ty "ident") (do
(panic "illegal function on line %" line) (call emit_list_literal s)
(call println "warning: deprecated list syntax on line %" line)
(return)
)) ))
(if (== id "fn") (do (if (== id "fn") (do
(let (_ (_ _ ident) (_ _ params) body) s) (let (_ (_ _ ident) (_ _ params) body) s)
(let sym (get_sym ident)) (let sym (call get_sym ident))
(let (sym_id) sym) (let (sym_id) sym)
(emit (format "function _%%(" ident sym_id)) (call emit (call format "function _%%(" ident sym_id))
(enter_scope) (call enter_scope)
(let first true) (let first true)
(for (_ _ ident) params (do (for (_ _ ident) params (do
(if (not first) (do (if (not first) (do
(emit ", ") (call emit ", ")
)) ))
(= first false) (= first false)
(let sym_id (define_param ident line)) (let sym_id (call define_param ident line))
(emit (format "_%%" ident sym_id)) (call emit (call format "_%%" ident sym_id))
)) ))
(emit ") {\n") (call emit ") {\n")
(emit (format "runtime.pushCall(\"%\");\n" ident)) (call emit (call format "runtime.pushCall(\"%\");\n" ident))
(emit_expr body) (call emit_expr body)
(emit ";\nruntime.popCall();\nreturn { type: \"null\" };\n}") (call emit ";\nruntime.popCall();\nreturn { type: \"null\" };\n}")
(leave_scope) (call leave_scope)
) (if (== id "let") (do ) (if (== id "let") (do
(let (_ pat expr) s) (let (_ pat expr) s)
(let reg (let_node_reg_count)) (let reg (call let_node_reg_count))
(let_node_reg_increment) (call let_node_reg_increment)
(emit (format "const r_% = " reg)) (call emit (call format "const r_% = " reg))
(emit_expr expr) (call emit_expr expr)
(emit_let_node pat reg) (call emit_let_node pat reg)
) (if (== id "do") (do ) (if (== id "do") (do
(enter_scope) (call enter_scope)
(discover_syms (slice s 1)) (call discover_syms (call slice s 1))
(emit_exprs (slice s 1)) (call emit_exprs (call slice s 1))
(leave_scope) (call leave_scope)
) (if (== id "for") (do ) (if (== id "for") (do
(let (_ pat expr body) s) (let (_ pat expr body) s)
(let reg (let_node_reg_count)) (let reg (call let_node_reg_count))
(let_node_reg_increment) (call let_node_reg_increment)
(emit (format "for (const r_% of " reg)) (call emit (call format "for (const r_% of " reg))
(emit_expr expr) (call emit_expr expr)
(emit ".values) {") (call emit ".values) {")
(enter_scope) (call enter_scope)
(emit_let_node pat reg) (call emit_let_node pat reg)
(enter_scope) (call enter_scope)
(emit ";\n") (call emit ";\n")
(emit_expr body) (call emit_expr body)
(emit "}") (call emit "}")
(leave_scope) (call leave_scope)
(leave_scope) (call leave_scope)
) (if (== id "loop") (do ) (if (== id "loop") (do
(let (_ body) s) (let (_ body) s)
(emit "while (true) {\n") (call emit "while (true) {\n")
(emit_expr body) (call emit_expr body)
(emit "}") (call emit "}")
) (if (== id "if") (do ) (if (== id "if") (do
(let (_ cond truthy falsy) s) (let (_ cond truthy falsy) s)
(emit "if (runtime.truthy(") (call emit "if (runtime.truthy(")
(emit_expr cond) (call emit_expr cond)
(emit ")) {\n") (call emit ")) {\n")
(emit_expr truthy) (call emit_expr truthy)
(emit "}") (call emit "}")
(if (!= falsy null) (do (if (!= falsy null) (do
(emit " else {\n") (call emit " else {\n")
(emit_expr falsy) (call emit_expr falsy)
(emit "}") (call emit "}")
)) ))
) (if (== id "return") (do ) (if (== id "return") (do
(let (_ value) s) (let (_ value) s)
(emit "runtime.popCall();\n") (call emit "runtime.popCall();\n")
(emit "return ") (call emit "return ")
(if (!= value null) (do (if (!= value null) (do
(emit_expr value) (call emit_expr value)
) (do ) (do
(emit "{ type: \"null\" }") (call emit "{ type: \"null\" }")
)) ))
) (if (== id "break") (do ) (if (== id "break") (do
(let (_ value) s) (let (_ value) s)
(emit "break") (call emit "break")
(if (!= value null) (do (if (!= value null) (do
(panic "not implemented") (call panic "not implemented")
)) ))
) (if (== id "call") (do ) (if (== id "call") (do
(let (_ callee) s) (let (_ callee) s)
(let args (slice s 2)) (let args (call slice s 2))
(emit (format "(runtime.setLine(%), " line)) (call emit (call format "(runtime.setLine(%), " line))
(emit_expr callee) (call emit_expr callee)
(emit "(") (call emit "(")
(let first true) (let first true)
(for arg args (do (for arg args (do
(if (not first) (do (if (not first) (do
(emit ", ") (call emit ", ")
)) ))
(= first false) (= first false)
(emit_expr arg) (call emit_expr arg)
)) ))
(emit "))") (call emit "))")
) (if (== id "list") (do ) (if (== id "list") (do
(emit_list_literal (slice s 1)) (call emit_list_literal (call slice s 1))
) (if (== id "=") (do ) (if (== id "=") (do
(emit_assign_expr s line "=") (call emit_assign_expr s line "=")
) (if (== id "+=") (do ) (if (== id "+=") (do
(emit_assign_expr s line "+") (call emit_assign_expr s line "+")
) (if (== id "-=") (do ) (if (== id "-=") (do
(emit_assign_expr s line "-") (call emit_assign_expr s line "-")
) (if (== id "or") (do ) (if (== id "or") (do
(let (_ left right) s) (let (_ left right) s)
(emit (format "(runtime.setLine(%)" line)) (call emit (call format "(runtime.setLine(%)" line))
(emit ", { type: \"bool\", value: runtime.truthy(") (call emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left) (call emit_expr left)
(emit ") || runtime.truthy(") (call emit ") || runtime.truthy(")
(emit_expr right) (call emit_expr right)
(emit ") })") (call emit ") })")
) (if (== id "and") (do ) (if (== id "and") (do
(let (_ left right) s) (let (_ left right) s)
(emit (format "(runtime.setLine(%)" line)) (call emit (call format "(runtime.setLine(%)" line))
(emit ", { type: \"bool\", value: runtime.truthy(") (call emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left) (call emit_expr left)
(emit ") && runtime.truthy(") (call emit ") && runtime.truthy(")
(emit_expr right) (call emit_expr right)
(emit ") })") (call emit ") })")
) (if (== id "==") (do ) (if (== id "==") (do
(emit_binary_op s "opEq") (call emit_binary_op s "opEq")
) (if (== id "!=") (do ) (if (== id "!=") (do
(emit_binary_op s "opNe") (call emit_binary_op s "opNe")
) (if (== id "<") (do ) (if (== id "<") (do
(emit_binary_op s "opLt") (call emit_binary_op s "opLt")
) (if (== id ">") (do ) (if (== id ">") (do
(emit_binary_op s "opGt") (call emit_binary_op s "opGt")
) (if (== id "<=") (do ) (if (== id "<=") (do
(emit_binary_op s "opLte") (call emit_binary_op s "opLte")
) (if (== id ">=") (do ) (if (== id ">=") (do
(emit_binary_op s "opGte") (call emit_binary_op s "opGte")
) (if (== id "+") (do ) (if (== id "+") (do
(emit_binary_op s "opAdd") (call emit_binary_op s "opAdd")
) (if (== id "-") (do ) (if (== id "-") (do
(emit_binary_op s "opSub") (call emit_binary_op s "opSub")
) (if (== id "not") (do ) (if (== id "not") (do
(let (_ expr) s) (let (_ expr) s)
(emit "runtime.opNot(") (call emit "runtime.opNot(")
(emit_expr expr) (call emit_expr expr)
(emit ")") (call emit ")")
) (do ) (do
(let (callee) s) (call emit_list_literal s)
(let args (slice s 1)) (call println "warning: deprecated list syntax on line %" line)
(emit (format "(runtime.setLine(%), " line))
(emit_expr callee)
(emit "(")
(let first true)
(for arg args (do
(if (not first) (do
(emit ", ")
))
(= first false)
(emit_expr arg)
))
(emit "))")
))))))))))))))))))))))))) )))))))))))))))))))))))))
)) ))
(fn emit_list_literal (s) (do (fn emit_list_literal (s) (do
(emit "({ type: \"list\", values: [") (call emit "({ type: \"list\", values: [")
(let first true) (let first true)
(for e s (do (for e s (do
(if (not first) (do (if (not first) (do
(emit ", ") (call emit ", ")
)) ))
(= first false) (= first false)
(emit_expr e) (call emit_expr e)
)) ))
(emit "] })") (call emit "] })")
)) ))
(fn emit_let_node (pat base_reg) (do (fn emit_let_node (pat base_reg) (do
@ -314,117 +303,117 @@
(if (== ident "_") (return)) (if (== ident "_") (return))
(let sym_id (define_let ident line)) (let sym_id (call define_let ident line))
(emit (format ";\nlet _%% = r_%" ident sym_id base_reg)) (call emit (call format ";\nlet _%% = r_%" ident sym_id base_reg))
) (if (== pat_ty "list") (do ) (if (== pat_ty "list") (do
(let (_ _ pats) pat) (let (_ _ pats) pat)
//(emit (format //(call emit (call format
// (+ ";\nif (r_%.type !== \"list\") {\nruntime.setLine(%);" // (+ ";\nif (r_%.type !== \"list\") {\nruntime.setLine(%);"
// "\nruntime.panic(\"expected list\");\n}\n") // "\nruntime.panic(\"expected list\");\n}\n")
// base_reg // base_reg
// line // line
//)) //))
//(emit (format //(call emit (call format
// (+ ";\nif (% > r_%.values.length) {\nruntime.setLine(%);\nruntime.panic" // (+ ";\nif (% > r_%.values.length) {\nruntime.setLine(%);\nruntime.panic"
// "(`expected % elements, got ${r_%.values.length}`);\n}\n") // "(`expected % elements, got ${r_%.values.length}`);\n}\n")
// (len pats) // (call len pats)
// base_reg // base_reg
// line // line
// (len pats) // (call len pats)
// base_reg // base_reg
//)) //))
(let i 0) (let i 0)
(for pat pats (do (for pat pats (do
(let reg (let_node_reg_count)) (let reg (call let_node_reg_count))
(let_node_reg_increment) (call let_node_reg_increment)
(emit (format (call emit (call format
";\nconst r_% = r_%.values[%] ?? { type: \"null\"}" ";\nconst r_% = r_%.values[%] ?? { type: \"null\"}"
reg base_reg i reg base_reg i
)) ))
(emit_let_node pat reg) (call emit_let_node pat reg)
(+= i 1) (+= i 1)
)) ))
) (do ) (do
(panic "malformed pattern on line %" line) (call panic "malformed pattern on line %" line)
))) )))
)) ))
(fn emit_binary_op (s id) (do (fn emit_binary_op (s id) (do
(let (_ left right) s) (let (_ left right) s)
(emit (format "runtime.%(" id)) (call emit (call format "runtime.%(" id))
(emit_expr left) (call emit_expr left)
(emit ", ") (call emit ", ")
(emit_expr right) (call emit_expr right)
(emit ")") (call emit ")")
)) ))
(fn emit_assign_expr (s line id) (do (fn emit_assign_expr (s line id) (do
(let (_ (target_type) expr) s) (let (_ (target_type) expr) s)
(if (!= target_type "ident") (do (if (!= target_type "ident") (do
(panic "cannot assign to expression on line %" line) (call panic "cannot assign to expression on line %" line)
)) ))
(let (_ (_ _ ident)) s) (let (_ (_ _ ident)) s)
(let sym (get_sym ident)) (let sym (call get_sym ident))
(if (== sym null) (do (if (== sym null) (do
(panic "could not find symbol '%' on line %" ident line) (call panic "could not find symbol '%' on line %" ident line)
)) ))
(let (sym_id sym_type sym_ident _) sym) (let (sym_id sym_type sym_ident _) sym)
(if (== sym_type "let") (do (if (== sym_type "let") (do
(emit (format "(_%% = " sym_ident sym_id)) (call emit (call format "(_%% = " sym_ident sym_id))
(if (== id "=") (do (if (== id "=") (do
(emit_expr expr) (call emit_expr expr)
) (if (== id "+") (do ) (if (== id "+") (do
(emit (format "runtime.opAdd(_%%, " sym_ident sym_id)) (call emit (call format "runtime.opAdd(_%%, " sym_ident sym_id))
(emit_expr expr) (call emit_expr expr)
(emit ")") (call emit ")")
) (if (== id "-") (do ) (if (== id "-") (do
(emit (format "runtime.opSub(_%%, " sym_ident sym_id)) (call emit (call format "runtime.opSub(_%%, " sym_ident sym_id))
(emit_expr expr) (call emit_expr expr)
(emit ")") (call emit ")")
) (do ) (do
(panic "not implemented") (call panic "not implemented")
)))) ))))
(emit ")") (call emit ")")
) (do ) (do
(panic "cannot assign to symbol '%' on line %" sym_ident line) (call panic "cannot assign to symbol '%' on line %" sym_ident line)
)) ))
)) ))
(fn emit (str) (do (fn emit (str) (do
(push output str) (call push output str)
)) ))
(fn define_builtin (ident builtin_id) (do (fn define_builtin (ident builtin_id) (do
(let sym_id (sym_id_count)) (let sym_id (call sym_id_count))
(sym_id_increment) (call sym_id_increment)
(define_sym ident (list sym_id "builtin" builtin_id)) (call define_sym ident (list sym_id "builtin" builtin_id))
(return sym_id) (return sym_id)
)) ))
(fn define_fn (ident line) (do (fn define_fn (ident line) (do
(let sym_id (sym_id_count)) (let sym_id (call sym_id_count))
(sym_id_increment) (call sym_id_increment)
(define_sym ident (list sym_id "fn" ident line)) (call define_sym ident (list sym_id "fn" ident line))
(return sym_id) (return sym_id)
)) ))
(fn define_param (ident line) (do (fn define_param (ident line) (do
(let sym_id (sym_id_count)) (let sym_id (call sym_id_count))
(sym_id_increment) (call sym_id_increment)
(define_sym ident (list sym_id "param" ident line)) (call define_sym ident (list sym_id "param" ident line))
(return sym_id) (return sym_id)
)) ))
(fn define_let (ident line) (do (fn define_let (ident line) (do
(let sym_id (sym_id_count)) (let sym_id (call sym_id_count))
(sym_id_increment) (call sym_id_increment)
(define_sym ident (list sym_id "let" ident line)) (call define_sym ident (list sym_id "let" ident line))
(return sym_id) (return sym_id)
)) ))
@ -461,50 +450,50 @@
(let (_ map) syms) (let (_ map) syms)
(let i 0) (let i 0)
(loop (do (loop (do
(if (>= i (len map)) (break)) (if (>= i (call len map)) (break))
(let (s_ident _) (at map i)) (let (s_ident _) (call at map i))
(if (== ident s_ident) (do (if (== ident s_ident) (do
(set map i (list ident sym)) (call set map i (list ident sym))
(return) (return)
)) ))
(+= i 1) (+= i 1)
)) ))
(push map (list ident sym)) (call push map (list ident sym))
)) ))
(fn find_sym (syms ident) (do (fn find_sym (syms ident) (do
(let (parent map) syms) (let (parent map) syms)
(let i 0) (let i 0)
(loop (do (loop (do
(if (>= i (len map)) (break)) (if (>= i (call len map)) (break))
(let (s_ident s_sym) (at map i)) (let (s_ident s_sym) (call at map i))
(if (== ident s_ident) (do (if (== ident s_ident) (do
(return s_sym) (return s_sym)
)) ))
(+= i 1) (+= i 1)
)) ))
(if (!= parent null) (do (if (!= parent null) (do
(return (find_sym parent ident)) (return (call find_sym parent ident))
)) ))
(return null) (return null)
)) ))
(fn get (ident) (do (fn get (ident) (do
(return (find_sym syms ident)) (return (call find_sym syms ident))
)) ))
(fn print_syms_node (syms depth) (do (fn print_syms_node (syms depth) (do
(let (parent map) syms) (let (parent map) syms)
(for (ident sym) map (do (for (ident sym) map (do
(println "%- %: %" (indent depth) ident sym) (call println "%- %: %" (call indent depth) ident sym)
)) ))
(if (!= parent null) (do (if (!= parent null) (do
(print_syms_node parent (+ depth 1)) (call print_syms_node parent (+ depth 1))
)) ))
)) ))
(fn print_syms () (do (fn print_syms () (do
(print_syms_node syms 0) (call print_syms_node syms 0)
)) ))
(return (list (return (list
@ -518,12 +507,12 @@
(fn string_escape (str) (do (fn string_escape (str) (do
(let str_len (len str)) (let str_len (call len str))
(let i 0) (let i 0)
(let result "") (let result "")
(loop (do (loop (do
(if (>= i str_len) (break)) (if (>= i str_len) (break))
(let ch (at str i)) (let ch (call at str i))
(if (== ch "\\") (do (if (== ch "\\") (do
(+= result "\\\\") (+= result "\\\\")
) (if (== ch "\"") (do ) (if (== ch "\"") (do
@ -546,69 +535,69 @@
(fn Parser (tokens) (do (fn Parser (tokens) (do
(let i 0) (let i 0)
(let tok (at tokens i)) (let tok (call at tokens i))
(fn parse () (do (fn parse () (do
(let exprs (list)) (let exprs (list))
(loop (do (loop (do
(if (done) (break)) (if (call done) (break))
(push exprs (parse_expr)) (call push exprs (call parse_expr))
)) ))
(return exprs) (return exprs)
)) ))
(fn parse_expr () (do (fn parse_expr () (do
(let (ty line value) tok) (let (ty line value) tok)
(if (eat "(") (do (if (call eat "(") (do
(let values (list)) (let values (list))
(loop (do (loop (do
(if (test ")") (break)) (if (call test ")") (break))
(push values (parse_expr)) (call push values (call parse_expr))
)) ))
(if (not (eat ")")) (do (if (not (call eat ")")) (do
(panic "expected ')' on line %" (at tok 1)) (call panic "expected ')' on line %" (call at tok 1))
)) ))
(return (list "list" line values)) (return (list "list" line values))
) (if (eat "string") (do ) (if (call eat "string") (do
(return (list "string" line value)) (return (list "string" line value))
) (if (eat "int") (do ) (if (call eat "int") (do
(return (list "int" line (string_to_int value))) (return (list "int" line (call string_to_int value)))
) (if (eat "ident") (do ) (if (call eat "ident") (do
(return (list "ident" line value)) (return (list "ident" line value))
) (do ) (do
(panic "expected expression, got '%' on line %" ty line) (call panic "expected expression, got '%' on line %" ty line)
))))) )))))
)) ))
(fn eat (pat) (do (fn eat (pat) (do
(if (not (test pat)) (return false)) (if (not (call test pat)) (return false))
(step) (call step)
(return true) (return true)
)) ))
(fn step () (do (fn step () (do
(+= i 1) (+= i 1)
(if (not (done)) (do (if (not (call done)) (do
(let new_tok (at tokens i)) (let new_tok (call at tokens i))
(= tok new_tok) (= tok new_tok)
)) ))
)) ))
(fn test (pat) (do (fn test (pat) (do
(if (done) (return false)) (if (call done) (return false))
(let (ty) tok) (let (ty) tok)
(return (== pat ty)) (return (== pat ty))
)) ))
(fn done () (do (fn done () (do
(return (>= i (len tokens))) (return (>= i (call len tokens)))
)) ))
(return (list parse)) (return (list parse))
)) ))
(fn tokenize (text) (do (fn tokenize (text) (do
(let text_len (len text)) (let text_len (call len text))
(let tokens (list)) (let tokens (list))
(let i 0) (let i 0)
@ -620,27 +609,27 @@
(loop (do (loop (do
(if (>= i text_len) (break)) (if (>= i text_len) (break))
(let ch (at text i)) (let ch (call at text i))
(if (contains " \t\r\n" ch) (do (if (call contains " \t\r\n" ch) (do
(if (== ch "\n") (do (if (== ch "\n") (do
(+= line 1) (+= line 1)
)) ))
(+= i 1) (+= i 1)
) (if (slice_eq text i "//") (do ) (if (call slice_eq text i "//") (do
(loop (do (loop (do
(if (or (>= i text_len) (== (at text i) "\n")) (do (if (or (>= i text_len) (== (call at text i) "\n")) (do
(break) (break)
)) ))
(+= i 1) (+= i 1)
)) ))
) (if (contains "()" ch) (do ) (if (call contains "()" ch) (do
(push tokens (list ch line)) (call push tokens (list ch line))
(+= i 1) (+= i 1)
) (if (== ch "\"") (do ) (if (== ch "\"") (do
(let value "") (let value "")
(+= i 1) (+= i 1)
(= ch (at text i)) (= ch (call at text i))
(loop (do (loop (do
(if (or (>= i text_len) (== ch "\"")) (do (if (or (>= i text_len) (== ch "\"")) (do
(break) (break)
@ -650,7 +639,7 @@
(if (>= i text_len) (do (if (>= i text_len) (do
(break) (break)
)) ))
(= ch (at text i)) (= ch (call at text i))
(if (== ch "t") (do (if (== ch "t") (do
(+= value "\t") (+= value "\t")
) (if (== ch "r") (do ) (if (== ch "r") (do
@ -666,37 +655,37 @@
(+= value ch) (+= value ch)
)) ))
(+= i 1) (+= i 1)
(= ch (at text i)) (= ch (call at text i))
)) ))
(if (or (>= i text_len) (!= ch "\"")) (do (if (or (>= i text_len) (!= ch "\"")) (do
(panic "expected '\"' on line %" line) (call panic "expected '\"' on line %" line)
)) ))
(+= i 1) (+= i 1)
(push tokens (list "string" line value)) (call push tokens (list "string" line value))
) (if (contains "0123456789" ch) (do ) (if (call contains "0123456789" ch) (do
(let value "") (let value "")
(loop (do (loop (do
(= ch (at text i)) (= ch (call at text i))
(if (or (>= i text_len) (not (contains "0123456789" ch))) (do (if (or (>= i text_len) (not (call contains "0123456789" ch))) (do
(break) (break)
)) ))
(+= value ch) (+= value ch)
(+= i 1) (+= i 1)
)) ))
(push tokens (list "int" line value)) (call push tokens (list "int" line value))
) (if (contains ident_chars ch) (do ) (if (call contains ident_chars ch) (do
(let value "") (let value "")
(loop (do (loop (do
(= ch (at text i)) (= ch (call at text i))
(if (or (>= i text_len) (not (contains ident_chars ch))) (do (if (or (>= i text_len) (not (call contains ident_chars ch))) (do
(break) (break)
)) ))
(+= value ch) (+= value ch)
(+= i 1) (+= i 1)
)) ))
(push tokens (list "ident" line value)) (call push tokens (list "ident" line value))
) (do ) (do
(println "illegal char '%'" ch) (call println "illegal char '%'" ch)
(+= i 1) (+= i 1)
))))))) )))))))
)) ))
@ -704,11 +693,11 @@
)) ))
(fn contains (text ch) (do (fn contains (text ch) (do
(let text_len (len text)) (let text_len (call len text))
(let i 0) (let i 0)
(loop (do (loop (do
(if (>= i text_len) (break)) (if (>= i text_len) (break))
(if (== (at text i) ch) (do (if (== (call at text i) ch) (do
(return true) (return true)
)) ))
(+= i 1) (+= i 1)
@ -717,15 +706,15 @@
)) ))
(fn slice_eq (str slice_idx substr) (do (fn slice_eq (str slice_idx substr) (do
(let str_len (len str)) (let str_len (call len str))
(let substr_len (len substr)) (let substr_len (call len substr))
(let i 0) (let i 0)
(loop (do (loop (do
(if (>= i substr_len) (if (>= i substr_len)
(return true)) (return true))
(if (>= (+ slice_idx i) str_len) (if (>= (+ slice_idx i) str_len)
(return false)) (return false))
(if (!= (at str (+ slice_idx i)) (at substr i)) (if (!= (call at str (+ slice_idx i)) (call at substr i))
(return false)) (return false))
(+= i 1) (+= i 1)
)) ))
@ -735,13 +724,13 @@
(fn print_expr (expr depth) (do (fn print_expr (expr depth) (do
(let (ty line value) expr) (let (ty line value) expr)
(if (== ty "list") (do (if (== ty "list") (do
(println "%(% %" (indent depth) ty line) (call println "%(% %" (call indent depth) ty line)
(for e value (do (for e value (do
(print_expr e (+ depth 1)) (call print_expr e (+ depth 1))
)) ))
(println "%)" (indent depth)) (call println "%)" (call indent depth))
) (do ) (do
(println "%%" (indent depth) expr) (call println "%%" (call indent depth) expr)
)) ))
)) ))
@ -757,12 +746,12 @@
)) ))
(fn slice (list idx) (do (fn slice (list idx) (do
(let list_len (len list)) (let list_len (call len list))
(let elems (list)) (let elems (list))
(let i idx) (let i idx)
(loop (do (loop (do
(if (>= i list_len) (break)) (if (>= i list_len) (break))
(push elems (at list i)) (call push elems (call at list i))
(+= i 1) (+= i 1)
)) ))
(return elems) (return elems)
@ -770,49 +759,49 @@
(let silent false) (let silent false)
(let (input_filename output_filename) (get_args)) (let (input_filename output_filename) (call get_args))
(if (not silent) (println "reading file '%'..." input_filename)) (if (not silent) (call println "reading file '%'..." input_filename))
(let text (read_text_file input_filename)) (let text (call read_text_file input_filename))
//(println "=== text ===") //(call println "=== text ===")
// (println text) // (call println text)
//(println (len text)) //(call println (call len text))
(if (not silent) (println "tokenizing...")) (if (not silent) (call println "tokenizing..."))
(let tokens (tokenize text)) (let tokens (call tokenize text))
//(println "=== tokens ===") //(call println "=== tokens ===")
//(for elem tokens (do //(for elem tokens (do
// (let (tok line value) elem) // (let (tok line value) elem)
// (if (!= value null) (do // (if (!= value null) (do
// (println "%\t%\t%" line tok value) // (call println "%\t%\t%" line tok value)
// ) (do // ) (do
// (println "%\t%" line tok) // (call println "%\t%" line tok)
// )) // ))
//)) //))
//(println (len tokens)) //(call println (call len tokens))
(if (not silent) (println "parsing...")) (if (not silent) (call println "parsing..."))
(let parser (Parser tokens)) (let parser (call Parser tokens))
(let (parse) parser) (let (parse) parser)
(let ast (parse)) (let ast (call parse))
// (println "=== ast ===") // (call println "=== ast ===")
// (for expr ast (do // (for expr ast (do
// (print_expr expr 0) // (call print_expr expr 0)
// )) // ))
(if (not silent) (println "emitting...")) (if (not silent) (call println "emitting..."))
(let emitter (Emitter ast input_filename)) (let emitter (call Emitter ast input_filename))
(let (emit) emitter) (let (emit) emitter)
(let js_code (emit)) (let js_code (call emit))
// (println "=== js ===") // (call println "=== js ===")
// (println js_code) // (call println js_code)
(if (not silent) (println "writing file '%'..." output_filename)) (if (not silent) (call println "writing file '%'..." output_filename))
(write_text_file output_filename js_code) (call write_text_file output_filename js_code)

1055
stage2.js

File diff suppressed because it is too large Load Diff