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()); 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); uint64_t size = std::max(_value->size, idx + 1);
auto pod = TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * size)); auto pod = TRY(arena_alloc<PodStackFrame>(sizeof(OffPtr<PodObject>) * size));
pod->header.tag = Tag::StackFrame; pod->header.tag = Tag::StackFrame;

View file

@ -1114,7 +1114,7 @@ class StackFrame : public Object {
using Object::get; using Object::get;
Result<Value> get(uint64_t idx) const; 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<StackFrame> settop(uint64_t idx) const;
Result<Value> parent() const; Result<Value> parent() const;
Result<Value> fun() const; Result<Value> fun() const;

View file

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

View file

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

View file

@ -278,20 +278,11 @@ Result<void> VM::step_bytecode() {
} }
Result<void> VM::step_native() { Result<void> VM::step_native() {
// foo
auto fun = TRY(_stack.fun()); auto fun = TRY(_stack.fun());
if (!fun.is<StdlibFunction>()) return ERROR(TypeMismatch); if (!fun.is<StdlibFunction>()) return ERROR(TypeMismatch);
auto fun_id = fun.to<StdlibFunction>()->fun_id(); auto fun_id = fun.to<StdlibFunction>()->fun_id();
auto params = TRY(_stack.get(0)); _stack = TRY(call_stdlib_function(fun_id, _stack));
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(_stack.incpc()); _stack = TRY(_stack.incpc());
return Result<void>(); return Result<void>();
} }