✨ improve error info when lack arguments
in function call
This commit is contained in:
parent
80f9fc5842
commit
ecfb679218
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
[](./LICENSE)
|
[](./LICENSE)
|
||||||
|
|
||||||
> This document is also available in: [__中文__](./doc/README_zh.md) | [__English__](./README.md)
|
> This document is also available in: [__中文__](./doc/README_zh.md) | [__English__](./README.md)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
[](../LICENSE)
|
[](../LICENSE)
|
||||||
|
|
||||||
> 这篇文档包含多语言版本: [__中文__](../doc/README_zh.md) | [__English__](../README.md)
|
> 这篇文档包含多语言版本: [__中文__](../doc/README_zh.md) | [__English__](../README.md)
|
||||||
|
|
|
@ -28,7 +28,7 @@ var builtin_cocreate(var* local, gc& ngc) {
|
||||||
|
|
||||||
cort.ctx.top[0] = nil;
|
cort.ctx.top[0] = nil;
|
||||||
cort.ctx.localr = cort.ctx.top+1;
|
cort.ctx.localr = cort.ctx.top+1;
|
||||||
cort.ctx.top = cort.ctx.localr+func.func().lsize;
|
cort.ctx.top = cort.ctx.localr+func.func().local_size;
|
||||||
cort.ctx.localr[0] = func.func().local[0];
|
cort.ctx.localr[0] = func.func().local[0];
|
||||||
cort.ctx.top[0] = nil; // old upvalr
|
cort.ctx.top[0] = nil; // old upvalr
|
||||||
cort.ctx.top++;
|
cort.ctx.top++;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef __nasver
|
#ifndef __nasver
|
||||||
#define __nasver "11.0"
|
#define __nasver "11.1"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
|
@ -93,7 +93,7 @@ std::ostream& operator<<(std::ostream& out, nas_hash& hash) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_func::clear() {
|
void nas_func::clear() {
|
||||||
dpara = -1;
|
dynamic_parameter_index = -1;
|
||||||
local.clear();
|
local.clear();
|
||||||
upval.clear();
|
upval.clear();
|
||||||
keys.clear();
|
keys.clear();
|
||||||
|
|
|
@ -146,22 +146,26 @@ struct nas_hash {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_func {
|
struct nas_func {
|
||||||
i32 dpara; // dynamic parameter name index in hash.
|
i32 dynamic_parameter_index; // dynamic parameter name index in hash.
|
||||||
u32 entry; // pc will set to entry-1 to call this function
|
u32 entry; // pc will set to entry-1 to call this function
|
||||||
u32 psize; // used to load default parameters to a new function
|
u32 parameter_size; // used to load default parameters to a new function
|
||||||
u32 lsize; // used to expand memory space for local values on stack
|
u32 local_size; // used to expand memory space for local values on stack
|
||||||
std::vector<var> local; // local scope with default value(var)
|
std::vector<var> local; // local scope with default value(var)
|
||||||
std::vector<var> upval; // closure
|
std::vector<var> upval; // closure
|
||||||
std::unordered_map<u32,u32> keys; // parameter table, u32 begins from 1
|
|
||||||
|
|
||||||
nas_func(): dpara(-1), entry(0), psize(0), lsize(0) {}
|
// parameter table, u32 begins from 1
|
||||||
|
std::unordered_map<std::string, u32> keys;
|
||||||
|
|
||||||
|
nas_func():
|
||||||
|
dynamic_parameter_index(-1), entry(0),
|
||||||
|
parameter_size(0), local_size(0) {}
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_upval {
|
struct nas_upval {
|
||||||
public:
|
public:
|
||||||
/* on stack, use these variables */
|
/* on stack, use these variables */
|
||||||
bool onstk;
|
bool on_stack;
|
||||||
u32 size;
|
u32 size;
|
||||||
var* stk;
|
var* stk;
|
||||||
|
|
||||||
|
@ -169,14 +173,14 @@ public:
|
||||||
std::vector<var> elems;
|
std::vector<var> elems;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_upval(): onstk(true), size(0), stk(nullptr) {}
|
nas_upval(): on_stack(true), size(0), stk(nullptr) {}
|
||||||
|
|
||||||
var& operator[](usize n) {
|
var& operator[](usize n) {
|
||||||
return onstk? stk[n]:elems[n];
|
return on_stack? stk[n]:elems[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
onstk = true;
|
on_stack = true;
|
||||||
elems.clear();
|
elems.clear();
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
@ -184,7 +188,7 @@ public:
|
||||||
|
|
||||||
struct nas_ghost {
|
struct nas_ghost {
|
||||||
private:
|
private:
|
||||||
using destructor=void (*)(void*);
|
using destructor = void (*)(void*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
|
|
|
@ -188,10 +188,10 @@ void vm::gstate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm::lstate() {
|
void vm::lstate() {
|
||||||
if (!ctx.localr || !ctx.funcr.func().lsize) {
|
if (!ctx.localr || !ctx.funcr.func().local_size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const u32 lsize = ctx.funcr.func().lsize;
|
const u32 lsize = ctx.funcr.func().local_size;
|
||||||
std::clog << "local (0x" << std::hex << reinterpret_cast<u64>(ctx.localr)
|
std::clog << "local (0x" << std::hex << reinterpret_cast<u64>(ctx.localr)
|
||||||
<< " <+" << static_cast<u64>(ctx.localr-ctx.stack)
|
<< " <+" << static_cast<u64>(ctx.localr-ctx.stack)
|
||||||
<< ">)\n" << std::dec;
|
<< ">)\n" << std::dec;
|
||||||
|
@ -228,6 +228,22 @@ void vm::detail() {
|
||||||
ustate();
|
ustate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string vm::report_lack_arguments(u32 argc, const nas_func& func) const {
|
||||||
|
auto result = std::string("lack argument(s): ");
|
||||||
|
std::vector<std::string> argument_list = {};
|
||||||
|
argument_list.resize(func.keys.size());
|
||||||
|
for(const auto& i : func.keys) {
|
||||||
|
argument_list[i.second-1] = i.first;
|
||||||
|
}
|
||||||
|
for(u32 i = argc; i<argument_list.size(); ++i) {
|
||||||
|
result += argument_list[i];
|
||||||
|
if (i!=argument_list.size()-1) {
|
||||||
|
result += ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void vm::die(const std::string& str) {
|
void vm::die(const std::string& str) {
|
||||||
std::cerr << "[vm] error: " << str << "\n";
|
std::cerr << "[vm] error: " << str << "\n";
|
||||||
traceback();
|
traceback();
|
||||||
|
|
117
src/nasal_vm.h
117
src/nasal_vm.h
|
@ -65,6 +65,7 @@ protected:
|
||||||
void lstate();
|
void lstate();
|
||||||
void ustate();
|
void ustate();
|
||||||
void detail();
|
void detail();
|
||||||
|
std::string report_lack_arguments(u32, const nas_func&) const;
|
||||||
void die(const std::string&);
|
void die(const std::string&);
|
||||||
|
|
||||||
/* vm calculation functions*/
|
/* vm calculation functions*/
|
||||||
|
@ -204,7 +205,7 @@ inline void vm::o_repl() {
|
||||||
|
|
||||||
inline void vm::o_intl() {
|
inline void vm::o_intl() {
|
||||||
ctx.top[0].func().local.resize(imm[ctx.pc], nil);
|
ctx.top[0].func().local.resize(imm[ctx.pc], nil);
|
||||||
ctx.top[0].func().lsize = imm[ctx.pc];
|
ctx.top[0].func().local_size = imm[ctx.pc];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_loadg() {
|
inline void vm::o_loadg() {
|
||||||
|
@ -217,7 +218,7 @@ inline void vm::o_loadl() {
|
||||||
|
|
||||||
inline void vm::o_loadu() {
|
inline void vm::o_loadu() {
|
||||||
ctx.funcr.func().upval[(imm[ctx.pc]>>16)&0xffff]
|
ctx.funcr.func().upval[(imm[ctx.pc]>>16)&0xffff]
|
||||||
.upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0];
|
.upval()[imm[ctx.pc]&0xffff] = (ctx.top--)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_pnum() {
|
inline void vm::o_pnum() {
|
||||||
|
@ -252,7 +253,7 @@ inline void vm::o_newf() {
|
||||||
(++ctx.top)[0] = ngc.alloc(vm_func);
|
(++ctx.top)[0] = ngc.alloc(vm_func);
|
||||||
auto& func = ctx.top[0].func();
|
auto& func = ctx.top[0].func();
|
||||||
func.entry = imm[ctx.pc];
|
func.entry = imm[ctx.pc];
|
||||||
func.psize = 1;
|
func.parameter_size = 1;
|
||||||
|
|
||||||
/* this means you create a new function in local scope */
|
/* this means you create a new function in local scope */
|
||||||
if (ctx.localr) {
|
if (ctx.localr) {
|
||||||
|
@ -260,7 +261,7 @@ inline void vm::o_newf() {
|
||||||
// function created in the same local scope shares one closure
|
// function created in the same local scope shares one closure
|
||||||
// so this size & stk setting has no problem
|
// so this size & stk setting has no problem
|
||||||
var upval = (ctx.upvalr.type==vm_nil)? ngc.alloc(vm_upval):ctx.upvalr;
|
var upval = (ctx.upvalr.type==vm_nil)? ngc.alloc(vm_upval):ctx.upvalr;
|
||||||
upval.upval().size = ctx.funcr.func().lsize;
|
upval.upval().size = ctx.funcr.func().local_size;
|
||||||
upval.upval().stk = ctx.localr;
|
upval.upval().stk = ctx.localr;
|
||||||
func.upval.push_back(upval);
|
func.upval.push_back(upval);
|
||||||
ctx.upvalr = upval;
|
ctx.upvalr = upval;
|
||||||
|
@ -275,20 +276,20 @@ inline void vm::o_happ() {
|
||||||
inline void vm::o_para() {
|
inline void vm::o_para() {
|
||||||
auto& func = ctx.top[0].func();
|
auto& func = ctx.top[0].func();
|
||||||
// func->size has 1 place reserved for "me"
|
// func->size has 1 place reserved for "me"
|
||||||
func.keys[imm[ctx.pc]] = func.psize;
|
func.keys[cstr[imm[ctx.pc]]] = func.parameter_size;
|
||||||
func.local[func.psize++] = var::none();
|
func.local[func.parameter_size++] = var::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_deft() {
|
inline void vm::o_deft() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
auto& func = (--ctx.top)[0].func();
|
auto& func = (--ctx.top)[0].func();
|
||||||
// func->size has 1 place reserved for "me"
|
// func->size has 1 place reserved for "me"
|
||||||
func.keys[imm[ctx.pc]] = func.psize;
|
func.keys[cstr[imm[ctx.pc]]] = func.parameter_size;
|
||||||
func.local[func.psize++] = val;
|
func.local[func.parameter_size++] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_dyn() {
|
inline void vm::o_dyn() {
|
||||||
ctx.top[0].func().dpara = imm[ctx.pc];
|
ctx.top[0].func().dynamic_parameter_index = imm[ctx.pc];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_lnot() {
|
inline void vm::o_lnot() {
|
||||||
|
@ -349,6 +350,7 @@ inline void vm::o_sub() {op_calc(-);}
|
||||||
inline void vm::o_mul() {op_calc(*);}
|
inline void vm::o_mul() {op_calc(*);}
|
||||||
inline void vm::o_div() {op_calc(/);}
|
inline void vm::o_div() {op_calc(/);}
|
||||||
inline void vm::o_lnk() {
|
inline void vm::o_lnk() {
|
||||||
|
// concat two vectors into one
|
||||||
if (ctx.top[-1].type==vm_vec && ctx.top[0].type==vm_vec) {
|
if (ctx.top[-1].type==vm_vec && ctx.top[0].type==vm_vec) {
|
||||||
ngc.temp = ngc.alloc(vm_vec);
|
ngc.temp = ngc.alloc(vm_vec);
|
||||||
for(auto i : ctx.top[-1].vec().elems) {
|
for(auto i : ctx.top[-1].vec().elems) {
|
||||||
|
@ -362,6 +364,7 @@ inline void vm::o_lnk() {
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// concat strings
|
||||||
ctx.top[-1] = ngc.newstr(ctx.top[-1].tostr()+ctx.top[0].tostr());
|
ctx.top[-1] = ngc.newstr(ctx.top[-1].tostr()+ctx.top[0].tostr());
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
@ -607,7 +610,7 @@ inline void vm::o_callv() {
|
||||||
ctx.top[0].func().local[0] = val; // 'me'
|
ctx.top[0].func().local[0] = val; // 'me'
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_str) {
|
} else if (vec.type==vm_str) {
|
||||||
auto& str = vec.str();
|
const auto& str = vec.str();
|
||||||
i32 num = val.tonum();
|
i32 num = val.tonum();
|
||||||
i32 len = str.length();
|
i32 len = str.length();
|
||||||
if (num<-len || num>=len) {
|
if (num<-len || num>=len) {
|
||||||
|
@ -670,13 +673,13 @@ inline void vm::o_callh() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_callfv() {
|
inline void vm::o_callfv() {
|
||||||
u32 argc = imm[ctx.pc]; // arguments counter
|
const u32 argc = imm[ctx.pc]; // arguments counter
|
||||||
var* local = ctx.top-argc+1; // arguments begin address
|
var* local = ctx.top-argc+1; // arguments begin address
|
||||||
if (local[-1].type!=vm_func) {
|
if (local[-1].type!=vm_func) {
|
||||||
die("must call a function");
|
die("must call a function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& func = local[-1].func();
|
const auto& func = local[-1].func();
|
||||||
|
|
||||||
// swap funcr with local[-1]
|
// swap funcr with local[-1]
|
||||||
var tmp = local[-1];
|
var tmp = local[-1];
|
||||||
|
@ -684,27 +687,29 @@ inline void vm::o_callfv() {
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
|
|
||||||
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top-argc+func.lsize+3>=ctx.canary) {
|
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// parameter size is func->psize-1, 1 is reserved for "me"
|
// parameter size is func->psize-1, 1 is reserved for "me"
|
||||||
u32 psize = func.psize-1;
|
const u32 parameter_size = func.parameter_size-1;
|
||||||
if (argc<psize && func.local[argc+1].type==vm_none) {
|
if (argc<parameter_size && func.local[argc+1].type==vm_none) {
|
||||||
die("lack argument(s)");
|
die(report_lack_arguments(argc, func));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load dynamic argument, default nil, for better performance
|
||||||
var dynamic = nil;
|
var dynamic = nil;
|
||||||
if (func.dpara>=0) { // load dynamic arguments
|
if (func.dynamic_parameter_index>=0) {
|
||||||
|
// load dynamic argument
|
||||||
dynamic = ngc.alloc(vm_vec);
|
dynamic = ngc.alloc(vm_vec);
|
||||||
for(u32 i = psize; i<argc; ++i) {
|
for(u32 i = parameter_size; i<argc; ++i) {
|
||||||
dynamic.vec().elems.push_back(local[i]);
|
dynamic.vec().elems.push_back(local[i]);
|
||||||
}
|
}
|
||||||
} else if (psize<argc) {
|
} else if (parameter_size<argc) {
|
||||||
// load arguments to "arg", located at stack+1
|
// load arguments to default dynamic argument "arg", located at stack+1
|
||||||
dynamic = ngc.alloc(vm_vec);
|
dynamic = ngc.alloc(vm_vec);
|
||||||
for(u32 i = psize; i<argc; ++i) {
|
for(u32 i = parameter_size; i<argc; ++i) {
|
||||||
dynamic.vec().elems.push_back(local[i]);
|
dynamic.vec().elems.push_back(local[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,19 +718,21 @@ inline void vm::o_callfv() {
|
||||||
// then all the available values the vector needs
|
// then all the available values the vector needs
|
||||||
// are all outside the stack top and may be
|
// are all outside the stack top and may be
|
||||||
// collected incorrectly
|
// collected incorrectly
|
||||||
ctx.top = local+func.lsize;
|
ctx.top = local+func.local_size;
|
||||||
|
|
||||||
u32 min_size = (std::min)(psize, argc); // avoid error in MSVC
|
const u32 min_size = (std::min)(parameter_size, argc); // avoid error in MSVC
|
||||||
for(u32 i = min_size; i>=1; --i) { // load arguments
|
for(u32 i = min_size; i>=1; --i) { // load arguments
|
||||||
local[i] = local[i-1];
|
local[i] = local[i-1];
|
||||||
}
|
}
|
||||||
local[0] = func.local[0];// load "me"
|
local[0] = func.local[0];// load "me"
|
||||||
|
|
||||||
// load local scope & default arguments
|
// load local scope & default arguments
|
||||||
for(u32 i = min_size+1; i<func.lsize; ++i) {
|
for(u32 i = min_size+1; i<func.local_size; ++i) {
|
||||||
local[i] = func.local[i];
|
local[i] = func.local[i];
|
||||||
}
|
}
|
||||||
local[func.dpara>=0? psize+1:func.lsize-1] = dynamic;
|
// load dynamic argument
|
||||||
|
local[func.dynamic_parameter_index>=0?
|
||||||
|
parameter_size+1:func.local_size-1] = dynamic;
|
||||||
|
|
||||||
ctx.top[0] = ctx.upvalr;
|
ctx.top[0] = ctx.upvalr;
|
||||||
(++ctx.top)[0] = var::addr(ctx.localr);
|
(++ctx.top)[0] = var::addr(ctx.localr);
|
||||||
|
@ -736,41 +743,56 @@ inline void vm::o_callfv() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_callfh() {
|
inline void vm::o_callfh() {
|
||||||
auto& hash = ctx.top[0].hash().elems;
|
const auto& hash = ctx.top[0].hash().elems;
|
||||||
if (ctx.top[-1].type!=vm_func) {
|
if (ctx.top[-1].type!=vm_func) {
|
||||||
die("must call a function");
|
die("must call a function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& func = ctx.top[-1].func();
|
const auto& func = ctx.top[-1].func();
|
||||||
var tmp = ctx.top[-1];
|
var tmp = ctx.top[-1];
|
||||||
ctx.top[-1] = ctx.funcr;
|
ctx.top[-1] = ctx.funcr;
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
|
|
||||||
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top+func.lsize+2>= ctx.canary) {
|
if (ctx.top+func.local_size+2>= ctx.canary) {
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (func.dpara>=0) {
|
// dynamic parameter is not allowed in this kind of function call
|
||||||
die("special call cannot use dynamic argument");
|
if (func.dynamic_parameter_index>=0) {
|
||||||
|
die("special call cannot use dynamic argument \"" +
|
||||||
|
cstr[func.dynamic_parameter_index] + "\""
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var* local = ctx.top;
|
var* local = ctx.top;
|
||||||
ctx.top += func.lsize;
|
ctx.top += func.local_size;
|
||||||
for(u32 i = 0; i<func.lsize; ++i) {
|
for(u32 i = 0; i<func.local_size; ++i) {
|
||||||
local[i] = func.local[i];
|
local[i] = func.local[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lack_arguments_flag = false;
|
||||||
for(const auto& i : func.keys) {
|
for(const auto& i : func.keys) {
|
||||||
auto& key = cstr[i.first];
|
const auto& key = i.first;
|
||||||
if (hash.count(key)) {
|
if (hash.count(key)) {
|
||||||
local[i.second] = hash[key];
|
local[i.second] = hash.at(key);
|
||||||
} else if (local[i.second].type==vm_none) {
|
} else if (local[i.second].type==vm_none) {
|
||||||
die("lack argument(s): \""+key+"\"");
|
lack_arguments_flag = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (lack_arguments_flag) {
|
||||||
|
auto info = std::string("lack argument(s): ");
|
||||||
|
for(const auto& i : func.keys) {
|
||||||
|
const auto& key = i.first;
|
||||||
|
if (local[i.second].type==vm_none) {
|
||||||
|
info += key + ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info = info.substr(0, info.length()-2);
|
||||||
|
die(info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.top[0] = ctx.upvalr;
|
ctx.top[0] = ctx.upvalr;
|
||||||
(++ctx.top)[0] = var::addr(ctx.localr);
|
(++ctx.top)[0] = var::addr(ctx.localr);
|
||||||
|
@ -831,7 +853,7 @@ inline void vm::o_slc() {
|
||||||
inline void vm::o_slc2() {
|
inline void vm::o_slc2() {
|
||||||
var val2 = (ctx.top--)[0];
|
var val2 = (ctx.top--)[0];
|
||||||
var val1 = (ctx.top--)[0];
|
var val1 = (ctx.top--)[0];
|
||||||
auto& ref = ctx.top[-1].vec().elems;
|
const auto& ref = ctx.top[-1].vec().elems;
|
||||||
auto& aim = ctx.top[0].vec().elems;
|
auto& aim = ctx.top[0].vec().elems;
|
||||||
|
|
||||||
u8 type1 = val1.type,type2=val2.type;
|
u8 type1 = val1.type,type2=val2.type;
|
||||||
|
@ -875,8 +897,9 @@ inline void vm::o_mcalll() {
|
||||||
inline void vm::o_mupval() {
|
inline void vm::o_mupval() {
|
||||||
ctx.memr = &(
|
ctx.memr = &(
|
||||||
ctx.funcr.func()
|
ctx.funcr.func()
|
||||||
.upval[(imm[ctx.pc]>>16)&0xffff]
|
.upval[(imm[ctx.pc]>>16)&0xffff]
|
||||||
.upval()[imm[ctx.pc]&0xffff]);
|
.upval()[imm[ctx.pc]&0xffff]
|
||||||
|
);
|
||||||
(++ctx.top)[0] = ctx.memr[0];
|
(++ctx.top)[0] = ctx.memr[0];
|
||||||
// push value in this memory space on stack
|
// push value in this memory space on stack
|
||||||
// to avoid being garbage collected
|
// to avoid being garbage collected
|
||||||
|
@ -897,7 +920,7 @@ inline void vm::o_mcallv() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.hash();
|
auto& ref = vec.hash();
|
||||||
auto& str = val.str();
|
const auto& str = val.str();
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
if (!ctx.memr) {
|
if (!ctx.memr) {
|
||||||
ref.elems[str] = nil;
|
ref.elems[str] = nil;
|
||||||
|
@ -909,7 +932,7 @@ inline void vm::o_mcallv() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.map();
|
auto& ref = vec.map();
|
||||||
auto& str = val.str();
|
const auto& str = val.str();
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
if (!ctx.memr) {
|
if (!ctx.memr) {
|
||||||
die("cannot find symbol \"" + str + "\"");
|
die("cannot find symbol \"" + str + "\"");
|
||||||
|
@ -926,7 +949,7 @@ inline void vm::o_mcallh() {
|
||||||
die("must call a hash");
|
die("must call a hash");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& str = cstr[imm[ctx.pc]];
|
const auto& str = cstr[imm[ctx.pc]];
|
||||||
if (hash.type==vm_map) {
|
if (hash.type==vm_map) {
|
||||||
ctx.memr = hash.map().get_mem(str);
|
ctx.memr = hash.map().get_mem(str);
|
||||||
if (!ctx.memr) {
|
if (!ctx.memr) {
|
||||||
|
@ -936,7 +959,8 @@ inline void vm::o_mcallh() {
|
||||||
}
|
}
|
||||||
auto& ref = hash.hash();
|
auto& ref = hash.hash();
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
if (!ctx.memr) { // create a new key
|
// create a new key
|
||||||
|
if (!ctx.memr) {
|
||||||
ref.elems[str] = nil;
|
ref.elems[str] = nil;
|
||||||
ctx.memr = ref.get_mem(str);
|
ctx.memr = ref.get_mem(str);
|
||||||
}
|
}
|
||||||
|
@ -970,10 +994,11 @@ inline void vm::o_ret() {
|
||||||
ctx.funcr = ctx.top[0];
|
ctx.funcr = ctx.top[0];
|
||||||
ctx.top[0] = ret; // rewrite func with returned value
|
ctx.top[0] = ret; // rewrite func with returned value
|
||||||
|
|
||||||
if (up.type==vm_upval) { // synchronize upvalue
|
// synchronize upvalue
|
||||||
|
if (up.type==vm_upval) {
|
||||||
auto& upval = up.upval();
|
auto& upval = up.upval();
|
||||||
auto size = func.func().lsize;
|
auto size = func.func().local_size;
|
||||||
upval.onstk = false;
|
upval.on_stack = false;
|
||||||
upval.elems.resize(size);
|
upval.elems.resize(size);
|
||||||
for(u32 i = 0; i<size; ++i) {
|
for(u32 i = 0; i<size; ++i) {
|
||||||
upval.elems[i] = local[i];
|
upval.elems[i] = local[i];
|
||||||
|
|
Loading…
Reference in New Issue