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());
|
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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
11
src/vm.cpp
11
src/vm.cpp
|
@ -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>();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue