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 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 (let_node_reg_count let_node_reg_increment) (Counter))
(let builtin_syms (list
(list "format" "builtinFormat")
@ -33,6 +34,7 @@
(define_builtin ident builtin_id)
))
(enter_scope)
(discover_syms ast)
(emit_exprs ast)
(return (strings_join output))
@ -96,11 +98,17 @@
(emit (format "_%%" value sym_id))
) (if (== sym_ty "param") (do
(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))
) (do
(panic "not implemented '%'" sym_ty)
)))))
))))))
) (do
(panic "unknown expr type '%' on line %" ty line)
)))))
@ -115,7 +123,57 @@
(if (!= id_ty "ident") (do
(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 sym (get_sym ident))
@ -138,7 +196,7 @@
(emit ") {\n")
(emit (format "runtime.pushCall(\"%\");\n" ident))
(emit (format "runtime.pushCall(\"%\", \"%\");\n" ident filename))
(emit_expr body)
(emit ";\nruntime.popCall();\nreturn { type: \"null\" };\n}")
@ -210,7 +268,7 @@
) (if (== id "call") (do
(let (_ callee) s)
(let args (slice s 2))
(emit (format "(runtime.setLine(%), " line))
(emit (format "(%, " (rt_info line)))
(emit_expr callee)
(emit "(")
@ -235,7 +293,7 @@
(emit_assign_expr s line "-")
) (if (== id "or") (do
(let (_ left right) s)
(emit (format "(runtime.setLine(%)" line))
(emit (format "(%" (rt_info line) line))
(emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left)
(emit ") || runtime.truthy(")
@ -243,7 +301,7 @@
(emit ") })")
) (if (== id "and") (do
(let (_ left right) s)
(emit (format "(runtime.setLine(%)" line))
(emit (format "(%" (rt_info line) line))
(emit ", { type: \"bool\", value: runtime.truthy(")
(emit_expr left)
(emit ") && runtime.truthy(")
@ -273,7 +331,7 @@
) (do
(let (callee) s)
(let args (slice s 1))
(emit (format "(runtime.setLine(%), " line))
(emit (format "(%, " (rt_info line) line))
(emit_expr callee)
(emit "(")
@ -288,7 +346,7 @@
))
(emit "))")
)))))))))))))))))))))))))
))))))))))))))))))))))))))
))
(fn emit_list_literal (s) (do
@ -334,12 +392,16 @@
))
(fn emit_binary_op (s id) (do
(let (_ left right) s)
(emit (format "runtime.%(" id))
(let ((_ line _) left right) s)
(emit (format "(%, runtime.%(" (rt_info line) id))
(emit_expr left)
(emit ", ")
(emit_expr right)
(emit ")")
(emit "))")
))
(fn rt_info (line) (do
(return (format "runtime.info(\"%\", %)" filename line))
))
(fn emit_assign_expr (s line id) (do
@ -410,6 +472,32 @@
(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))
))
@ -439,7 +527,7 @@
(= syms parent)
))
(fn define (ident sym) (do
(fn define_sym (ident sym) (do
(let (_ map) syms)
(let i 0)
(loop (do
@ -471,10 +559,15 @@
(return null)
))
(fn get (ident) (do
(fn get_sym (ident) (do
(return (find_sym syms ident))
))
(fn get_current_map () (do
(let (_ map) syms)
(return map)
))
(fn print_syms_node (syms depth) (do
(let (parent map) syms)
(for (ident sym) map (do
@ -492,8 +585,9 @@
(return (list
enter_scope
leave_scope
define
get
define_sym
get_sym
get_current_map
print_syms
))
))
@ -750,42 +844,15 @@
(return elems)
))
(let silent false)
(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))
//(println "=== text ===")
// (println text)
//(println (len text))
(if (not silent) (println "tokenizing..."))
(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 (parse) parser)
(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 (emit) emitter)
(let js_code (emit))
@ -793,8 +860,8 @@
// (println "=== js ===")
// (println js_code)
(if (not silent) (println "writing file '%'..." output_filename))
(write_text_file output_filename js_code)
(println "written '%'!" output_filename)

View File

@ -16,7 +16,12 @@ export class Runtime {
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 });
}
@ -41,8 +46,8 @@ export class Runtime {
` \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) {
const name = reversedStack[i + 1].name;
const { filename, line } = reversedStack[i];
const { name, filename } = reversedStack[i + 1];
const { line } = reversedStack[i];
console.error(
` \x1b[90mat \x1b[37m${name} \x1b[90m(${filename}:${line})\x1b[0m`,
);

1890
stage2.js

File diff suppressed because it is too large Load Diff