Make stdlib functions use normal VM stack for parameter passing

This commit is contained in:
Konstantin Nazarov 2024-09-15 15:39:12 +01:00
parent bb71669c83
commit 06149c3d61
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 71 additions and 44 deletions

View file

@ -328,7 +328,7 @@ Result<Value> StackFrame::get(uint64_t idx) const {
return Value::create(_value->data[idx].get());
}
Result<StackFrame> StackFrame::set(uint64_t idx, const Value& val) {
Result<StackFrame> StackFrame::set(uint64_t idx, const Value& val) const {
uint64_t size = std::max(_value->size, idx + 1);
auto pod = TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * size));
pod->header.tag = Tag::StackFrame;

View file

@ -1114,7 +1114,7 @@ class StackFrame : public Object {
using Object::get;
Result<Value> get(uint64_t idx) const;
Result<StackFrame> set(uint64_t idx, const Value& val);
Result<StackFrame> set(uint64_t idx, const Value& val) const;
Result<StackFrame> settop(uint64_t idx) const;
Result<Value> parent() const;
Result<Value> fun() const;

View file

@ -5,7 +5,7 @@
#include "sourcerange.hpp"
#include "writer.hpp"
typedef Result<Value> (*StdlibFunctionIdPtr)(const Array& params);
typedef Result<StackFrame> (*StdlibFunctionIdPtr)(const StackFrame& stack);
struct StdlibFunctionEntry {
const char* name;
@ -13,11 +13,12 @@ struct StdlibFunctionEntry {
StdlibFunctionIdPtr fun_ptr;
};
Result<Value> stdlib_unknown(const Array& params) {
Result<StackFrame> stdlib_unknown(const StackFrame& stack) {
return ERROR(NotImplemented);
}
Result<Value> stdlib_print(const Array& params) {
Result<StackFrame> stdlib_print(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto size = TRY(params.size());
for (uint64_t i = 0; i < size; i++) {
Value param = TRY(params.get(i));
@ -33,19 +34,25 @@ Result<Value> stdlib_print(const Array& params) {
}
}
return Value(TRY(Nil::create()));
auto nil = Value(TRY(Nil::create()));
auto res = TRY(stack.set(0, nil));
return res.ret(0);
}
Result<Value> stdlib_println(const Array& params) {
TRY(stdlib_print(params));
Result<StackFrame> stdlib_println(const StackFrame& stack) {
auto res = TRY(stdlib_print(stack));
std::cout << "\n";
return Value(TRY(Nil::create()));
return res;
}
Result<Value> stdlib_prn(const Array& params) { return ERROR(NotImplemented); }
Result<StackFrame> stdlib_prn(const StackFrame& stack) {
return ERROR(NotImplemented);
}
Result<Value> stdlib_assert(const Array& params) {
Result<StackFrame> stdlib_assert(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto size = TRY(params.size());
for (uint64_t i = 0; i < size; i++) {
Value param = TRY(params.get(i));
@ -54,40 +61,59 @@ Result<Value> stdlib_assert(const Array& params) {
if (!v) return ERROR(AssertionFailed);
}
return Value(TRY(Nil::create()));
auto nil = Value(TRY(Nil::create()));
auto res = TRY(stack.set(0, nil));
return res.ret(0);
}
Result<Value> stdlib_dict(const Array& params) {
Value d = TRY(Dict::create(params));
return d;
Result<StackFrame> stdlib_dict(const StackFrame& stack) {
auto params = TRY(stack.get(0));
if (!params.is<Array>()) return ERROR(TypeMismatch);
Value d = TRY(Dict::create(*params.to<Array>()));
auto res = TRY(stack.set(0, d));
return res.ret(0);
}
Result<Value> stdlib_list(const Array& params) {
Value d = TRY(Pair::create(params));
return d;
Result<StackFrame> stdlib_list(const StackFrame& stack) {
auto params = TRY(stack.get(0));
if (!params.is<Array>()) return ERROR(TypeMismatch);
Value d = TRY(Pair::create(*params.to<Array>()));
auto res = TRY(stack.set(0, d));
return res.ret(0);
}
Result<Value> stdlib_array(const Array& params) {
Array array_copy = TRY(params.copy());
return Value(std::move(array_copy));
Result<StackFrame> stdlib_array(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto res = TRY(stack.set(0, params));
return res.ret(0);
}
Result<Value> stdlib_get(const Array& params) {
Result<StackFrame> stdlib_get(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto size = TRY(params.size());
if (size != 2) return ERROR(ArgumentCountMismatch);
Value collection = TRY(params.get(0));
Value key = TRY(params.get(1));
return TRY(collection.get(key));
auto val = TRY(collection.get(key));
auto res = TRY(stack.set(0, val));
return res.ret(0);
}
Result<Value> stdlib_srcloc(const Array& params) {
Array array_copy = TRY(params.copy());
Result<StackFrame> stdlib_srcloc(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto size = TRY(params.size());
if (size != 6) return ERROR(ArgumentCountMismatch);
SourceRange sr;
for (uint64_t i = 0; i < 6; i++) {
auto val = TRY(array_copy.get(i));
auto val = TRY(params.get(i));
if (!val.is<Int64>()) return ERROR(TypeMismatch);
int64_t intval = val.to<Int64>()->value();
switch (i) {
@ -114,16 +140,25 @@ Result<Value> stdlib_srcloc(const Array& params) {
}
}
return Value(TRY(SrcLoc::create(sr)));
auto val = Value(TRY(SrcLoc::create(sr)));
auto res = TRY(stack.set(0, val));
return res.ret(0);
}
Result<Value> stdlib_size(const Array& params) {
Result<StackFrame> stdlib_size(const StackFrame& stack) {
auto params = TRY(stack.get(0));
auto size = TRY(params.size());
if (size != 1) return ERROR(ArgumentCountMismatch);
auto param = TRY(params.get(0));
auto psize = TRY(param.size());
return Value(TRY(Int64::create((int64_t)psize)));
auto val = Value(TRY(Int64::create((int64_t)psize)));
auto res = TRY(stack.set(0, val));
return res.ret(0);
}
#define STDLIB_FUNCTION(name, id) \
@ -180,13 +215,13 @@ Result<StdlibFunctionId> get_stdlib_function(const Symbol& name) {
return fun_id;
}
Result<Value> call_stdlib_function(StdlibFunctionId fun_id,
const Array& params) {
Result<StackFrame> call_stdlib_function(StdlibFunctionId fun_id,
const StackFrame& stack) {
if (fun_id == StdlibFunctionId(0) || fun_id >= StdlibFunctionId::Max) {
return ERROR(KeyError);
}
return function_entries[(uint64_t)fun_id].fun_ptr(params);
return function_entries[(uint64_t)fun_id].fun_ptr(stack);
}
Result<const char*> get_stdlib_function_name(StdlibFunctionId fun_id) {

View file

@ -22,8 +22,9 @@ enum class StdlibFunctionId : uint64_t {
class Value;
class Symbol;
class Array;
class StackFrame;
Result<const char*> get_stdlib_function_name(StdlibFunctionId fun_id);
Result<StdlibFunctionId> get_stdlib_function(const Symbol& name);
Result<Value> call_stdlib_function(StdlibFunctionId fun_id,
const Array& params);
Result<StackFrame> call_stdlib_function(StdlibFunctionId fun_id,
const StackFrame& stack);

View file

@ -278,20 +278,11 @@ Result<void> VM::step_bytecode() {
}
Result<void> VM::step_native() {
// foo
auto fun = TRY(_stack.fun());
if (!fun.is<StdlibFunction>()) return ERROR(TypeMismatch);
auto fun_id = fun.to<StdlibFunction>()->fun_id();
auto params = TRY(_stack.get(0));
if (!params.is<Array>()) return ERROR(TypeMismatch);
auto res = TRY(call_stdlib_function(fun_id, *params.to<Array>()));
auto top = TRY(_stack.size());
_stack = TRY(_stack.set(top, res));
_stack = TRY(_stack.ret(top));
_stack = TRY(call_stdlib_function(fun_id, _stack));
_stack = TRY(_stack.incpc());
return Result<void>();
}