Make stdlib functions use normal VM stack for parameter passing
This commit is contained in:
parent
bb71669c83
commit
06149c3d61
5 changed files with 71 additions and 44 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
11
src/vm.cpp
11
src/vm.cpp
|
@ -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>();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue