mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 13:06:30 +00:00
fix call stuff
This commit is contained in:
parent
d9d08dc2ed
commit
18eddd82a4
@ -50,85 +50,16 @@ export const Builtins = {
|
|||||||
ArrayLength: 0x24,
|
ArrayLength: 0x24,
|
||||||
StructSet: 0x30,
|
StructSet: 0x30,
|
||||||
Print: 0x40,
|
Print: 0x40,
|
||||||
|
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export function opToString(op: number): string {
|
export function opToString(op: number): string {
|
||||||
switch (op) {
|
return Object.entries(Ops)
|
||||||
case Ops.Nop:
|
.find(([_key, value]) => value === op)
|
||||||
return "Nop";
|
?.[0] ?? `<unknown Op ${op}>`;
|
||||||
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}>`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function builtinToString(builtin: number): string {
|
export function builtinToString(builtin: number): string {
|
||||||
switch (builtin) {
|
return Object.entries(Builtins)
|
||||||
case Builtins.StringConcat: return "StringConcat";
|
.find(([_key, value]) => value === builtin)
|
||||||
case Builtins.StringEqual: return "StringEqual";
|
?.[0] ?? `<unknown Builtin ${builtin}>`;
|
||||||
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}>`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export class Reporter {
|
|||||||
|
|
||||||
private printReport({ reporter, type, pos, msg }: Report) {
|
private printReport({ reporter, type, pos, msg }: Report) {
|
||||||
console.error(
|
console.error(
|
||||||
`${reporter}: ${type}: ${msg}${
|
`${reporter} ${type}: ${msg}${
|
||||||
pos ? ` at ${pos.line}:${pos.col}` : ""
|
pos ? ` at ${pos.line}:${pos.col}` : ""
|
||||||
}`,
|
}`,
|
||||||
);
|
);
|
||||||
|
@ -113,7 +113,8 @@ export class Lowerer {
|
|||||||
if (stmt.kind.expr) {
|
if (stmt.kind.expr) {
|
||||||
this.lowerExpr(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[]) {
|
private lowerBuiltinAnno(annoArgs: Expr[]) {
|
||||||
@ -127,49 +128,15 @@ export class Lowerer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const value = anno.kind.value;
|
const value = anno.kind.value;
|
||||||
switch (value) {
|
const builtin = Object.entries(Builtins).find((entry) =>
|
||||||
case "Print": {
|
entry[0] === value
|
||||||
this.program.add(Ops.Builtin, Builtins.Print);
|
)?.[1];
|
||||||
break;
|
if (builtin === undefined) {
|
||||||
}
|
throw new Error(
|
||||||
case "StringLength": {
|
`unrecognized builtin '${value}'`,
|
||||||
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}'`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
this.program.add(Ops.Builtin, builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private lowerFnStmt(stmt: Stmt) {
|
private lowerFnStmt(stmt: Stmt) {
|
||||||
@ -238,7 +205,7 @@ export class Lowerer {
|
|||||||
case "ident":
|
case "ident":
|
||||||
break;
|
break;
|
||||||
case "group":
|
case "group":
|
||||||
break;
|
return void this.lowerExpr(expr.kind.expr);
|
||||||
case "field":
|
case "field":
|
||||||
break;
|
break;
|
||||||
case "index":
|
case "index":
|
||||||
@ -246,7 +213,7 @@ export class Lowerer {
|
|||||||
case "call":
|
case "call":
|
||||||
return this.lowerCallExpr(expr);
|
return this.lowerCallExpr(expr);
|
||||||
case "unary":
|
case "unary":
|
||||||
break;
|
return this.lowerUnaryExpr(expr);
|
||||||
case "binary":
|
case "binary":
|
||||||
return this.lowerBinaryExpr(expr);
|
return this.lowerBinaryExpr(expr);
|
||||||
case "if":
|
case "if":
|
||||||
@ -299,6 +266,28 @@ export class Lowerer {
|
|||||||
this.program.add(Ops.PushString, expr.kind.value);
|
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) {
|
private lowerBinaryExpr(expr: Expr) {
|
||||||
if (expr.kind.type !== "binary") {
|
if (expr.kind.type !== "binary") {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
@ -320,6 +309,9 @@ export class Lowerer {
|
|||||||
case "==":
|
case "==":
|
||||||
this.program.add(Ops.Equal);
|
this.program.add(Ops.Equal);
|
||||||
return;
|
return;
|
||||||
|
case "<":
|
||||||
|
this.program.add(Ops.LessThan);
|
||||||
|
return;
|
||||||
case ">=":
|
case ">=":
|
||||||
this.program.add(Ops.LessThan);
|
this.program.add(Ops.LessThan);
|
||||||
this.program.add(Ops.Not);
|
this.program.add(Ops.Not);
|
||||||
@ -403,7 +395,8 @@ export class Lowerer {
|
|||||||
|
|
||||||
this.program.setLabel(contineLabel);
|
this.program.setLabel(contineLabel);
|
||||||
this.lowerExpr(expr.kind.body);
|
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.add(Ops.Jump);
|
||||||
this.program.setLabel(breakLabel);
|
this.program.setLabel(breakLabel);
|
||||||
if (expr.vtype!.type === "null") {
|
if (expr.vtype!.type === "null") {
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
|
|
||||||
fn array_new_string() -> [string] #[builtin(ArrayNew)] {}
|
|
||||||
|
|
||||||
fn print(msg: string) #[builtin(Print)] {}
|
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) -> string #[builtin(StringPushChar)] {}
|
||||||
|
|
||||||
fn string_push_char(str: string, value: int) #[builtin(StringPushChar)] {}
|
|
||||||
|
|
||||||
fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {}
|
fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {}
|
||||||
|
|
||||||
fn string_length(str: string) -> int #[builtin(StringLength)] {}
|
fn string_length(str: string) -> int #[builtin(StringLength)] {}
|
||||||
|
|
||||||
fn array_string_length(array: [string]) -> int #[builtin(StringLength)] {}
|
fn array_new_string() -> [string] #[builtin(ArrayNew)] {}
|
||||||
|
fn array_push_string(array: [string], value: string) #[builtin(ArrayPush)] {}
|
||||||
fn array_string_at(array: [string], index: int) -> string #[builtin(ArrayAt)] {}
|
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 {
|
fn char(ch: string) -> int {
|
||||||
string_char_at(ch, 0)
|
string_char_at(ch, 0)
|
||||||
@ -25,6 +22,9 @@ fn split(str: string, seperator: int) -> [string] {
|
|||||||
let i = 0;
|
let i = 0;
|
||||||
let current_str = "";
|
let current_str = "";
|
||||||
loop {
|
loop {
|
||||||
|
if i >= string_length(str) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
let char = string_char_at(str, i);
|
let char = string_char_at(str, i);
|
||||||
if char == seperator {
|
if char == seperator {
|
||||||
array_push_string(result, current_str);
|
array_push_string(result, current_str);
|
||||||
@ -32,9 +32,6 @@ fn split(str: string, seperator: int) -> [string] {
|
|||||||
} else {
|
} else {
|
||||||
string_push_char(current_str, char);
|
string_push_char(current_str, char);
|
||||||
}
|
}
|
||||||
if string_length(str) - 1 == i {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
@ -43,11 +40,13 @@ fn split(str: string, seperator: int) -> [string] {
|
|||||||
fn main() {
|
fn main() {
|
||||||
let array = split("aoisfjasoifjsaiofjsa", char("a"));
|
let array = split("aoisfjasoifjsaiofjsa", char("a"));
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
let array_length = array_length_string(array);
|
||||||
loop {
|
loop {
|
||||||
print(array_string_at(array, i) + "\n");
|
if i >= array_length {
|
||||||
i = i + 1;
|
|
||||||
if array_string_length(array) - 1 == i {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
let v = array_at_string(array, 0);
|
||||||
|
println(v);
|
||||||
|
i = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
examples/string_int_args.slg
Normal file
25
examples/string_int_args.slg
Normal 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);
|
||||||
|
}
|
||||||
|
|
140
runtime/vm.cpp
140
runtime/vm.cpp
@ -30,8 +30,13 @@ void VM::run_n_instructions(size_t amount)
|
|||||||
void VM::run_instruction()
|
void VM::run_instruction()
|
||||||
{
|
{
|
||||||
if (this->opts.print_stack_debug) {
|
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,
|
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();
|
auto op = eat_op();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@ -125,11 +130,9 @@ void VM::run_instruction()
|
|||||||
stack_push(Ptr { .value = this->bp });
|
stack_push(Ptr { .value = this->bp });
|
||||||
this->pc = fn_ptr.as_ptr().value;
|
this->pc = fn_ptr.as_ptr().value;
|
||||||
this->bp = static_cast<uint32_t>(this->stack.size());
|
this->bp = static_cast<uint32_t>(this->stack.size());
|
||||||
// for (size_t i = arguments.size(); i > 0; --i) {
|
for (auto&& arg = arguments.rbegin(); arg != arguments.rend();
|
||||||
// stack_push(std::move(arguments.at(i - 1)));
|
++arg) {
|
||||||
// }
|
stack_push(*arg);
|
||||||
for (size_t i = 0; i < arguments.size(); ++i) {
|
|
||||||
stack_push(std::move(arguments.at(i)));
|
|
||||||
}
|
}
|
||||||
if (this->opts.flame_graph) {
|
if (this->opts.flame_graph) {
|
||||||
this->flame_graph.report_call(
|
this->flame_graph.report_call(
|
||||||
@ -277,20 +280,57 @@ void VM::run_instruction()
|
|||||||
|
|
||||||
void VM::run_builtin(Builtin builtin_id)
|
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) {
|
switch (builtin_id) {
|
||||||
case Builtin::StringConcat: {
|
case Builtin::StringConcat: {
|
||||||
assert_stack_has(2);
|
assert_stack_has(2);
|
||||||
auto left = stack_pop();
|
|
||||||
auto right = stack_pop();
|
auto right = stack_pop();
|
||||||
|
auto left = stack_pop();
|
||||||
stack_push(
|
stack_push(
|
||||||
String(right.as_string().value + left.as_string().value));
|
String(left.as_string().value + right.as_string().value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Builtin::StringEqual: {
|
case Builtin::StringEqual: {
|
||||||
assert_stack_has(2);
|
assert_stack_has(2);
|
||||||
auto left = stack_pop();
|
|
||||||
auto right = 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;
|
break;
|
||||||
}
|
}
|
||||||
case Builtin::ArraySet: {
|
case Builtin::ArraySet: {
|
||||||
@ -299,6 +339,32 @@ void VM::run_builtin(Builtin builtin_id)
|
|||||||
std::exit(1);
|
std::exit(1);
|
||||||
break;
|
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: {
|
case Builtin::StructSet: {
|
||||||
assert_stack_has(2);
|
assert_stack_has(2);
|
||||||
std::cerr << std::format("not implemented\n");
|
std::cerr << std::format("not implemented\n");
|
||||||
@ -312,59 +378,5 @@ void VM::run_builtin(Builtin builtin_id)
|
|||||||
stack_push(Null());
|
stack_push(Null());
|
||||||
break;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,8 +185,8 @@ public:
|
|||||||
result += std::format(
|
result += std::format(
|
||||||
"{:<11}", stack[stack.size() - i - 1].to_repr_string());
|
"{:<11}", stack[stack.size() - i - 1].to_repr_string());
|
||||||
}
|
}
|
||||||
if (stack.size() >= max_items) {
|
if (stack.size() > max_items) {
|
||||||
result += std::format(" ... + {}", stack.size() - max_items + 1);
|
result += std::format(" ... + {}", stack.size() - max_items);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user