implement import

This commit is contained in:
sfja 2025-09-23 19:30:39 +02:00
parent 67cd456762
commit f8ac0f3b6c
3 changed files with 1155 additions and 909 deletions

View File

@ -1,11 +1,12 @@
(fn Emitter (ast filename) (do (fn Emitter (ast initial_filename) (do
(let output (list)) (let output (list))
(let filename initial_filename)
(let (enter_scope leave_scope define_sym get_sym print_syms) (Syms)) (let syms (Syms))
(let (let_node_reg_count let_node_reg_increment) (Counter))
(let (sym_id_count sym_id_increment) (Counter)) (let (sym_id_count sym_id_increment) (Counter))
(let (let_node_reg_count let_node_reg_increment) (Counter))
(let builtin_syms (list (let builtin_syms (list
(list "format" "builtinFormat") (list "format" "builtinFormat")
@ -33,6 +34,7 @@
(define_builtin ident builtin_id) (define_builtin ident builtin_id)
)) ))
(enter_scope)
(discover_syms ast) (discover_syms ast)
(emit_exprs ast) (emit_exprs ast)
(return (strings_join output)) (return (strings_join output))
@ -96,11 +98,17 @@
(emit (format "_%%" value sym_id)) (emit (format "_%%" value sym_id))
) (if (== sym_ty "param") (do ) (if (== sym_ty "param") (do
(emit (format "_%%" value sym_id)) (emit (format "_%%" value sym_id))
) (if (== sym_ty "let") (do ) (if (== sym_ty "let") (do
(emit (format "_%%" value sym_id))
) (if (== sym_ty "imported") (do
// this might give problems in the future.
// the solution is to feed the imported symbol
// back into this code, so that stuff gets
// handled appropriately.
(emit (format "_%%" value sym_id)) (emit (format "_%%" value sym_id))
) (do ) (do
(panic "not implemented '%'" sym_ty) (panic "not implemented '%'" sym_ty)
))))) ))))))
) (do ) (do
(panic "unknown expr type '%' on line %" ty line) (panic "unknown expr type '%' on line %" ty line)
))))) )))))
@ -115,7 +123,57 @@
(if (!= id_ty "ident") (do (if (!= id_ty "ident") (do
(panic "illegal function on line %" line) (panic "illegal function on line %" line)
)) ))
(if (== id "fn") (do (if (== id "import") (do
(let outer_filename filename)
(let (_ (_ _ inner_filename) (_ _ idents)) s)
(= filename inner_filename)
(let text (read_text_file filename))
(let tokens (tokenize text))
(let parser (Parser tokens))
(let (parse) parser)
(let ast (parse))
(let (_ generate_imported) (Emitter ast filename))
(emit (format "runtime.setFile(\"%\");\n" filename))
(let outer_syms syms)
(= syms (Syms))
(for (ident builtin_id) builtin_syms (do
(define_builtin ident builtin_id)
))
(enter_scope)
(discover_syms ast)
(emit_exprs ast)
(let sym_map (get_current_map))
(= syms outer_syms)
(= filename outer_filename)
(emit (format "runtime.setFile(\"%\");\n" outer_filename))
(for (_ _ ident) idents (do
(let sym null)
(for (sym_ident found_sym) sym_map (do
(if (== sym_ident ident) (do
(= sym found_sym)
(break)
))
))
(if (== sym null) (do
(println "sym_map = %" sym_map)
(panic "no symbol '%' from imported '%'" ident filename)
))
(let (_ sym_type) sym)
(if (== sym_type "imported") (do
(define_sym ident sym)
) (do
(let (sym_id) sym)
(define_sym ident (list sym_id "imported" sym))
))
))
) (if (== id "fn") (do
(let (_ (_ _ ident) (_ _ params) body) s) (let (_ (_ _ ident) (_ _ params) body) s)
(let sym (get_sym ident)) (let sym (get_sym ident))
@ -138,7 +196,7 @@
(emit ") {\n") (emit ") {\n")
(emit (format "runtime.pushCall(\"%\");\n" ident)) (emit (format "runtime.pushCall(\"%\", \"%\");\n" ident filename))
(emit_expr body) (emit_expr body)
(emit ";\nruntime.popCall();\nreturn { type: \"null\" };\n}") (emit ";\nruntime.popCall();\nreturn { type: \"null\" };\n}")
@ -210,7 +268,7 @@
) (if (== id "call") (do ) (if (== id "call") (do
(let (_ callee) s) (let (_ callee) s)
(let args (slice s 2)) (let args (slice s 2))
(emit (format "(runtime.setLine(%), " line)) (emit (format "(%, " (rt_info line)))
(emit_expr callee) (emit_expr callee)
(emit "(") (emit "(")
@ -235,7 +293,7 @@
(emit_assign_expr s line "-") (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)) (emit (format "(%" (rt_info line) line))
(emit ", { type: \"bool\", value: runtime.truthy(") (emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left) (emit_expr left)
(emit ") || runtime.truthy(") (emit ") || runtime.truthy(")
@ -243,7 +301,7 @@
(emit ") })") (emit ") })")
) (if (== id "and") (do ) (if (== id "and") (do
(let (_ left right) s) (let (_ left right) s)
(emit (format "(runtime.setLine(%)" line)) (emit (format "(%" (rt_info line) line))
(emit ", { type: \"bool\", value: runtime.truthy(") (emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left) (emit_expr left)
(emit ") && runtime.truthy(") (emit ") && runtime.truthy(")
@ -273,7 +331,7 @@
) (do ) (do
(let (callee) s) (let (callee) s)
(let args (slice s 1)) (let args (slice s 1))
(emit (format "(runtime.setLine(%), " line)) (emit (format "(%, " (rt_info line) line))
(emit_expr callee) (emit_expr callee)
(emit "(") (emit "(")
@ -288,7 +346,7 @@
)) ))
(emit "))") (emit "))")
))))))))))))))))))))))))) ))))))))))))))))))))))))))
)) ))
(fn emit_list_literal (s) (do (fn emit_list_literal (s) (do
@ -334,12 +392,16 @@
)) ))
(fn emit_binary_op (s id) (do (fn emit_binary_op (s id) (do
(let (_ left right) s) (let ((_ line _) left right) s)
(emit (format "runtime.%(" id)) (emit (format "(%, runtime.%(" (rt_info line) id))
(emit_expr left) (emit_expr left)
(emit ", ") (emit ", ")
(emit_expr right) (emit_expr right)
(emit ")") (emit "))")
))
(fn rt_info (line) (do
(return (format "runtime.info(\"%\", %)" filename line))
)) ))
(fn emit_assign_expr (s line id) (do (fn emit_assign_expr (s line id) (do
@ -410,6 +472,32 @@
(return sym_id) (return sym_id)
)) ))
// indirection for syms
(fn enter_scope () (do
(let (enter_scope) syms)
(enter_scope)
))
(fn leave_scope () (do
(let (_ leave_scope) syms)
(leave_scope)
))
(fn define_sym (ident sym) (do
(let (_ _ define_sym) syms)
(return (define_sym ident sym))
))
(fn get_sym (ident) (do
(let (_ _ _ get_sym) syms)
(return (get_sym ident))
))
(fn get_current_map () (do
(let (_ _ _ _ get_current_map) syms)
(return (get_current_map))
))
(fn print_syms () (do
(let (_ _ _ _ _ print_syms) syms)
(print_syms)
))
(return (list generate)) (return (list generate))
)) ))
@ -439,7 +527,7 @@
(= syms parent) (= syms parent)
)) ))
(fn define (ident sym) (do (fn define_sym (ident sym) (do
(let (_ map) syms) (let (_ map) syms)
(let i 0) (let i 0)
(loop (do (loop (do
@ -471,10 +559,15 @@
(return null) (return null)
)) ))
(fn get (ident) (do (fn get_sym (ident) (do
(return (find_sym syms ident)) (return (find_sym syms ident))
)) ))
(fn get_current_map () (do
(let (_ map) syms)
(return map)
))
(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
@ -492,8 +585,9 @@
(return (list (return (list
enter_scope enter_scope
leave_scope leave_scope
define define_sym
get get_sym
get_current_map
print_syms print_syms
)) ))
)) ))
@ -750,42 +844,15 @@
(return elems) (return elems)
)) ))
(let silent false)
(let (input_filename output_filename) (get_args)) (let (input_filename output_filename) (get_args))
(if (not silent) (println "reading file '%'..." input_filename)) (println "compiling '%'..." input_filename)
(let text (read_text_file input_filename)) (let text (read_text_file input_filename))
//(println "=== text ===")
// (println text)
//(println (len text))
(if (not silent) (println "tokenizing..."))
(let tokens (tokenize text)) (let tokens (tokenize text))
//(println "=== tokens ===")
//(for elem tokens (do
// (let (tok line value) elem)
// (if (!= value null) (do
// (println "%\t%\t%" line tok value)
// ) (do
// (println "%\t%" line tok)
// ))
//))
//(println (len tokens))
(if (not silent) (println "parsing..."))
(let parser (Parser tokens)) (let parser (Parser tokens))
(let (parse) parser) (let (parse) parser)
(let ast (parse)) (let ast (parse))
// (println "=== ast ===")
// (for expr ast (do
// (print_expr expr 0)
// ))
(if (not silent) (println "emitting..."))
(let emitter (Emitter ast input_filename)) (let emitter (Emitter ast input_filename))
(let (emit) emitter) (let (emit) emitter)
(let js_code (emit)) (let js_code (emit))
@ -793,8 +860,8 @@
// (println "=== js ===") // (println "=== js ===")
// (println js_code) // (println js_code)
(if (not silent) (println "writing file '%'..." output_filename))
(write_text_file output_filename js_code) (write_text_file output_filename js_code)
(println "written '%'!" output_filename)

