fix call stuff

This commit is contained in:
sfja 2024-12-13 06:09:10 +01:00
parent d9d08dc2ed
commit 18eddd82a4
7 changed files with 163 additions and 203 deletions

View File

@ -50,85 +50,16 @@ export const Builtins = {
ArrayLength: 0x24,
StructSet: 0x30,
Print: 0x40,
} as const;
export function opToString(op: number): string {
switch (op) {
case Ops.Nop:
return "Nop";
case Ops.PushNull:
return "PushNull";
case Ops.PushInt:
return "PushInt";
case Ops.PushBool:
return "PushBool";
case Ops.PushString:
return "PushString";
case Ops.PushPtr:
return "PushPtr";
case Ops.Pop:
return "Pop";
case Ops.ReserveStatic:
return "ReserveStatic";
case Ops.LoadStatic:
return "LoadStatic";
case Ops.StoreStatic:
return "StoreStatic";
case Ops.LoadLocal:
return "LoadLocal";
case Ops.StoreLocal:
return "StoreLocal";
case Ops.Call:
return "Call";
case Ops.Return:
return "Return";
case Ops.Jump:
return "Jump";
case Ops.JumpIfTrue:
return "JumpIfTrue";
case Ops.Builtin:
return "Builtin";
case Ops.Add:
return "Add";
case Ops.Subtract:
return "Subtract";
case Ops.Multiply:
return "Multiply";
case Ops.Divide:
return "Divide";
case Ops.Remainder:
return "Remainder";
case Ops.Equal:
return "Equal";
case Ops.LessThan:
return "LessThan";
case Ops.And:
return "And";
case Ops.Or:
return "Or";
case Ops.Xor:
return "Xor";
case Ops.Not:
return "Not";
case Ops.SourceMap:
return "SourceMap";
default:
return `<unknown Op ${op}>`;
}
return Object.entries(Ops)
.find(([_key, value]) => value === op)
?.[0] ?? `<unknown Op ${op}>`;
}
export function builtinToString(builtin: number): string {
switch (builtin) {
case Builtins.StringConcat: return "StringConcat";
case Builtins.StringEqual: return "StringEqual";
case Builtins.StringCharAt: return "StringCharAt";
case Builtins.StringLength: return "StringLength";
case Builtins.StringPushChar: return "StringPushChar";
case Builtins.ArraySet: return "ArraySet";
case Builtins.StructSet: return "StructSet";
case Builtins.Print: return "Print";
default:
return `<unknown Builtin ${builtin}>`;
}
return Object.entries(Builtins)
.find(([_key, value]) => value === builtin)
?.[0] ?? `<unknown Builtin ${builtin}>`;
}

View File

