compile file

This commit is contained in:
sfja 2025-09-11 23:12:36 +02:00
parent b9b479fd63
commit 09acd55405
4 changed files with 47 additions and 23 deletions

View File

@ -31,9 +31,20 @@
) (if (== ty "string") ( ) (if (== ty "string") (
(let (_ _ value) expr) (let (_ _ value) expr)
(call emit (call format "{ type: \"string\", value: \"%\" }" (call string_escape value))) (call emit (call format "{ type: \"string\", value: \"%\" }" (call string_escape value)))
) (if (== ty "ident") ( ) (if (== ty "ident") (do
(let (_ _ value) expr) (let (_ _ value) expr)
(if (== value "null") (do
(call emit "{ type: \"null\" }")
(return)
) (if (== value "false") (do
(call emit "{ type: \"bool\", value: false }")
(return)
) (if (== value "true") (do
(call emit "{ type: \"bool\", value: true }")
(return)
))))
(let sym (call get_sym value)) (let sym (call get_sym value))
(if (== sym null) (do (if (== sym null) (do
(call panic "undefined symbol '%'" value) (call panic "undefined symbol '%'" value)
@ -43,9 +54,7 @@
(if (== sym_ty "builtin") (do (if (== sym_ty "builtin") (do
(let (_ id) sym) (let (_ id) sym)
(if (== id "println") (do (if (== id "println") (do
(call emit (call format (call emit "((...args) => runtime.builtinPrintln(...args))")
"((...args) => (runtime.setLine(%), runtime.builtinPrintln(...args)))"
line))
) (do ) (do
(call panic "unknown builtin '%'" id) (call panic "unknown builtin '%'" id)
)) ))
@ -83,22 +92,24 @@
(call define_sym name ("fn" name line)) (call define_sym name ("fn" name line))
(call emit (call format ") {\n" name)) (call emit (call format ") {\n" name))
(call emit (call format "runtime.pushCall(\"%\");" name))
(call emit_expr body) (call emit_expr body)
(call emit "}") (call emit "}")
) (if (== id "do") (do ) (if (== id "do") (do
(call emit_exprs (call slice s 1)) (call emit_exprs (call slice s 1))
) (if (== id "return") (do ) (if (== id "return") (do
(let (_ value) s) (let (_ value) s)
(call emit "runtime.popCall();\n")
(call emit "return ") (call emit "return ")
(if (!= value null) (do (if (!= value null) (do
(call emit_expr value) (call emit_expr value)
) (do ) (do
(call emit "null") (call emit "null")
)) ))
(call emit ";")
) (if (== id "call") (do ) (if (== id "call") (do
(let (_ callee) s) (let (_ callee) s)
(let args (call slice s 2)) (let args (call slice s 2))
(call emit (call format "(runtime.setLine(%), " line))
(call emit_expr callee) (call emit_expr callee)
(call emit "(") (call emit "(")
@ -112,7 +123,7 @@
(call emit_expr arg) (call emit_expr arg)
)) ))
(call emit ")") (call emit "))")
) (do ) (do
(call emit "{ type: \"list\", values: [") (call emit "{ type: \"list\", values: [")
(let first true) (let first true)
@ -444,16 +455,17 @@
(return elems) (return elems)
)) ))
(let silent true)
(let input_filename "program.phi") (let (_ input_filename) (call get_args))
(call println "reading file...") (if (not silent) (call println "reading file..."))
(let text (call read_text_file input_filename)) (let text (call read_text_file input_filename))
//(call println "=== text ===") //(call println "=== text ===")
//(call println text) //(call println text)
(call println "tokenizing...") (if (not silent) (call println "tokenizing..."))
(let tokens (call tokenize text)) (let tokens (call tokenize text))
//(call println "=== tokens ===") //(call println "=== tokens ===")
@ -461,7 +473,7 @@
// (call println "%\t%\t%" line tok (if (!= value null) value "")) // (call println "%\t%\t%" line tok (if (!= value null) value ""))
//)) //))
(call println "parsing...") (if (not silent) (call println "parsing..."))
(let parser (call Parser tokens)) (let parser (call Parser tokens))
(let (parse) parser) (let (parse) parser)
(let ast (call parse)) (let ast (call parse))
@ -471,15 +483,15 @@
// (call print_expr expr 0) // (call print_expr expr 0)
//)) //))
(call println "emitting...") (if (not silent) (call println "emitting..."))
(let emitter (call Emitter ast input_filename)) (let emitter (call Emitter ast input_filename))
(let (emit) emitter) (let (emit) emitter)
(let js_code (call emit)) (let js_code (call emit))
(call println "=== js ===") //(call println "=== js ===")
(call println js_code) //(call println js_code)
(call println "writing file...") (if (not silent) (call println "writing file..."))
(call write_text_file "out.js" js_code) (call write_text_file "out.js" js_code)

7
phi.js
View File

@ -21,7 +21,7 @@ function main() {
lastValue = result.value; lastValue = result.value;
} }
if (lastValue !== null) { if (lastValue !== null) {
console.log(Runtime.valueToJs(lastValue)); // console.log(Runtime.valueToJs(lastValue));
} }
} }
@ -58,8 +58,8 @@ class Evaluator {
} else if (expr.type === "ident") { } else if (expr.type === "ident") {
const sym = this.findSym(expr.value); const sym = this.findSym(expr.value);
if (!sym) { if (!sym) {
throw new Error( this.panic(
`could not find symbol '${expr.value}' on line ${expr.line}`, `undefined symbol '${expr.value}'`,
); );
} }
if (sym.type === "local") { if (sym.type === "local") {
@ -431,6 +431,7 @@ class Evaluator {
"string_to_int": (...args) => this.runtime.builtinStringToInt(...args), "string_to_int": (...args) => this.runtime.builtinStringToInt(...args),
"char_code": (...args) => this.runtime.builtinCharCode(...args), "char_code": (...args) => this.runtime.builtinCharCode(...args),
"strings_join": (...args) => this.runtime.builtinStringsJoin(...args), "strings_join": (...args) => this.runtime.builtinStringsJoin(...args),
"get_args": (...args) => this.runtime.builtinGetArgs(...args),
}; };
consts = { consts = {

View File

@ -1,6 +1,7 @@
(fn hello () (do (fn hello () (do
(call println "hello world") (call println "hello world")
(call println "hello world") (call println "hello world")
(return null)
)) ))
(call hello) (call hello)

View File

@ -13,7 +13,7 @@ export class Runtime {
this.currentLine = line; this.currentLine = line;
} }
pushCall(name, line) { pushCall(name, line = this.currentLine) {
this.callStack.push({ name, line }); this.callStack.push({ name, line });
} }
@ -32,13 +32,14 @@ export class Runtime {
} }
printCallStack() { printCallStack() {
const last = this.callStack[this.callStack.length - 1]; const reversedStack = this.callStack.toReversed();
const last = reversedStack[0];
console.error( console.error(
` \x1b[90mat \x1b[37m${last.name} \x1b[90m(${this.filename}:${this.currentLine})\x1b[0m`, ` \x1b[90mat \x1b[37m${last.name} \x1b[90m(${this.filename}:${this.currentLine})\x1b[0m`,
); );
for (let i = this.callStack.length - 2; i >= 0; --i) { for (let i = 0; i < reversedStack.length - 1 && i < 20; ++i) {
const name = this.callStack[i].name; const name = reversedStack[i + 1].name;
const line = this.callStack[i + 1].line; const line = reversedStack[i].line;
console.error( console.error(
` \x1b[90mat \x1b[37m${name} \x1b[90m(${this.filename}:${line})\x1b[0m`, ` \x1b[90mat \x1b[37m${name} \x1b[90m(${this.filename}:${line})\x1b[0m`,
); );
@ -156,6 +157,15 @@ export class Runtime {
}; };
} }
builtinGetArgs() {
return {
type: "list",
values: process.argv
.slice(2)
.map((value) => ({ type: "string", value })),
};
}
static valueToPrint(value) { static valueToPrint(value) {
if (value.type === "null") { if (value.type === "null") {
return "null"; return "null";