bug fixed
This commit is contained in:
parent
540aeb73f4
commit
183446d32a
2
makefile
2
makefile
|
@ -1,6 +1,6 @@
|
|||
.PHONY=test
|
||||
nasal:main.cpp nasal_ast.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal.h
|
||||
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -Wshadow
|
||||
clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -Wshadow -Wall
|
||||
test:nasal
|
||||
./nasal test/ascii-art.nas
|
||||
./nasal -c test/bf.nas
|
||||
|
|
8
nasal.h
8
nasal.h
|
@ -1,6 +1,5 @@
|
|||
#ifndef __NASAL_H__
|
||||
#define __NASAL_H__
|
||||
#pragma GCC optimize(2)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
@ -20,10 +19,6 @@
|
|||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
check if a string can be converted to a number
|
||||
if this string cannot be converted to a number,it will return nan
|
||||
*/
|
||||
inline double hex_to_double(const char* str)
|
||||
{
|
||||
double ret=0;
|
||||
|
@ -104,9 +99,6 @@ double str2num(const char* str)
|
|||
return is_negative?-ret_num:ret_num;
|
||||
}
|
||||
|
||||
/*
|
||||
show raw string
|
||||
*/
|
||||
std::string raw_string(const std::string& str)
|
||||
{
|
||||
std::string ret("");
|
||||
|
|
112
nasal_ast.h
112
nasal_ast.h
|
@ -66,13 +66,13 @@ const char* ast_name[]=
|
|||
class nasal_ast
|
||||
{
|
||||
private:
|
||||
uint32_t text_line;
|
||||
uint32_t node_type;
|
||||
double node_num;
|
||||
std::string node_str;
|
||||
std::vector<nasal_ast> node_child;
|
||||
uint32_t _line;
|
||||
uint32_t _type;
|
||||
double _num;
|
||||
std::string _str;
|
||||
std::vector<nasal_ast> _child;
|
||||
public:
|
||||
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):text_line(l),node_type(t){}
|
||||
nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):_line(l),_type(t){}
|
||||
nasal_ast(const nasal_ast&);
|
||||
nasal_ast(nasal_ast&&);
|
||||
void print(const int);
|
||||
|
@ -80,88 +80,88 @@ public:
|
|||
|
||||
nasal_ast& operator=(const nasal_ast&);
|
||||
nasal_ast& operator=(nasal_ast&&);
|
||||
nasal_ast& operator[](const int index){return node_child[index];}
|
||||
const nasal_ast& operator[](const int index) const {return node_child[index];}
|
||||
size_t size() const {return node_child.size();}
|
||||
nasal_ast& operator[](const int index){return _child[index];}
|
||||
const nasal_ast& operator[](const int index) const {return _child[index];}
|
||||
size_t size() const {return _child.size();}
|
||||
|
||||
void add(nasal_ast&& ast){node_child.push_back(std::move(ast));}
|
||||
void add(const nasal_ast& ast){node_child.push_back(ast);}
|
||||
void set_line(const uint32_t l){text_line=l;}
|
||||
void set_type(const uint32_t t){node_type=t;}
|
||||
void set_str(const std::string& s){node_str=s;}
|
||||
void set_num(const double n){node_num=n;}
|
||||
void add(nasal_ast&& ast){_child.push_back(std::move(ast));}
|
||||
void add(const nasal_ast& ast){_child.push_back(ast);}
|
||||
void set_line(const uint32_t l){_line=l;}
|
||||
void set_type(const uint32_t t){_type=t;}
|
||||
void set_str(const std::string& s){_str=s;}
|
||||
void set_num(const double n){_num=n;}
|
||||
|
||||
inline const uint32_t line() const {return text_line;}
|
||||
inline const uint32_t type() const {return node_type;}
|
||||
inline const double num() const {return node_num;}
|
||||
inline const std::string& str() const {return node_str;}
|
||||
inline const std::vector<nasal_ast>& child() const {return node_child;}
|
||||
inline std::vector<nasal_ast>& child(){return node_child;}
|
||||
inline uint32_t line() const {return _line;}
|
||||
inline uint32_t type() const {return _type;}
|
||||
inline double num() const {return _num;}
|
||||
inline const std::string& str() const {return _str;}
|
||||
inline const std::vector<nasal_ast>& child() const {return _child;}
|
||||
inline std::vector<nasal_ast>& child(){return _child;}
|
||||
};
|
||||
|
||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||
{
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num =tmp.node_num;
|
||||
node_str =tmp.node_str;
|
||||
node_child=tmp.node_child;
|
||||
_line=tmp._line;
|
||||
_type=tmp._type;
|
||||
_num =tmp._num;
|
||||
_str =tmp._str;
|
||||
_child=tmp._child;
|
||||
}
|
||||
|
||||
nasal_ast::nasal_ast(nasal_ast&& tmp)
|
||||
{
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num =tmp.node_num;
|
||||
node_str.swap(tmp.node_str);
|
||||
node_child.swap(tmp.node_child);
|
||||
_line=tmp._line;
|
||||
_type=tmp._type;
|
||||
_num =tmp._num;
|
||||
_str.swap(tmp._str);
|
||||
_child.swap(tmp._child);
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||
{
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num=tmp.node_num;
|
||||
node_str=tmp.node_str;
|
||||
node_child=tmp.node_child;
|
||||
_line=tmp._line;
|
||||
_type=tmp._type;
|
||||
_num=tmp._num;
|
||||
_str=tmp._str;
|
||||
_child=tmp._child;
|
||||
return *this;
|
||||
}
|
||||
|
||||
nasal_ast& nasal_ast::operator=(nasal_ast&& tmp)
|
||||
{
|
||||
text_line=tmp.text_line;
|
||||
node_type=tmp.node_type;
|
||||
node_num=tmp.node_num;
|
||||
node_str.swap(tmp.node_str);
|
||||
node_child.swap(tmp.node_child);
|
||||
_line=tmp._line;
|
||||
_type=tmp._type;
|
||||
_num=tmp._num;
|
||||
_str.swap(tmp._str);
|
||||
_child.swap(tmp._child);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void nasal_ast::clear()
|
||||
{
|
||||
text_line=0;
|
||||
node_num=0;
|
||||
node_str="";
|
||||
node_type=ast_null;
|
||||
node_child.clear();
|
||||
_line=0;
|
||||
_num=0;
|
||||
_str="";
|
||||
_type=ast_null;
|
||||
_child.clear();
|
||||
}
|
||||
|
||||
void nasal_ast::print(const int depth)
|
||||
{
|
||||
for(int i=0;i<depth;++i)
|
||||
std::cout<<"| ";
|
||||
std::cout<<ast_name[node_type];
|
||||
std::cout<<ast_name[_type];
|
||||
if(
|
||||
node_type==ast_str ||
|
||||
node_type==ast_id ||
|
||||
node_type==ast_default ||
|
||||
node_type==ast_dynamic ||
|
||||
node_type==ast_callh)
|
||||
std::cout<<":"<<raw_string(node_str);
|
||||
else if(node_type==ast_num || node_type==ast_file)
|
||||
std::cout<<":"<<node_num;
|
||||
_type==ast_str ||
|
||||
_type==ast_id ||
|
||||
_type==ast_default ||
|
||||
_type==ast_dynamic ||
|
||||
_type==ast_callh)
|
||||
std::cout<<":"<<raw_string(_str);
|
||||
else if(_type==ast_num || _type==ast_file)
|
||||
std::cout<<":"<<_num;
|
||||
std::cout<<'\n';
|
||||
for(auto& i:node_child)
|
||||
for(auto& i:_child)
|
||||
i.print(depth+1);
|
||||
}
|
||||
|
||||
|
|
93
nasal_gc.h
93
nasal_gc.h
|
@ -32,13 +32,13 @@ const uint32_t increment[vm_type_size]=
|
|||
128 // vm_obj
|
||||
};
|
||||
|
||||
// declaration of nasal value type
|
||||
struct nasal_vec;
|
||||
struct nasal_hash;
|
||||
struct nasal_func;
|
||||
struct nasal_obj;
|
||||
struct nasal_val;
|
||||
// declaration of nasal_ref
|
||||
struct nasal_ref// 16 bytes
|
||||
|
||||
struct nasal_ref
|
||||
{
|
||||
uint8_t type;
|
||||
union
|
||||
|
@ -50,43 +50,27 @@ struct nasal_ref// 16 bytes
|
|||
nasal_ref(const uint8_t t=vm_none):type(t){}
|
||||
nasal_ref(const uint8_t t,const double n):type(t){value.num=n;}
|
||||
nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;}
|
||||
nasal_ref(const nasal_ref& nr)
|
||||
{
|
||||
type=nr.type;
|
||||
value=nr.value;
|
||||
}
|
||||
nasal_ref(const nasal_ref&& nr)
|
||||
{
|
||||
type=nr.type;
|
||||
value=nr.value;
|
||||
}
|
||||
nasal_ref(const nasal_ref& nr):type(nr.type),value(nr.value){}
|
||||
nasal_ref& operator=(const nasal_ref& nr)
|
||||
{
|
||||
type=nr.type;
|
||||
value=nr.value;
|
||||
return *this;
|
||||
}
|
||||
nasal_ref& operator=(const nasal_ref&& nr)
|
||||
{
|
||||
type=nr.type;
|
||||
value=nr.value;
|
||||
return *this;
|
||||
}
|
||||
bool operator==(const nasal_ref& nr){return type==nr.type && value.gcobj==nr.value.gcobj;}
|
||||
bool operator!=(const nasal_ref& nr){return type!=nr.type || value.gcobj!=nr.value.gcobj;}
|
||||
// nasal is a weak-type programming language because number and string can be translated to each other
|
||||
// number and string can be translated to each other
|
||||
double to_number();
|
||||
std::string to_string();
|
||||
// inline function to get number and pointers, make it easier to read the code
|
||||
inline double& num ();
|
||||
inline std::string* str ();
|
||||
inline nasal_vec* vec ();
|
||||
inline nasal_hash* hash();
|
||||
inline nasal_func* func();
|
||||
inline void*& obj ();
|
||||
inline nasal_obj* obj ();
|
||||
};
|
||||
|
||||
struct nasal_vec// 24 bytes
|
||||
struct nasal_vec
|
||||
{
|
||||
std::vector<nasal_ref> elems;
|
||||
|
||||
|
@ -95,7 +79,7 @@ struct nasal_vec// 24 bytes
|
|||
nasal_ref* get_mem(const int);
|
||||
};
|
||||
|
||||
struct nasal_hash// 56 bytes
|
||||
struct nasal_hash
|
||||
{
|
||||
std::unordered_map<std::string,nasal_ref> elems;
|
||||
|
||||
|
@ -104,22 +88,30 @@ struct nasal_hash// 56 bytes
|
|||
nasal_ref* get_mem(const std::string&);
|
||||
};
|
||||
|
||||
struct nasal_func// 112 bytes
|
||||
struct nasal_func
|
||||
{
|
||||
int32_t dynpara; // dynamic parameter name index in hash.
|
||||
uint32_t entry; // pc will set to entry-1 to call this function
|
||||
std::vector<nasal_ref> local; // local scope with default value(nasal_ref)
|
||||
std::vector<nasal_ref> upvalue; // closure
|
||||
std::unordered_map<std::string,int> keys; // parameter name table
|
||||
std::unordered_map<std::string,size_t> keys; // parameter name table
|
||||
|
||||
nasal_func():dynpara(-1){}
|
||||
void clear();
|
||||
};
|
||||
|
||||
struct nasal_obj
|
||||
{
|
||||
uint32_t type;
|
||||
void* ptr;
|
||||
nasal_obj():ptr(nullptr){}
|
||||
void clear();
|
||||
};
|
||||
|
||||
constexpr uint8_t GC_UNCOLLECTED=0;
|
||||
constexpr uint8_t GC_COLLECTED =1;
|
||||
constexpr uint8_t GC_FOUND =2;
|
||||
struct nasal_val// 16 bytes
|
||||
struct nasal_val
|
||||
{
|
||||
uint8_t mark;
|
||||
uint8_t type;
|
||||
|
@ -129,14 +121,13 @@ struct nasal_val// 16 bytes
|
|||
nasal_vec* vec;
|
||||
nasal_hash* hash;
|
||||
nasal_func* func;
|
||||
void* obj;
|
||||
nasal_obj* obj;
|
||||
}ptr;
|
||||
|
||||
nasal_val(uint8_t);
|
||||
~nasal_val();
|
||||
};
|
||||
|
||||
/*functions of nasal_vec*/
|
||||
nasal_ref nasal_vec::get_val(const int index)
|
||||
{
|
||||
int size=elems.size();
|
||||
|
@ -165,7 +156,7 @@ void nasal_vec::print()
|
|||
std::cout<<"[]";
|
||||
return;
|
||||
}
|
||||
ssize_t iter=0;
|
||||
size_t iter=0;
|
||||
std::cout<<'[';
|
||||
for(auto& i:elems)
|
||||
{
|
||||
|
@ -183,10 +174,8 @@ void nasal_vec::print()
|
|||
std::cout<<",]"[(++iter)==elems.size()];
|
||||
}
|
||||
--depth;
|
||||
return;
|
||||
}
|
||||
|
||||
/*functions of nasal_hash*/
|
||||
nasal_ref nasal_hash::get_val(const std::string& key)
|
||||
{
|
||||
if(elems.count(key))
|
||||
|
@ -259,20 +248,23 @@ void nasal_hash::print()
|
|||
std::cout<<",}"[(++iter)==elems.size()];
|
||||
}
|
||||
--depth;
|
||||
return;
|
||||
}
|
||||
|
||||
/*functions of nasal_func*/
|
||||
void nasal_func::clear()
|
||||
{
|
||||
dynpara=-1;
|
||||
local.clear();
|
||||
upvalue.clear();
|
||||
keys.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
/*functions of nasal_val*/
|
||||
void nasal_obj::clear()
|
||||
{
|
||||
if(ptr)
|
||||
free(ptr);
|
||||
ptr=nullptr;
|
||||
}
|
||||
|
||||
nasal_val::nasal_val(uint8_t val_type)
|
||||
{
|
||||
mark=GC_COLLECTED;
|
||||
|
@ -283,9 +275,8 @@ nasal_val::nasal_val(uint8_t val_type)
|
|||
case vm_vec: ptr.vec=new nasal_vec; break;
|
||||
case vm_hash: ptr.hash=new nasal_hash; break;
|
||||
case vm_func: ptr.func=new nasal_func; break;
|
||||
case vm_obj: ptr.obj=nullptr; break;
|
||||
case vm_obj: ptr.obj=new nasal_obj; break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
nasal_val::~nasal_val()
|
||||
{
|
||||
|
@ -295,22 +286,16 @@ nasal_val::~nasal_val()
|
|||
case vm_vec: delete ptr.vec; break;
|
||||
case vm_hash: delete ptr.hash; break;
|
||||
case vm_func: delete ptr.func; break;
|
||||
case vm_obj:
|
||||
if(ptr.obj)
|
||||
free(ptr.obj);
|
||||
break;
|
||||
case vm_obj: delete ptr.obj; break;
|
||||
}
|
||||
ptr.obj=nullptr;
|
||||
type=vm_nil;
|
||||
return;
|
||||
}
|
||||
|
||||
/* functions of nasal_ref */
|
||||
double nasal_ref::to_number()
|
||||
{
|
||||
if(type==vm_str)
|
||||
return str2num(str()->c_str());
|
||||
return num();
|
||||
return value.num;
|
||||
}
|
||||
std::string nasal_ref::to_string()
|
||||
{
|
||||
|
@ -325,14 +310,14 @@ inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; }
|
|||
inline nasal_vec* nasal_ref::vec (){return value.gcobj->ptr.vec; }
|
||||
inline nasal_hash* nasal_ref::hash(){return value.gcobj->ptr.hash;}
|
||||
inline nasal_func* nasal_ref::func(){return value.gcobj->ptr.func;}
|
||||
inline void*& nasal_ref::obj (){return value.gcobj->ptr.obj; }
|
||||
inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; }
|
||||
|
||||
constexpr uint32_t STACK_MAX_DEPTH=2047;
|
||||
struct nasal_gc
|
||||
{
|
||||
#define STACK_MAX_DEPTH (4095)
|
||||
nasal_ref zero; // reserved address of nasal_val,type vm_num, 0
|
||||
nasal_ref one; // reserved address of nasal_val,type vm_num, 1
|
||||
nasal_ref nil; // reserved address of nasal_val,type vm_nil
|
||||
nasal_ref zero;
|
||||
nasal_ref one;
|
||||
nasal_ref nil;
|
||||
nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow
|
||||
nasal_ref* top; // stack top
|
||||
std::vector<nasal_ref> strs; // reserved address for const vm_str
|
||||
|
@ -393,11 +378,7 @@ void nasal_gc::sweep()
|
|||
case vm_vec: i->ptr.vec->elems.clear(); break;
|
||||
case vm_hash:i->ptr.hash->elems.clear();break;
|
||||
case vm_func:i->ptr.func->clear(); break;
|
||||
case vm_obj:
|
||||
if(i->ptr.obj)
|
||||
free(i->ptr.obj);
|
||||
i->ptr.obj=nullptr;
|
||||
break;
|
||||
case vm_obj: i->ptr.obj->clear(); break;
|
||||
}
|
||||
free_list[i->type].push(i);
|
||||
i->mark=GC_COLLECTED;
|
||||
|
|
|
@ -144,7 +144,7 @@ void nasal_lexer::die(const char* info)
|
|||
{
|
||||
++error;
|
||||
std::cout<<"[lexer] line "<<line<<" column "<<code.length()<<": \n"<<code<<'\n';
|
||||
for(uint32_t i=0;i<code.size()-1;++i)
|
||||
for(int i=0;i<(int)code.size()-1;++i)
|
||||
std::cout<<char(" \t"[code[i]=='\t']);
|
||||
std::cout<<'^'<<info<<'\n';
|
||||
}
|
||||
|
@ -259,7 +259,10 @@ std::string nasal_lexer::str_gen()
|
|||
}
|
||||
// check if this string ends with a " or '
|
||||
if(ptr++>=size)
|
||||
{
|
||||
die("get EOF when generating string.");
|
||||
return str;
|
||||
}
|
||||
code+=res[ptr-1];
|
||||
if(begin=='`' && str.length()!=1)
|
||||
die("\'`\' is used for string that includes one character.");
|
||||
|
|
|
@ -225,7 +225,7 @@ bool nasal_parse::check_special_call()
|
|||
{
|
||||
// special call means like this:
|
||||
// function_name(a:1,b:2,c:3);
|
||||
uint32_t check_ptr=ptr,curve=1,bracket=0,brace=0,ques=0;
|
||||
uint32_t check_ptr=ptr,curve=1,bracket=0,brace=0;
|
||||
while(tokens[++check_ptr].type!=tok_eof && curve)
|
||||
{
|
||||
switch(tokens[check_ptr].type)
|
||||
|
|
309
nasal_vm.h
309
nasal_vm.h
|
@ -4,22 +4,21 @@
|
|||
class nasal_vm
|
||||
{
|
||||
private:
|
||||
/* reference from nasal_gc */
|
||||
nasal_ref*& top; // stack top
|
||||
/* values of nasal_vm */
|
||||
uint32_t pc; // program counter
|
||||
uint32_t offset; // used to load default parameter to a new function
|
||||
std::stack<uint32_t> ret; // ptr stack stores address for function to return
|
||||
std::stack<nasal_func*> func_stk; // stack to store function,this is used when getting upvalues
|
||||
uint32_t offset; // used to load default parameters to a new function
|
||||
std::stack<uint32_t> ret; // stack to store return pc
|
||||
std::stack<nasal_func*> func_stk; // stack to store function, used to get upvalues
|
||||
std::stack<int> counter; // iterator stack for forindex/foreach
|
||||
const double* num_table;// numbers used in process(const calculation)
|
||||
std::vector<std::string> str_table;// symbols used in process
|
||||
const double* num_table;// const numbers
|
||||
std::vector<std::string> str_table;// const symbols
|
||||
std::vector<uint32_t> imm; // immediate number
|
||||
nasal_ref* mem_addr; // used for mem_call
|
||||
nasal_gc gc; // garbage collector
|
||||
/* garbage collector */
|
||||
nasal_gc gc;
|
||||
/* values used for debug */
|
||||
std::vector<opcode> bytecode; // bytecode
|
||||
std::vector<std::string> files; // files
|
||||
std::vector<opcode> bytecode;
|
||||
std::vector<std::string> files;
|
||||
|
||||
void init(
|
||||
const std::vector<std::string>&,
|
||||
|
@ -116,7 +115,6 @@ private:
|
|||
void opr_mcallh();
|
||||
void opr_ret();
|
||||
public:
|
||||
nasal_vm():top(gc.top){}
|
||||
~nasal_vm(){clear();}
|
||||
void run(
|
||||
const nasal_codegen&,
|
||||
|
@ -131,9 +129,9 @@ void nasal_vm::init(
|
|||
const std::vector<std::string>& filenames)
|
||||
{
|
||||
gc.init(strs);
|
||||
num_table=nums.data(); // get constant numbers
|
||||
str_table=strs; // get constant strings & symbols
|
||||
files=filenames;// get filenames for debugger
|
||||
num_table=nums.data();
|
||||
str_table=strs;
|
||||
files=filenames;
|
||||
}
|
||||
void nasal_vm::clear()
|
||||
{
|
||||
|
@ -176,8 +174,7 @@ void nasal_vm::traceback()
|
|||
uint32_t same=0,last=0xffffffff;
|
||||
for(uint32_t point=0;!ret.empty();last=point,ret.pop())
|
||||
{
|
||||
point=ret.top();
|
||||
if(point==last)
|
||||
if((point=ret.top())==last)
|
||||
{
|
||||
++same;
|
||||
continue;
|
||||
|
@ -197,9 +194,9 @@ void nasal_vm::stackinfo(const uint32_t limit=10)
|
|||
printf("vm stack(limit %d):\n",limit);
|
||||
uint32_t same=0,global_size=bytecode[0].num;
|
||||
nasal_ref last={vm_none,0xffffffff};
|
||||
for(uint32_t i=0;i<limit && top>=gc.stack+global_size;++i,--top)
|
||||
for(uint32_t i=0;i<limit && gc.top>=gc.stack+global_size;++i,--gc.top)
|
||||
{
|
||||
if(top[0]==last)
|
||||
if(gc.top[0]==last)
|
||||
{
|
||||
++same;
|
||||
continue;
|
||||
|
@ -209,8 +206,8 @@ void nasal_vm::stackinfo(const uint32_t limit=10)
|
|||
printf("\t... | %d same value(s)\n",same);
|
||||
same=0;
|
||||
}
|
||||
last=top[0];
|
||||
valinfo(top[0]);
|
||||
last=gc.top[0];
|
||||
valinfo(gc.top[0]);
|
||||
}
|
||||
if(same)
|
||||
printf("\t... | %d same value(s)\n",same);
|
||||
|
@ -298,109 +295,109 @@ inline void nasal_vm::opr_intg()
|
|||
{
|
||||
// global values store on stack
|
||||
for(uint32_t i=0;i<imm[pc];++i)
|
||||
(top++)[0].type=vm_nil;
|
||||
--top;// point to the top
|
||||
(gc.top++)[0].type=vm_nil;
|
||||
--gc.top;// point to the top
|
||||
}
|
||||
inline void nasal_vm::opr_intl()
|
||||
{
|
||||
top[0].func()->local.resize(imm[pc],gc.nil);
|
||||
gc.top[0].func()->local.resize(imm[pc],gc.nil);
|
||||
}
|
||||
inline void nasal_vm::opr_loadg()
|
||||
{
|
||||
gc.stack[imm[pc]]=(top--)[0];
|
||||
gc.stack[imm[pc]]=(gc.top--)[0];
|
||||
}
|
||||
inline void nasal_vm::opr_loadl()
|
||||
{
|
||||
gc.local.back().vec()->elems[imm[pc]]=(top--)[0];
|
||||
gc.local.back().vec()->elems[imm[pc]]=(gc.top--)[0];
|
||||
}
|
||||
inline void nasal_vm::opr_loadu()
|
||||
{
|
||||
func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(top--)[0];
|
||||
func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(gc.top--)[0];
|
||||
}
|
||||
inline void nasal_vm::opr_pnum()
|
||||
{
|
||||
(++top)[0]={vm_num,num_table[imm[pc]]};
|
||||
(++gc.top)[0]={vm_num,num_table[imm[pc]]};
|
||||
}
|
||||
inline void nasal_vm::opr_pone()
|
||||
{
|
||||
(++top)[0]={vm_num,(double)1};
|
||||
(++gc.top)[0]={vm_num,(double)1};
|
||||
}
|
||||
inline void nasal_vm::opr_pzero()
|
||||
{
|
||||
(++top)[0]={vm_num,(double)0};
|
||||
(++gc.top)[0]={vm_num,(double)0};
|
||||
}
|
||||
inline void nasal_vm::opr_pnil()
|
||||
{
|
||||
(++top)[0].type=vm_nil;
|
||||
(++gc.top)[0].type=vm_nil;
|
||||
}
|
||||
inline void nasal_vm::opr_pstr()
|
||||
{
|
||||
(++top)[0]=gc.strs[imm[pc]];
|
||||
(++gc.top)[0]=gc.strs[imm[pc]];
|
||||
}
|
||||
inline void nasal_vm::opr_newv()
|
||||
{
|
||||
nasal_ref newv=gc.alloc(vm_vec);
|
||||
auto& vec=newv.vec()->elems;// top-imm[pc] stores the vector
|
||||
auto& vec=newv.vec()->elems;
|
||||
vec.resize(imm[pc]);
|
||||
// use top-=imm[pc]-1 here will cause error if imm[pc] is 0
|
||||
top=top-imm[pc]+1;
|
||||
gc.top=gc.top-imm[pc]+1;
|
||||
for(uint32_t i=0;i<imm[pc];++i)
|
||||
vec[i]=top[i];
|
||||
top[0]=newv;
|
||||
vec[i]=gc.top[i];
|
||||
gc.top[0]=newv;
|
||||
}
|
||||
inline void nasal_vm::opr_newh()
|
||||
{
|
||||
(++top)[0]=gc.alloc(vm_hash);
|
||||
(++gc.top)[0]=gc.alloc(vm_hash);
|
||||
}
|
||||
inline void nasal_vm::opr_newf()
|
||||
{
|
||||
offset=1;
|
||||
(++top)[0]=gc.alloc(vm_func);
|
||||
top[0].func()->entry=imm[pc];
|
||||
(++gc.top)[0]=gc.alloc(vm_func);
|
||||
gc.top[0].func()->entry=imm[pc];
|
||||
if(!gc.local.empty())
|
||||
{
|
||||
top[0].func()->upvalue=func_stk.top()->upvalue;
|
||||
top[0].func()->upvalue.push_back(gc.local.back());
|
||||
gc.top[0].func()->upvalue=func_stk.top()->upvalue;
|
||||
gc.top[0].func()->upvalue.push_back(gc.local.back());
|
||||
}
|
||||
}
|
||||
inline void nasal_vm::opr_happ()
|
||||
{
|
||||
top[-1].hash()->elems[str_table[imm[pc]]]=top[0];
|
||||
--top;
|
||||
gc.top[-1].hash()->elems[str_table[imm[pc]]]=gc.top[0];
|
||||
--gc.top;
|
||||
}
|
||||
inline void nasal_vm::opr_para()
|
||||
{
|
||||
nasal_func* func=top[0].func();
|
||||
nasal_func* func=gc.top[0].func();
|
||||
size_t size=func->keys.size();
|
||||
func->keys[str_table[imm[pc]]]=size;
|
||||
func->local[offset++]={vm_none};
|
||||
}
|
||||
inline void nasal_vm::opr_defpara()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_func* func=(--top)[0].func();
|
||||
nasal_ref val=gc.top[0];
|
||||
nasal_func* func=(--gc.top)[0].func();
|
||||
size_t size=func->keys.size();
|
||||
func->keys[str_table[imm[pc]]]=size;
|
||||
func->local[offset++]=val;
|
||||
}
|
||||
inline void nasal_vm::opr_dynpara()
|
||||
{
|
||||
top[0].func()->dynpara=imm[pc];
|
||||
gc.top[0].func()->dynpara=imm[pc];
|
||||
}
|
||||
inline void nasal_vm::opr_unot()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_ref val=gc.top[0];
|
||||
switch(val.type)
|
||||
{
|
||||
case vm_nil:top[0]=gc.zero;break;
|
||||
case vm_num:top[0]=val.num()?gc.zero:gc.one;break;
|
||||
case vm_nil:gc.top[0]=gc.zero;break;
|
||||
case vm_num:gc.top[0]=val.num()?gc.zero:gc.one;break;
|
||||
case vm_str:
|
||||
{
|
||||
double num=str2num(val.str()->c_str());
|
||||
if(std::isnan(num))
|
||||
top[0]=val.str()->empty()?gc.one:gc.zero;
|
||||
gc.top[0]=val.str()->empty()?gc.one:gc.zero;
|
||||
else
|
||||
top[0]=num?gc.zero:gc.one;
|
||||
gc.top[0]=num?gc.zero:gc.one;
|
||||
}
|
||||
break;
|
||||
default:die("unot: incorrect value type");break;
|
||||
|
@ -408,12 +405,12 @@ inline void nasal_vm::opr_unot()
|
|||
}
|
||||
inline void nasal_vm::opr_usub()
|
||||
{
|
||||
top[0]={vm_num,-top[0].to_number()};
|
||||
gc.top[0]={vm_num,-gc.top[0].to_number()};
|
||||
}
|
||||
|
||||
#define op_calc(type)\
|
||||
nasal_ref val(vm_num,top[-1].to_number() type top[0].to_number());\
|
||||
(--top)[0]=val;
|
||||
nasal_ref val(vm_num,gc.top[-1].to_number() type gc.top[0].to_number());\
|
||||
(--gc.top)[0]=val;
|
||||
|
||||
inline void nasal_vm::opr_add(){op_calc(+);}
|
||||
inline void nasal_vm::opr_sub(){op_calc(-);}
|
||||
|
@ -422,13 +419,13 @@ inline void nasal_vm::opr_div(){op_calc(/);}
|
|||
inline void nasal_vm::opr_lnk()
|
||||
{
|
||||
nasal_ref val=gc.alloc(vm_str);
|
||||
*val.str()=top[-1].to_string()+top[0].to_string();
|
||||
(--top)[0]=val;
|
||||
*val.str()=gc.top[-1].to_string()+gc.top[0].to_string();
|
||||
(--gc.top)[0]=val;
|
||||
}
|
||||
|
||||
#define op_calc_const(type)\
|
||||
nasal_ref val(vm_num,top[0].to_number() type num_table[imm[pc]]);\
|
||||
top[0]=val;
|
||||
nasal_ref val(vm_num,gc.top[0].to_number() type num_table[imm[pc]]);\
|
||||
gc.top[0]=val;
|
||||
|
||||
inline void nasal_vm::opr_addc(){op_calc_const(+);}
|
||||
inline void nasal_vm::opr_subc(){op_calc_const(-);}
|
||||
|
@ -437,13 +434,13 @@ inline void nasal_vm::opr_divc(){op_calc_const(/);}
|
|||
inline void nasal_vm::opr_lnkc()
|
||||
{
|
||||
nasal_ref val=gc.alloc(vm_str);
|
||||
*val.str()=top[0].to_string()+str_table[imm[pc]];
|
||||
top[0]=val;
|
||||
*val.str()=gc.top[0].to_string()+str_table[imm[pc]];
|
||||
gc.top[0]=val;
|
||||
}
|
||||
|
||||
#define op_calc_eq(type)\
|
||||
nasal_ref val(vm_num,mem_addr[0].to_number() type top[-1].to_number());\
|
||||
(--top)[0]=mem_addr[0]=val;
|
||||
nasal_ref val(vm_num,mem_addr[0].to_number() type gc.top[-1].to_number());\
|
||||
(--gc.top)[0]=mem_addr[0]=val;
|
||||
|
||||
inline void nasal_vm::opr_addeq(){op_calc_eq(+);}
|
||||
inline void nasal_vm::opr_subeq(){op_calc_eq(-);}
|
||||
|
@ -452,13 +449,13 @@ inline void nasal_vm::opr_diveq(){op_calc_eq(/);}
|
|||
inline void nasal_vm::opr_lnkeq()
|
||||
{
|
||||
nasal_ref val=gc.alloc(vm_str);
|
||||
*val.str()=mem_addr[0].to_string()+top[-1].to_string();
|
||||
(--top)[0]=mem_addr[0]=val;
|
||||
*val.str()=mem_addr[0].to_string()+gc.top[-1].to_string();
|
||||
(--gc.top)[0]=mem_addr[0]=val;
|
||||
}
|
||||
|
||||
#define op_calc_eq_const(type)\
|
||||
nasal_ref val(vm_num,mem_addr[0].to_number() type num_table[imm[pc]]);\
|
||||
top[0]=mem_addr[0]=val;
|
||||
gc.top[0]=mem_addr[0]=val;
|
||||
|
||||
inline void nasal_vm::opr_addeqc(){op_calc_eq_const(+);}
|
||||
inline void nasal_vm::opr_subeqc(){op_calc_eq_const(-);}
|
||||
|
@ -468,47 +465,47 @@ inline void nasal_vm::opr_lnkeqc()
|
|||
{
|
||||
nasal_ref val=gc.alloc(vm_str);
|
||||
*val.str()=mem_addr[0].to_string()+str_table[imm[pc]];
|
||||
top[0]=mem_addr[0]=val;
|
||||
gc.top[0]=mem_addr[0]=val;
|
||||
}
|
||||
|
||||
inline void nasal_vm::opr_meq()
|
||||
{
|
||||
mem_addr[0]=(--top)[0];
|
||||
mem_addr[0]=(--gc.top)[0];
|
||||
}
|
||||
inline void nasal_vm::opr_eq()
|
||||
{
|
||||
nasal_ref val2=top[0];
|
||||
nasal_ref val1=(--top)[0];
|
||||
nasal_ref val2=gc.top[0];
|
||||
nasal_ref val1=(--gc.top)[0];
|
||||
uint8_t a_type=val1.type;
|
||||
uint8_t b_type=val2.type;
|
||||
if(a_type==vm_nil && b_type==vm_nil)
|
||||
top[0]=gc.one;
|
||||
gc.top[0]=gc.one;
|
||||
else if(a_type==vm_str && b_type==vm_str)
|
||||
top[0]=(*val1.str()==*val2.str())?gc.one:gc.zero;
|
||||
gc.top[0]=(*val1.str()==*val2.str())?gc.one:gc.zero;
|
||||
else if(a_type==vm_num || b_type==vm_num)
|
||||
top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero;
|
||||
gc.top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero;
|
||||
else
|
||||
top[0]=(val1==val2)?gc.one:gc.zero;
|
||||
gc.top[0]=(val1==val2)?gc.one:gc.zero;
|
||||
}
|
||||
inline void nasal_vm::opr_neq()
|
||||
{
|
||||
nasal_ref val2=top[0];
|
||||
nasal_ref val1=(--top)[0];
|
||||
nasal_ref val2=gc.top[0];
|
||||
nasal_ref val1=(--gc.top)[0];
|
||||
uint8_t a_type=val1.type;
|
||||
uint8_t b_type=val2.type;
|
||||
if(a_type==vm_nil && b_type==vm_nil)
|
||||
top[0]=gc.zero;
|
||||
gc.top[0]=gc.zero;
|
||||
else if(a_type==vm_str && b_type==vm_str)
|
||||
top[0]=(*val1.str()!=*val2.str())?gc.one:gc.zero;
|
||||
gc.top[0]=(*val1.str()!=*val2.str())?gc.one:gc.zero;
|
||||
else if(a_type==vm_num || b_type==vm_num)
|
||||
top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero;
|
||||
gc.top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero;
|
||||
else
|
||||
top[0]=(val1!=val2)?gc.one:gc.zero;
|
||||
gc.top[0]=(val1!=val2)?gc.one:gc.zero;
|
||||
}
|
||||
|
||||
#define op_cmp(type)\
|
||||
--top;\
|
||||
top[0]=(top[0].to_number() type top[1].to_number())?gc.one:gc.zero;
|
||||
--gc.top;\
|
||||
gc.top[0]=(gc.top[0].to_number() type gc.top[1].to_number())?gc.one:gc.zero;
|
||||
|
||||
inline void nasal_vm::opr_less(){op_cmp(<);}
|
||||
inline void nasal_vm::opr_leq(){op_cmp(<=);}
|
||||
|
@ -516,7 +513,7 @@ inline void nasal_vm::opr_grt(){op_cmp(>);}
|
|||
inline void nasal_vm::opr_geq(){op_cmp(>=);}
|
||||
|
||||
#define op_cmp_const(type)\
|
||||
top[0]=(top[0].to_number() type num_table[imm[pc]])?gc.one:gc.zero;
|
||||
gc.top[0]=(gc.top[0].to_number() type num_table[imm[pc]])?gc.one:gc.zero;
|
||||
|
||||
inline void nasal_vm::opr_lessc(){op_cmp_const(<);}
|
||||
inline void nasal_vm::opr_leqc(){op_cmp_const(<=);}
|
||||
|
@ -525,7 +522,7 @@ inline void nasal_vm::opr_geqc(){op_cmp_const(>=);}
|
|||
|
||||
inline void nasal_vm::opr_pop()
|
||||
{
|
||||
--top;
|
||||
--gc.top;
|
||||
}
|
||||
inline void nasal_vm::opr_jmp()
|
||||
{
|
||||
|
@ -533,19 +530,19 @@ inline void nasal_vm::opr_jmp()
|
|||
}
|
||||
inline void nasal_vm::opr_jt()
|
||||
{
|
||||
if(condition(top[0]))
|
||||
if(condition(gc.top[0]))
|
||||
pc=imm[pc]-1;
|
||||
}
|
||||
inline void nasal_vm::opr_jf()
|
||||
{
|
||||
if(!condition(top[0]))
|
||||
if(!condition(gc.top[0]))
|
||||
pc=imm[pc]-1;
|
||||
--top;
|
||||
--gc.top;
|
||||
}
|
||||
inline void nasal_vm::opr_counter()
|
||||
{
|
||||
counter.push(-1);
|
||||
if(top[0].type!=vm_vec)
|
||||
if(gc.top[0].type!=vm_vec)
|
||||
die("cnt: must use vector in forindex/foreach");
|
||||
}
|
||||
inline void nasal_vm::opr_cntpop()
|
||||
|
@ -554,54 +551,54 @@ inline void nasal_vm::opr_cntpop()
|
|||
}
|
||||
inline void nasal_vm::opr_findex()
|
||||
{
|
||||
if(++counter.top()>=top[0].vec()->elems.size())
|
||||
if(++counter.top()>=gc.top[0].vec()->elems.size())
|
||||
{
|
||||
pc=imm[pc]-1;
|
||||
return;
|
||||
}
|
||||
(++top)[0]={vm_num,(double)counter.top()};
|
||||
(++gc.top)[0]={vm_num,(double)counter.top()};
|
||||
}
|
||||
inline void nasal_vm::opr_feach()
|
||||
{
|
||||
std::vector<nasal_ref>& ref=top[0].vec()->elems;
|
||||
std::vector<nasal_ref>& ref=gc.top[0].vec()->elems;
|
||||
if(++counter.top()>=ref.size())
|
||||
{
|
||||
pc=imm[pc]-1;
|
||||
return;
|
||||
}
|
||||
(++top)[0]=ref[counter.top()];
|
||||
(++gc.top)[0]=ref[counter.top()];
|
||||
}
|
||||
inline void nasal_vm::opr_callg()
|
||||
{
|
||||
(++top)[0]=gc.stack[imm[pc]];
|
||||
(++gc.top)[0]=gc.stack[imm[pc]];
|
||||
}
|
||||
inline void nasal_vm::opr_calll()
|
||||
{
|
||||
(++top)[0]=gc.local.back().vec()->elems[imm[pc]];
|
||||
(++gc.top)[0]=gc.local.back().vec()->elems[imm[pc]];
|
||||
}
|
||||
inline void nasal_vm::opr_upval()
|
||||
{
|
||||
(++top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
|
||||
(++gc.top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
|
||||
}
|
||||
inline void nasal_vm::opr_callv()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_ref vec=(--top)[0];
|
||||
nasal_ref val=gc.top[0];
|
||||
nasal_ref vec=(--gc.top)[0];
|
||||
if(vec.type==vm_vec)
|
||||
{
|
||||
top[0]=vec.vec()->get_val(val.to_number());
|
||||
if(top[0].type==vm_none)
|
||||
gc.top[0]=vec.vec()->get_val(val.to_number());
|
||||
if(gc.top[0].type==vm_none)
|
||||
die("callv: index out of range:"+std::to_string(val.to_number()));
|
||||
}
|
||||
else if(vec.type==vm_hash)
|
||||
{
|
||||
if(val.type!=vm_str)
|
||||
die("callv: must use string as the key");
|
||||
top[0]=vec.hash()->get_val(*val.value.gcobj->ptr.str);
|
||||
if(top[0].type==vm_none)
|
||||
gc.top[0]=vec.hash()->get_val(*val.str());
|
||||
if(gc.top[0].type==vm_none)
|
||||
die("callv: cannot find member \""+*val.str()+"\" of this hash");
|
||||
if(top[0].type==vm_func)
|
||||
top[0].func()->local[0]=val;// me
|
||||
if(gc.top[0].type==vm_func)
|
||||
gc.top[0].func()->local[0]=val;// 'me'
|
||||
}
|
||||
else if(vec.type==vm_str)
|
||||
{
|
||||
|
@ -610,49 +607,47 @@ inline void nasal_vm::opr_callv()
|
|||
int str_size=str.length();
|
||||
if(num<-str_size || num>=str_size)
|
||||
die("callv: index out of range:"+std::to_string(val.to_number()));
|
||||
top[0]={vm_num,static_cast<double>(str[num>=0? num:num+str_size])};
|
||||
gc.top[0]={vm_num,static_cast<double>(str[num>=0? num:num+str_size])};
|
||||
}
|
||||
else
|
||||
die("callv: must call a vector/hash/string");
|
||||
}
|
||||
inline void nasal_vm::opr_callvi()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_ref val=gc.top[0];
|
||||
if(val.type!=vm_vec)
|
||||
die("callvi: must use a vector");
|
||||
|
||||
// cannot use operator[],because this may cause overflow
|
||||
(++top)[0]=val.vec()->get_val(imm[pc]);
|
||||
if(top[0].type==vm_none)
|
||||
(++gc.top)[0]=val.vec()->get_val(imm[pc]);
|
||||
if(gc.top[0].type==vm_none)
|
||||
die("callvi: index out of range:"+std::to_string(imm[pc]));
|
||||
}
|
||||
inline void nasal_vm::opr_callh()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_ref val=gc.top[0];
|
||||
if(val.type!=vm_hash)
|
||||
die("callh: must call a hash");
|
||||
|
||||
top[0]=val.hash()->get_val(str_table[imm[pc]]);
|
||||
if(top[0].type==vm_none)
|
||||
gc.top[0]=val.hash()->get_val(str_table[imm[pc]]);
|
||||
if(gc.top[0].type==vm_none)
|
||||
die("callh: member \""+str_table[imm[pc]]+"\" does not exist");
|
||||
|
||||
if(top[0].type==vm_func)
|
||||
top[0].func()->local[0]=val;// me
|
||||
if(gc.top[0].type==vm_func)
|
||||
gc.top[0].func()->local[0]=val;// 'me'
|
||||
}
|
||||
inline void nasal_vm::opr_callfv()
|
||||
{
|
||||
uint32_t args_size=imm[pc];
|
||||
nasal_ref* args=top-args_size+1;
|
||||
nasal_ref* args=gc.top-args_size+1;
|
||||
if(args[-1].type!=vm_func)
|
||||
die("callfv: must call a function");
|
||||
// push new local scope
|
||||
// push function and new local scope
|
||||
func_stk.push(args[-1].func());
|
||||
auto& func=*args[-1].func();
|
||||
|
||||
gc.local.push_back(gc.alloc(vm_vec));
|
||||
gc.local.back().vec()->elems=func.local;
|
||||
// load parameters
|
||||
auto& closure=gc.local.back().vec()->elems;
|
||||
auto& local=gc.local.back().vec()->elems;
|
||||
|
||||
uint32_t para_size=func.keys.size();
|
||||
// load arguments
|
||||
|
@ -662,83 +657,81 @@ inline void nasal_vm::opr_callfv()
|
|||
// if args_size>para_size,for 0 to args_size will cause corruption
|
||||
uint32_t min_size=std::min(para_size,args_size);
|
||||
for(uint32_t i=0;i<min_size;++i)
|
||||
closure[i+1]=args[i];
|
||||
local[i+1]=args[i];
|
||||
// load dynamic argument if args_size>=para_size
|
||||
if(func.dynpara>=0)
|
||||
{
|
||||
nasal_ref vec=gc.alloc(vm_vec);
|
||||
for(uint32_t i=para_size;i<args_size;++i)
|
||||
vec.vec()->elems.push_back(args[i]);
|
||||
closure.back()=vec;
|
||||
local.back()=vec;
|
||||
}
|
||||
|
||||
top-=args_size;// pop arguments
|
||||
gc.top-=args_size;// pop arguments
|
||||
ret.push(pc);
|
||||
pc=func.entry-1;
|
||||
}
|
||||
inline void nasal_vm::opr_callfh()
|
||||
{
|
||||
// get parameter list and function value
|
||||
auto& hash=top[0].hash()->elems;
|
||||
if(top[-1].type!=vm_func)
|
||||
auto& hash=gc.top[0].hash()->elems;
|
||||
if(gc.top[-1].type!=vm_func)
|
||||
die("callfh: must call a function");
|
||||
// push new local scope
|
||||
func_stk.push(top[-1].func());
|
||||
auto& func=*top[-1].func();
|
||||
// push function and new local scope
|
||||
func_stk.push(gc.top[-1].func());
|
||||
auto& func=*gc.top[-1].func();
|
||||
gc.local.push_back(gc.alloc(vm_vec));
|
||||
gc.local.back().vec()->elems=func.local;
|
||||
// load parameters
|
||||
auto& closure=gc.local.back().vec()->elems;
|
||||
auto& local=gc.local.back().vec()->elems;
|
||||
if(func.dynpara>=0)
|
||||
die("callfh: special call cannot use dynamic argument");
|
||||
|
||||
for(auto& i:func.keys)
|
||||
{
|
||||
if(hash.count(i.first))
|
||||
closure[i.second+1]=hash[i.first];
|
||||
local[i.second+1]=hash[i.first];
|
||||
else if(func.local[i.second+1/*1 is reserved for 'me'*/].type==vm_none)
|
||||
die("callfh: lack argument(s): \""+i.first+"\"");
|
||||
}
|
||||
|
||||
--top;// pop hash
|
||||
--gc.top;// pop hash
|
||||
ret.push(pc);
|
||||
pc=func.entry-1;
|
||||
}
|
||||
inline void nasal_vm::opr_callb()
|
||||
{
|
||||
(++top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc);
|
||||
if(top[0].type==vm_none)
|
||||
(++gc.top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc);
|
||||
if(gc.top[0].type==vm_none)
|
||||
die("native function error.");
|
||||
}
|
||||
inline void nasal_vm::opr_slcbegin()
|
||||
{
|
||||
// | slice_vector | <-- top[0]
|
||||
// ----------------
|
||||
// | resource_vec | <-- top[-1]
|
||||
// ----------------
|
||||
(++top)[0]=gc.alloc(vm_vec);
|
||||
if(top[-1].type!=vm_vec)
|
||||
// | slice_vector | <-- gc.top[0]
|
||||
// +--------------+
|
||||
// | resource_vec | <-- gc.top[-1]
|
||||
// +--------------+
|
||||
(++gc.top)[0]=gc.alloc(vm_vec);
|
||||
if(gc.top[-1].type!=vm_vec)
|
||||
die("slcbegin: must slice a vector");
|
||||
}
|
||||
inline void nasal_vm::opr_slcend()
|
||||
{
|
||||
top[-1]=top[0];
|
||||
--top;
|
||||
gc.top[-1]=gc.top[0];
|
||||
--gc.top;
|
||||
}
|
||||
inline void nasal_vm::opr_slc()
|
||||
{
|
||||
nasal_ref val=(top--)[0];
|
||||
nasal_ref res=top[-1].vec()->get_val(val.to_number());
|
||||
nasal_ref val=(gc.top--)[0];
|
||||
nasal_ref res=gc.top[-1].vec()->get_val(val.to_number());
|
||||
if(res.type==vm_none)
|
||||
die("slc: index out of range:"+std::to_string(val.to_number()));
|
||||
top[0].vec()->elems.push_back(res);
|
||||
gc.top[0].vec()->elems.push_back(res);
|
||||
}
|
||||
inline void nasal_vm::opr_slc2()
|
||||
{
|
||||
nasal_ref val2=(top--)[0];
|
||||
nasal_ref val1=(top--)[0];
|
||||
std::vector<nasal_ref>& ref=top[-1].vec()->elems;
|
||||
std::vector<nasal_ref>& aim=top[0].vec()->elems;
|
||||
nasal_ref val2=(gc.top--)[0];
|
||||
nasal_ref val1=(gc.top--)[0];
|
||||
std::vector<nasal_ref>& ref=gc.top[-1].vec()->elems;
|
||||
std::vector<nasal_ref>& aim=gc.top[0].vec()->elems;
|
||||
|
||||
uint8_t type1=val1.type,type2=val2.type;
|
||||
int num1=val1.to_number();
|
||||
|
@ -767,22 +760,22 @@ inline void nasal_vm::opr_slc2()
|
|||
inline void nasal_vm::opr_mcallg()
|
||||
{
|
||||
mem_addr=gc.stack+imm[pc];
|
||||
(++top)[0]=mem_addr[0];
|
||||
(++gc.top)[0]=mem_addr[0];
|
||||
}
|
||||
inline void nasal_vm::opr_mcalll()
|
||||
{
|
||||
mem_addr=&(gc.local.back().vec()->elems[imm[pc]]);
|
||||
(++top)[0]=mem_addr[0];
|
||||
(++gc.top)[0]=mem_addr[0];
|
||||
}
|
||||
inline void nasal_vm::opr_mupval()
|
||||
{
|
||||
mem_addr=&func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff];
|
||||
(++top)[0]=mem_addr[0];
|
||||
(++gc.top)[0]=mem_addr[0];
|
||||
}
|
||||
inline void nasal_vm::opr_mcallv()
|
||||
{
|
||||
nasal_ref val=top[0];
|
||||
nasal_ref vec=(--top)[0];
|
||||
nasal_ref val=gc.top[0];
|
||||
nasal_ref vec=(--gc.top)[0];
|
||||
if(vec.type==vm_vec)
|
||||
{
|
||||
mem_addr=vec.vec()->get_mem(val.to_number());
|
||||
|
@ -807,7 +800,7 @@ inline void nasal_vm::opr_mcallv()
|
|||
}
|
||||
inline void nasal_vm::opr_mcallh()
|
||||
{
|
||||
nasal_ref hash=top[0];
|
||||
nasal_ref hash=gc.top[0];
|
||||
if(hash.type!=vm_hash)
|
||||
die("mcallh: must call a hash");
|
||||
nasal_hash& ref=*hash.hash();
|
||||
|
@ -823,13 +816,13 @@ inline void nasal_vm::opr_ret()
|
|||
{
|
||||
// get nasal_func and set 'me' to nil
|
||||
// and rewrite nasal_func with returned value
|
||||
top[-1].func()->local[0]={vm_nil};
|
||||
--top;
|
||||
top[0]=top[1];
|
||||
gc.top[-1].func()->local[0]={vm_nil};
|
||||
--gc.top;
|
||||
gc.top[0]=gc.top[1];
|
||||
|
||||
func_stk.pop(); // pop function stack
|
||||
gc.local.pop_back(); // pop local scope
|
||||
pc=ret.top();ret.pop(); // fetch pc
|
||||
func_stk.pop();
|
||||
gc.local.pop_back();
|
||||
pc=ret.top();ret.pop();
|
||||
}
|
||||
void nasal_vm::run(
|
||||
const nasal_codegen& gen,
|
||||
|
|
Loading…
Reference in New Issue