View File

@ -16,7 +16,12 @@ export class Runtime {
this.currentLine = line; this.currentLine = line;
} }
pushCall(name, filename = this.filename, line = this.currentLine) { info(filename, line) {
this.currentFilename = filename;
this.currentLine = line;
}
pushCall(name, filename, line = this.currentLine) {
this.callStack.push({ name, filename, line }); this.callStack.push({ name, filename, line });
} }
@ -41,8 +46,8 @@ export class Runtime {
` \x1b[90mat \x1b[37m${last.name} \x1b[90m(${this.currentFilename}:${this.currentLine})\x1b[0m`, ` \x1b[90mat \x1b[37m${last.name} \x1b[90m(${this.currentFilename}:${this.currentLine})\x1b[0m`,
); );
for (let i = 0; i < reversedStack.length - 1 && i < 20; ++i) { for (let i = 0; i < reversedStack.length - 1 && i < 20; ++i) {
const name = reversedStack[i + 1].name; const { name, filename } = reversedStack[i + 1];
const { filename, line } = reversedStack[i]; const { line } = reversedStack[i];
console.error( console.error(
` \x1b[90mat \x1b[37m${name} \x1b[90m(${filename}:${line})\x1b[0m`, ` \x1b[90mat \x1b[37m${name} \x1b[90m(${filename}:${line})\x1b[0m`,
); );

1890
stage2.js

File diff suppressed because it is too large Load Diff