@ -19,7 +19,7 @@ export class Reporter {
private printReport({ reporter, type, pos, msg }: Report) {
console.error(
`${reporter}: ${type}: ${msg}${
`${reporter} ${type}: ${msg}${
pos ? ` at ${pos.line}:${pos.col}` : ""
}`,
);

View File

@ -113,7 +113,8 @@ export class Lowerer {
if (stmt.kind.expr) {
this.lowerExpr(stmt.kind.expr);
}
this.program.add(Ops.Jump, this.breakStack.at(-1)!);
this.program.add(Ops.PushPtr, this.breakStack.at(-1)!);
this.program.add(Ops.Jump);
}
private lowerBuiltinAnno(annoArgs: Expr[]) {
@ -127,49 +128,15 @@ export class Lowerer {
);
}
const value = anno.kind.value;
switch (value) {
case "Print": {
this.program.add(Ops.Builtin, Builtins.Print);
break;
}
case "StringLength": {
this.program.add(Ops.Builtin, Builtins.StringLength);
break;
}
case "StringCharAt": {
this.program.add(Ops.Builtin, Builtins.StringCharAt);
break;
}
case "StringPushChar": {
this.program.add(Ops.Builtin, Builtins.StringPushChar);
break;
}
case "ArrayNew": {
this.program.add(Ops.Builtin, Builtins.ArrayNew);
break;
}
case "ArraySet": {
this.program.add(Ops.Builtin, Builtins.ArraySet);
break;
}
case "ArrayPush": {
this.program.add(Ops.Builtin, Builtins.ArrayPush);
break;
}
case "ArrayLength": {
this.program.add(Ops.Builtin, Builtins.ArrayLength);
break;
}
case "ArrayAt": {
this.program.add(Ops.Builtin, Builtins.ArrayAt);
break;
}
default: {
throw new Error(
`unrecognized builtin '${value}'`,
);
}
const builtin = Object.entries(Builtins).find((entry) =>
entry[0] === value
)?.[1];
if (builtin === undefined) {
throw new Error(
`unrecognized builtin '${value}'`,
);
}
this.program.add(Ops.Builtin, builtin);
}
private lowerFnStmt(stmt: Stmt) {
@ -238,7 +205,7 @@ export class Lowerer {
case "ident":
break;
case "group":
break;
return void this.lowerExpr(expr.kind.expr);
case "field":
break;
case "index":
@ -246,7 +213,7 @@ export class Lowerer {
case "call":
return this.lowerCallExpr(expr);
case "unary":
break;
return this.lowerUnaryExpr(expr);
case "binary":
return this.lowerBinaryExpr(expr);
case "if":
@ -299,6 +266,28 @@ export class Lowerer {
this.program.add(Ops.PushString, expr.kind.value);
}
private lowerUnaryExpr(expr: Expr) {
if (expr.kind.type !== "unary") {
throw new Error();
}
this.lowerExpr(expr.kind.subject);
const vtype = expr.kind.subject.vtype!;
if (vtype.type === "bool") {
switch (expr.kind.unaryType) {
case "not":
this.program.add(Ops.Not);
return;
default:
}
}
throw new Error(
`unhandled unary` +
` '${vtypeToString(expr.vtype!)}' aka. ` +
` ${expr.kind.unaryType}` +
` '${vtypeToString(expr.kind.subject.vtype!)}'`,
);
}
private lowerBinaryExpr(expr: Expr) {
if (expr.kind.type !== "binary") {
throw new Error();
@ -320,6 +309,9 @@ export class Lowerer {
case "==":
this.program.add(Ops.Equal);
return;
case "<":
this.program.add(Ops.LessThan);
return;
case ">=":
this.program.add(Ops.LessThan);
this.program.add(Ops.Not);
@ -403,7 +395,8 @@ export class Lowerer {
this.program.setLabel(contineLabel);
this.lowerExpr(expr.kind.body);
this.program.add(Ops.PushPtr, breakLabel);
this.program.add(Ops.Pop);
this.program.add(Ops.PushPtr, contineLabel);
this.program.add(Ops.Jump);
this.program.setLabel(breakLabel);
if (expr.vtype!.type === "null") {

View File

@ -1,19 +1,16 @@
fn array_new_string() -> [string] #[builtin(ArrayNew)] {}
fn print(msg: string) #[builtin(Print)] {}
fn println(msg: string) { print(msg + "\n") }
fn array_push_string(array: [string], str: string) #[builtin(ArrayPush)] {}
fn string_push_char(str: string, value: int) #[builtin(StringPushChar)] {}
fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {}
fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {}
fn string_length(str: string) -> int #[builtin(StringLength)] {}
fn array_string_length(array: [string]) -> int #[builtin(StringLength)] {}
fn array_string_at(array: [string], index: int) -> string #[builtin(ArrayAt)] {}
fn array_new_string() -> [string] #[builtin(ArrayNew)] {}
fn array_push_string(array: [string], value: string) #[builtin(ArrayPush)] {}
fn array_length_string(array: [string]) -> int #[builtin(ArrayLength)] {}
fn array_at_string(array: [string], index: int) -> string #[builtin(ArrayAt)] {}
fn char(ch: string) -> int {
string_char_at(ch, 0)
@ -25,6 +22,9 @@ fn split(str: string, seperator: int) -> [string] {
let i = 0;
let current_str = "";
loop {
if i >= string_length(str) {
break;
}
let char = string_char_at(str, i);
if char == seperator {
array_push_string(result, current_str);
@ -32,9 +32,6 @@ fn split(str: string, seperator: int) -> [string] {
} else {
string_push_char(current_str, char);
}
if string_length(str) - 1 == i {
break;
}
i = i + 1;
}
result
@ -43,11 +40,13 @@ fn split(str: string, seperator: int) -> [string] {
fn main() {
let array = split("aoisfjasoifjsaiofjsa", char("a"));
let i = 0;
let array_length = array_length_string(array);
loop {
print(array_string_at(array, i) + "\n");
i = i + 1;
if array_string_length(array) - 1 == i {
if i >= array_length {
break;
}
let v = array_at_string(array, 0);
println(v);
i = i + 1;
}
}

View File

@ -0,0 +1,25 @@
fn print(msg: string) #[builtin(Print)] {}
fn repeat(value: string, amount: int) -> string {
let result = "";
let i = 0;
loop {
if not (i < amount) {
break;
}
result = result + value;
i = i + 1;
}
result
}
fn main() {
let value = repeat("hello world\n", 3);
print(value);
}

View File

@ -30,8 +30,13 @@ void VM::run_n_instructions(size_t amount)
void VM::run_instruction()
{
if (this->opts.print_stack_debug) {
// std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
// maybe_op_to_string(this->program[this->pc]),
// stack_repr_string(8));
auto stack_frame_size = this->stack.size() - this->bp;
std::cout << std::format(" {:>4}: {:<12}{}\n", this->pc,
maybe_op_to_string(this->program[this->pc]), stack_repr_string(8));
maybe_op_to_string(this->program[this->pc]),
stack_repr_string(stack_frame_size));
}
auto op = eat_op();
switch (op) {
@ -125,11 +130,9 @@ void VM::run_instruction()
stack_push(Ptr { .value = this->bp });
this->pc = fn_ptr.as_ptr().value;
this->bp = static_cast<uint32_t>(this->stack.size());
// for (size_t i = arguments.size(); i > 0; --i) {
// stack_push(std::move(arguments.at(i - 1)));
// }
for (size_t i = 0; i < arguments.size(); ++i) {
stack_push(std::move(arguments.at(i)));
for (auto&& arg = arguments.rbegin(); arg != arguments.rend();
++arg) {
stack_push(*arg);
}
if (this->opts.flame_graph) {
this->flame_graph.report_call(
@ -277,20 +280,57 @@ void VM::run_instruction()
void VM::run_builtin(Builtin builtin_id)
{
if (this->opts.print_stack_debug) {
std::cout << std::format(
"Running builtin {}\n", static_cast<uint32_t>(builtin_id));
}
switch (builtin_id) {
case Builtin::StringConcat: {
assert_stack_has(2);
auto left = stack_pop();
auto right = stack_pop();
auto left = stack_pop();
stack_push(
String(right.as_string().value + left.as_string().value));
String(left.as_string().value + right.as_string().value));
break;
}
case Builtin::StringEqual: {
assert_stack_has(2);
auto left = stack_pop();
auto right = stack_pop();
stack_push(Bool(right.as_string().value == left.as_string().value));
auto left = stack_pop();
stack_push(Bool(left.as_string().value == right.as_string().value));
break;
}
case Builtin::StringCharAt: {
assert_stack_has(2);
auto index_value = stack_pop();
auto str = stack_pop();
auto index = static_cast<size_t>(index_value.as_int().value);
auto ch = static_cast<int32_t>(str.as_string().value.at(index));
stack_push(Int(ch));
break;
}
case Builtin::StringLength: {
assert_stack_has(1);
auto str = stack_pop().as_string().value;
auto length = static_cast<int32_t>(str.length());
stack_push(Int(length));
break;
}
case Builtin::StringPushChar: {
assert_stack_has(2);
auto ch = stack_pop();
auto str = stack_pop();
auto new_str = std::string(str.as_string().value);
new_str.push_back(static_cast<char>(ch.as_int().value));
stack_push(String(new_str));
break;
}
case Builtin::ArrayNew: {
auto alloc_res = this->heap.alloc<heap::AllocType::Array>();
stack_push(Ptr(alloc_res.val()));
break;
}
case Builtin::ArraySet: {
@ -299,6 +339,32 @@ void VM::run_builtin(Builtin builtin_id)
std::exit(1);
break;
}
case Builtin::ArrayPush: {
assert_stack_has(2);
auto value = stack_pop();
auto array_ptr = stack_pop().as_ptr().value;
this->heap.at(array_ptr).val()->as_array().values.push_back(value);
stack_push(Null());
break;
}
case Builtin::ArrayAt: {
assert_stack_has(2);
auto index = stack_pop().as_int().value;
auto array_ptr = stack_pop().as_ptr().value;
auto array = this->heap.at(array_ptr).val()->as_array();
stack_push(array.values.at(static_cast<size_t>(index)));
break;
}
case Builtin::ArrayLength: {
assert_stack_has(1);
auto array_ptr = stack_pop().as_ptr().value;
auto array = this->heap.at(array_ptr).val()->as_array();
stack_push(Int(static_cast<int32_t>(array.values.size())));
break;
}
case Builtin::StructSet: {
assert_stack_has(2);
std::cerr << std::format("not implemented\n");
@ -312,59 +378,5 @@ void VM::run_builtin(Builtin builtin_id)
stack_push(Null());
break;
}
case Builtin::StringCharAt: {
assert_stack_has(2);
auto str = stack_pop();
auto index_value = stack_pop();
auto index = static_cast<size_t>(index_value.as_int().value);
auto ch = static_cast<int32_t>(str.as_string().value.at(index));
stack_push(Int(ch));
break;
}
case Builtin::StringLength: {
assert_stack_has(1);
auto str = stack_pop().as_string().value;
auto length = static_cast<int32_t>(str.length());
stack_push(Int(length));
break;
}
case Builtin::StringPushChar: {
assert_stack_has(2);
auto str = stack_pop();
auto ch = stack_pop();
auto new_str = std::string(str.as_string().value);
new_str.push_back(static_cast<char>(ch.as_int().value));
stack_push(String(new_str));
break;
}
case Builtin::ArrayNew: {
auto alloc_res = this->heap.alloc<heap::AllocType::Array>();
stack_push(Ptr(alloc_res.val()));
break;
}
case Builtin::ArrayPush: {
assert_stack_has(2);
auto array_ptr = stack_pop().as_ptr().value;
auto value = stack_pop();
auto array = this->heap.at(array_ptr).val()->as_array();
array.values.push_back(value);
stack_push(Null());
break;
}
case Builtin::ArrayAt: {
assert_stack_has(2);
auto array_ptr = stack_pop().as_ptr().value;
auto index = stack_pop().as_int().value;
auto array = this->heap.at(array_ptr).val()->as_array();
stack_push(array.values.at(static_cast<size_t>(index)));
break;
}
case Builtin::ArrayLength: {
assert_stack_has(1);
auto array_ptr = stack_pop().as_ptr().value;
auto array = this->heap.at(array_ptr).val()->as_array();
stack_push(Int(static_cast<int32_t>(array.values.size())));
break;
}
}
}

View File

@ -185,8 +185,8 @@ public:
result += std::format(
"{:<11}", stack[stack.size() - i - 1].to_repr_string());
}
if (stack.size() >= max_items) {
result += std::format(" ... + {}", stack.size() - max_items + 1);
if (stack.size() > max_items) {
result += std::format(" ... + {}", stack.size() - max_items);
}
return result;
}