front end optimization&stack overflow prompt
change parameter type to avoid unnecessary copies of string. change stack depth from 65536<<4 to 16+(65536<<2). now you could know stack overflow when it happens
This commit is contained in:
parent
9f2c31149a
commit
3deea632f8
66
README.md
66
README.md
|
@ -1,8 +1,10 @@
|
||||||
# Nasal Script Language
|
# Nasal Script Language
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
[Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/).
|
[Nasal](http://wiki.flightgear.org/Nasal_scripting_language) is a script language that used in [FlightGear](https://www.flightgear.org/).
|
||||||
|
|
||||||
The interpreter is totally rewritten by ValKmjolnir using C++(standard c++11) without reusing the code in Andy Ross's nasal interpreter(https://github.com/andyross/nasal). But we really appreciate that Andy created this amazing programming language and his interpreter project.
|
The interpreter is totally rewritten by ValKmjolnir using C++(standard c++11) without reusing the code in Andy Ross's nasal interpreter(<https://github.com/andyross/nasal>). But we really appreciate that Andy created this amazing programming language and his interpreter project.
|
||||||
|
|
||||||
The interpreter is still in development(now it works well --2021/2/15). We really need your support!
|
The interpreter is still in development(now it works well --2021/2/15). We really need your support!
|
||||||
|
|
||||||
|
@ -10,9 +12,9 @@ Also,i am a member of [FGPRC](https://www.fgprc.org/), welcome to join us!
|
||||||
|
|
||||||
(2021/5/4) Now this project uses MIT license.Edit it if you want, use this project to learn or create more interesting things(But don't forget me XD).
|
(2021/5/4) Now this project uses MIT license.Edit it if you want, use this project to learn or create more interesting things(But don't forget me XD).
|
||||||
|
|
||||||
# Why Writing Nasal Interpreter
|
## Why Writing Nasal Interpreter
|
||||||
|
|
||||||
Nasal is a script language first used in Flightgear, created by Andy Ross(https://github.com/andyross).
|
Nasal is a script language first used in Flightgear, created by Andy Ross(<https://github.com/andyross>).
|
||||||
|
|
||||||
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax errors.
|
But in last summer holiday, members in FGPRC told me that it is hard to debug with nasal-console in Flightgear, especially when checking syntax errors.
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ Also, you could use this language to write some interesting programs and run the
|
||||||
|
|
||||||
You could add your own built-in functions to change this interpreter to a useful tool in your own projects(such as a script in your own game).
|
You could add your own built-in functions to change this interpreter to a useful tool in your own projects(such as a script in your own game).
|
||||||
|
|
||||||
# How to Compile
|
## How to Compile
|
||||||
|
|
||||||
Better choose the latest update of the interpreter.
|
Better choose the latest update of the interpreter.
|
||||||
|
|
||||||
|
@ -34,7 +36,7 @@ MUST USE -O2 ! pragma gcc optimize(2) seems useless when using g++
|
||||||
|
|
||||||
> g++ -std=c++11 -O2 main.cpp -o main.exe
|
> g++ -std=c++11 -O2 main.cpp -o main.exe
|
||||||
|
|
||||||
# Parser
|
## Parser
|
||||||
|
|
||||||
LL(k) parser.
|
LL(k) parser.
|
||||||
|
|
||||||
|
@ -47,7 +49,7 @@ These two expressions have the same first set,so LL(1) is useless for this langu
|
||||||
|
|
||||||
Maybe in the future i can refactor it to LL(1) with special checks.
|
Maybe in the future i can refactor it to LL(1) with special checks.
|
||||||
|
|
||||||
## version 1.0(last update 2019/10/14)
|
### version 1.0(last update 2019/10/14)
|
||||||
|
|
||||||
First fully functional version of nasal_parser.
|
First fully functional version of nasal_parser.
|
||||||
|
|
||||||
|
@ -59,17 +61,17 @@ In version 0.17(2019/9/15) 0.18(2019/9/18) 0.19(2019/10/1)i was playing the pars
|
||||||
|
|
||||||
This project began at 2019/8/31.
|
This project began at 2019/8/31.
|
||||||
|
|
||||||
# Abstract Syntax Tree
|
## Abstract Syntax Tree
|
||||||
|
|
||||||
## Version 1.2(last update 2019/10/31)
|
### Version 1.2(last update 2019/10/31)
|
||||||
|
|
||||||
The ast has been completed in this version.
|
The ast has been completed in this version.
|
||||||
|
|
||||||
## Version 2.0(last update 2020/8/31)
|
### Version 2.0(last update 2020/8/31)
|
||||||
|
|
||||||
A completed ast-interpreter with unfinished lib functions.
|
A completed ast-interpreter with unfinished lib functions.
|
||||||
|
|
||||||
## Version 3.0(last update 2020/10/23)
|
### Version 3.0(last update 2020/10/23)
|
||||||
|
|
||||||
The ast is refactored and is now easier to read and maintain.
|
The ast is refactored and is now easier to read and maintain.
|
||||||
|
|
||||||
|
@ -79,15 +81,15 @@ Now you can add your own functions as builtin-functions in this interpreter!
|
||||||
|
|
||||||
I decide to save the ast interpreter after releasing v4.0. Because it took me a long time to think and write...
|
I decide to save the ast interpreter after releasing v4.0. Because it took me a long time to think and write...
|
||||||
|
|
||||||
## Version 5.0(last update 2021/3/7)
|
### Version 5.0(last update 2021/3/7)
|
||||||
|
|
||||||
I change my mind.AST interpreter leaves me too much things to do.
|
I change my mind.AST interpreter leaves me too much things to do.
|
||||||
|
|
||||||
If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient.
|
If i continue saving this interpreter,it will be harder for me to make the bytecode vm become more efficient.
|
||||||
|
|
||||||
# Byte Code Interpreter
|
## Byte Code Interpreter
|
||||||
|
|
||||||
## Version 4.0(last update 2020/12/17)
|
### Version 4.0(last update 2020/12/17)
|
||||||
|
|
||||||
I have just finished the first version of byte-code-interpreter.
|
I have just finished the first version of byte-code-interpreter.
|
||||||
|
|
||||||
|
@ -120,7 +122,7 @@ for(var i=0;i<4000000;i+=1);
|
||||||
0x0000000b: nop 0x00000000
|
0x0000000b: nop 0x00000000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Version 5.0(last update 2021/3/7)
|
### Version 5.0(last update 2021/3/7)
|
||||||
|
|
||||||
I decide to optimize bytecode vm in this version.
|
I decide to optimize bytecode vm in this version.
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ Because it takes more than 1.5s to count i from 0 to 4000000-1.This is not effic
|
||||||
|
|
||||||
2021/1/23 update: Now it can count from 0 to 4000000-1 in 1.5s.
|
2021/1/23 update: Now it can count from 0 to 4000000-1 in 1.5s.
|
||||||
|
|
||||||
## Version 6.0(last update 2021/6/1)
|
### Version 6.0(last update 2021/6/1)
|
||||||
|
|
||||||
Use loadg loadl callg calll mcallg mcalll to avoid branches.
|
Use loadg loadl callg calll mcallg mcalll to avoid branches.
|
||||||
|
|
||||||
|
@ -169,7 +171,7 @@ for(var i=0;i<4000000;i+=1);
|
||||||
0x0000000c: nop 0x00000000
|
0x0000000c: nop 0x00000000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Version 6.5(latest)
|
### Version 6.5(latest)
|
||||||
|
|
||||||
2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error.
|
2021/5/31 update: Now gc can collect garbage correctly without re-collecting,which will cause fatal error.
|
||||||
|
|
||||||
|
@ -213,9 +215,9 @@ f(1024,2048);
|
||||||
0x00000011: nop 0x00000000
|
0x00000011: nop 0x00000000
|
||||||
```
|
```
|
||||||
|
|
||||||
# How to Use Nasal to Program
|
## How to Use Nasal to Program
|
||||||
|
|
||||||
## basic value type
|
### basic value type
|
||||||
|
|
||||||
Nasal has 6 value types.Number,string,vector,hash,function,nil.
|
Nasal has 6 value types.Number,string,vector,hash,function,nil.
|
||||||
|
|
||||||
|
@ -281,7 +283,7 @@ var f=func(x,y,z,dynamic_para...)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## operators
|
### operators
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
1+2;
|
1+2;
|
||||||
|
@ -311,7 +313,7 @@ a/=1;
|
||||||
a~='string';
|
a~='string';
|
||||||
```
|
```
|
||||||
|
|
||||||
## definition
|
### definition
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a=1;
|
var a=1;
|
||||||
|
@ -321,14 +323,14 @@ var (a,b,c)=(0,1,2);
|
||||||
(var a,b,c)=(0,1,2);
|
(var a,b,c)=(0,1,2);
|
||||||
```
|
```
|
||||||
|
|
||||||
## multi-assignment
|
### multi-assignment
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
(a,b[0],c.d)=[0,1,2];
|
(a,b[0],c.d)=[0,1,2];
|
||||||
(a,b[1],c.e)=(0,1,2);
|
(a,b[1],c.e)=(0,1,2);
|
||||||
```
|
```
|
||||||
|
|
||||||
## conditional expression
|
### conditional expression
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
if(1)
|
if(1)
|
||||||
|
@ -349,7 +351,7 @@ else
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## loop
|
### loop
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
while(condition)
|
while(condition)
|
||||||
|
@ -365,7 +367,7 @@ foreach(var i;elem)
|
||||||
print(i);
|
print(i);
|
||||||
```
|
```
|
||||||
|
|
||||||
## subvec
|
### subvec
|
||||||
|
|
||||||
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
|
Use index to search one element in the string will get the ascii number of this character.If you want to get the character,use built-in function chr().
|
||||||
|
|
||||||
|
@ -374,7 +376,7 @@ a[-1,1,0:2,0:,:3,:,nil:8,3:nil,nil:nil];
|
||||||
"hello world"[0];
|
"hello world"[0];
|
||||||
```
|
```
|
||||||
|
|
||||||
## special function call
|
### special function call
|
||||||
|
|
||||||
This is of great use but is not very efficient(because hashmap use string as the key to compare).
|
This is of great use but is not very efficient(because hashmap use string as the key to compare).
|
||||||
|
|
||||||
|
@ -382,7 +384,7 @@ This is of great use but is not very efficient(because hashmap use string as the
|
||||||
a(x:0,y:1,z:2);
|
a(x:0,y:1,z:2);
|
||||||
```
|
```
|
||||||
|
|
||||||
## lambda
|
### lambda
|
||||||
|
|
||||||
Also functions have this kind of use:
|
Also functions have this kind of use:
|
||||||
|
|
||||||
|
@ -391,7 +393,7 @@ func(x,y){return x+y}(0,1);
|
||||||
func(x){return 1/(1+math.exp(-x));}(0.5);
|
func(x){return 1/(1+math.exp(-x));}(0.5);
|
||||||
```
|
```
|
||||||
|
|
||||||
## closure
|
### closure
|
||||||
|
|
||||||
Use closure to OOP.
|
Use closure to OOP.
|
||||||
|
|
||||||
|
@ -419,7 +421,7 @@ var student=func(name,age)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## built-in functions
|
### built-in functions
|
||||||
|
|
||||||
Must import lib.nas or has these functions' definitions inside your code.
|
Must import lib.nas or has these functions' definitions inside your code.
|
||||||
|
|
||||||
|
@ -522,11 +524,3 @@ nasal_val* builtin_getkeys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
# 写在最后
|
|
||||||
|
|
||||||
我要怎么才能告诉gitee的逆天管理员gitee上的ValKmjolnir和github的ValKmjolnir是一个人?
|
|
||||||
|
|
||||||
他居然告诉我,我从github同步的仓库是他人项目?
|
|
||||||
|
|
||||||
我证明我是我自己?:sweat_smile:
|
|
2
main.cpp
2
main.cpp
|
@ -28,7 +28,7 @@ void logo()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void die(std::string stage,std::string filename)
|
void die(const char* stage,std::string& filename)
|
||||||
{
|
{
|
||||||
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
|
std::cout<<">> ["<<stage<<"] in <\""<<filename<<"\">: error(s) occurred,stop.\n";
|
||||||
return;
|
return;
|
||||||
|
|
192
nasal_ast.h
192
nasal_ast.h
|
@ -4,8 +4,7 @@
|
||||||
enum ast_node
|
enum ast_node
|
||||||
{
|
{
|
||||||
ast_null=0,
|
ast_null=0,
|
||||||
ast_root,
|
ast_root,ast_block,
|
||||||
ast_block,
|
|
||||||
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
|
ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec,
|
||||||
ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec,
|
ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec,
|
||||||
ast_args,ast_default_arg,ast_dynamic_id,
|
ast_args,ast_default_arg,ast_dynamic_id,
|
||||||
|
@ -20,74 +19,31 @@ enum ast_node
|
||||||
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter,
|
||||||
ast_conditional,ast_if,ast_elsif,ast_else,
|
ast_conditional,ast_if,ast_elsif,ast_else,
|
||||||
ast_multi_id,ast_multi_scalar,
|
ast_multi_id,ast_multi_scalar,
|
||||||
ast_definition,ast_multi_assign,
|
ast_def,ast_multi_assign,
|
||||||
ast_continue,ast_break,ast_return
|
ast_continue,ast_break,ast_ret
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ast_name(int type)
|
const char* ast_name[]=
|
||||||
{
|
{
|
||||||
switch(type)
|
"null",
|
||||||
{
|
"root","block",
|
||||||
case ast_null: return "null";
|
"nil","num","str","id","func","hash","vec",
|
||||||
case ast_root: return "root";
|
"hashmember","call","callh","callv","callf","subvec",
|
||||||
case ast_block: return "block";
|
"args","deflt_arg","dyn_id",
|
||||||
case ast_nil: return "nil";
|
"and","or",
|
||||||
case ast_num: return "number";
|
"=","+=","-=","*=","/=","~=",
|
||||||
case ast_str: return "string";
|
"==","!=",
|
||||||
case ast_id: return "id";
|
"<","<=",
|
||||||
case ast_func: return "function";
|
">",">=",
|
||||||
case ast_hash: return "hash";
|
"+","-","*","/","~",
|
||||||
case ast_vec: return "vector";
|
"unary-","unary!",
|
||||||
case ast_hashmember: return "hashmember";
|
"trino",
|
||||||
case ast_call: return "call";
|
"for","forindex","foreach","while","iter",
|
||||||
case ast_callh: return "callh";
|
"conditional","if","elsif","else",
|
||||||
case ast_callv: return "callv";
|
"multi_id","multi_scalar",
|
||||||
case ast_callf: return "callf";
|
"def","multi_assign",
|
||||||
case ast_subvec: return "subvec";
|
"continue","break","return"
|
||||||
case ast_args: return "args";
|
};
|
||||||
case ast_default_arg: return "deflt_arg";
|
|
||||||
case ast_dynamic_id: return "dyn_id";
|
|
||||||
case ast_and: return "and";
|
|
||||||
case ast_or: return "or";
|
|
||||||
case ast_equal: return "=";
|
|
||||||
case ast_addeq: return "+=";
|
|
||||||
case ast_subeq: return "-=";
|
|
||||||
case ast_multeq: return "*=";
|
|
||||||
case ast_diveq: return "/=";
|
|
||||||
case ast_lnkeq: return "~=";
|
|
||||||
case ast_cmpeq: return "==";
|
|
||||||
case ast_neq: return "!=";
|
|
||||||
case ast_less: return "<";
|
|
||||||
case ast_leq: return "<=";
|
|
||||||
case ast_grt: return ">";
|
|
||||||
case ast_geq: return ">=";
|
|
||||||
case ast_add: return "+";
|
|
||||||
case ast_sub: return "-";
|
|
||||||
case ast_mult: return "*";
|
|
||||||
case ast_div: return "/";
|
|
||||||
case ast_link: return "~";
|
|
||||||
case ast_neg: return "unary-";
|
|
||||||
case ast_not: return "unary!";
|
|
||||||
case ast_trino: return "trino";
|
|
||||||
case ast_for: return "for";
|
|
||||||
case ast_forindex: return "forindex";
|
|
||||||
case ast_foreach: return "foreach";
|
|
||||||
case ast_while: return "while";
|
|
||||||
case ast_new_iter: return "iter";
|
|
||||||
case ast_conditional: return "conditional";
|
|
||||||
case ast_if: return "if";
|
|
||||||
case ast_elsif: return "elsif";
|
|
||||||
case ast_else: return "else";
|
|
||||||
case ast_multi_id: return "multi_id";
|
|
||||||
case ast_multi_scalar: return "multi_scalar";
|
|
||||||
case ast_definition: return "def";
|
|
||||||
case ast_multi_assign: return "multi_assign";
|
|
||||||
case ast_continue: return "continue";
|
|
||||||
case ast_break: return "break";
|
|
||||||
case ast_return: return "return";
|
|
||||||
}
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
|
|
||||||
class nasal_ast
|
class nasal_ast
|
||||||
{
|
{
|
||||||
|
@ -98,39 +54,24 @@ private:
|
||||||
std::string str;
|
std::string str;
|
||||||
std::vector<nasal_ast> children;
|
std::vector<nasal_ast> children;
|
||||||
public:
|
public:
|
||||||
nasal_ast();
|
nasal_ast(){line=0;type=ast_null;}
|
||||||
nasal_ast(int,int);
|
nasal_ast(int l,int t){line=l;type=t;}
|
||||||
nasal_ast(const nasal_ast&);
|
nasal_ast(const nasal_ast&);
|
||||||
~nasal_ast();
|
|
||||||
nasal_ast& operator=(const nasal_ast&);
|
nasal_ast& operator=(const nasal_ast&);
|
||||||
void print_ast(int);
|
void print_ast(int);
|
||||||
void clear();
|
void clear();
|
||||||
void set_line(int);
|
void add_child(nasal_ast ast){children.push_back(ast);}
|
||||||
void set_type(int);
|
void set_line(int l){line=l;}
|
||||||
void set_str(std::string&);
|
void set_type(int t){type=t;}
|
||||||
void set_num(double);
|
void set_str(std::string& s){str=s;}
|
||||||
void add_child(nasal_ast);
|
void set_num(double n){num=n;}
|
||||||
int get_line();
|
int get_line(){return line;}
|
||||||
int get_type();
|
int get_type(){return type;}
|
||||||
double get_num();
|
double get_num(){return num;}
|
||||||
std::string& get_str();
|
std::string& get_str(){return str;}
|
||||||
std::vector<nasal_ast>& get_children();
|
std::vector<nasal_ast>& get_children(){return children;}
|
||||||
};
|
};
|
||||||
|
|
||||||
nasal_ast::nasal_ast()
|
|
||||||
{
|
|
||||||
line=0;
|
|
||||||
type=ast_null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nasal_ast::nasal_ast(int _line,int _type)
|
|
||||||
{
|
|
||||||
line=_line;
|
|
||||||
type=_type;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||||
{
|
{
|
||||||
line=tmp.line;
|
line=tmp.line;
|
||||||
|
@ -141,12 +82,6 @@ nasal_ast::nasal_ast(const nasal_ast& tmp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast::~nasal_ast()
|
|
||||||
{
|
|
||||||
children.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
nasal_ast& nasal_ast::operator=(const nasal_ast& tmp)
|
||||||
{
|
{
|
||||||
line=tmp.line;
|
line=tmp.line;
|
||||||
|
@ -167,67 +102,12 @@ void nasal_ast::clear()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_ast::set_line(int l)
|
|
||||||
{
|
|
||||||
line=l;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_ast::set_type(int t)
|
|
||||||
{
|
|
||||||
type=t;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_ast::set_str(std::string& s)
|
|
||||||
{
|
|
||||||
str=s;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_ast::set_num(double n)
|
|
||||||
{
|
|
||||||
num=n;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_ast::add_child(nasal_ast ast)
|
|
||||||
{
|
|
||||||
children.push_back(ast);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nasal_ast::get_line()
|
|
||||||
{
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nasal_ast::get_type()
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string& nasal_ast::get_str()
|
|
||||||
{
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
double nasal_ast::get_num()
|
|
||||||
{
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<nasal_ast>& nasal_ast::get_children()
|
|
||||||
{
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_ast::print_ast(int depth)
|
void nasal_ast::print_ast(int depth)
|
||||||
{
|
{
|
||||||
std::string indentation="";
|
std::string indentation="";
|
||||||
for(int i=0;i<depth;++i)
|
for(int i=0;i<depth;++i)
|
||||||
indentation+="| ";
|
indentation+="| ";
|
||||||
std::cout<<indentation<<ast_name(type);
|
std::cout<<indentation<<ast_name[type];
|
||||||
if(type==ast_str || type==ast_id || type==ast_dynamic_id || type==ast_callh)
|
if(type==ast_str || type==ast_id || type==ast_dynamic_id || type==ast_callh)
|
||||||
std::cout<<":"<<str;
|
std::cout<<":"<<str;
|
||||||
else if(type==ast_num)
|
else if(type==ast_num)
|
||||||
|
|
|
@ -55,7 +55,7 @@ nasal_val* builtin_right(std::vector<nasal_val*>&,nasal_gc&);
|
||||||
nasal_val* builtin_cmp(std::vector<nasal_val*>&,nasal_gc&);
|
nasal_val* builtin_cmp(std::vector<nasal_val*>&,nasal_gc&);
|
||||||
nasal_val* builtin_chr(std::vector<nasal_val*>&,nasal_gc&);
|
nasal_val* builtin_chr(std::vector<nasal_val*>&,nasal_gc&);
|
||||||
|
|
||||||
void builtin_err(std::string func_name,std::string info)
|
void builtin_err(const char* func_name,std::string info)
|
||||||
{
|
{
|
||||||
std::cout<<">> [vm] "<<func_name<<": "<<info<<".\n";
|
std::cout<<">> [vm] "<<func_name<<": "<<info<<".\n";
|
||||||
return;
|
return;
|
||||||
|
@ -65,7 +65,7 @@ void builtin_err(std::string func_name,std::string info)
|
||||||
// this table must end with {"",NULL}
|
// this table must end with {"",NULL}
|
||||||
struct FUNC_TABLE
|
struct FUNC_TABLE
|
||||||
{
|
{
|
||||||
std::string name;
|
const char* name;
|
||||||
nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&);
|
nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&);
|
||||||
} builtin_func[]=
|
} builtin_func[]=
|
||||||
{
|
{
|
||||||
|
|
|
@ -216,13 +216,13 @@ private:
|
||||||
void ret_gen(nasal_ast&);
|
void ret_gen(nasal_ast&);
|
||||||
public:
|
public:
|
||||||
nasal_codegen();
|
nasal_codegen();
|
||||||
int get_error();
|
int get_error(){return error;}
|
||||||
void main_progress(nasal_ast&);
|
void main_progress(nasal_ast&);
|
||||||
void print_op(int);
|
void print_op(int);
|
||||||
void print_byte_code();
|
void print_byte_code();
|
||||||
std::vector<std::string>& get_str_table();
|
std::vector<std::string>& get_str_table(){return str_res_table;}
|
||||||
std::vector<double>& get_num_table();
|
std::vector<double>& get_num_table(){return num_res_table;}
|
||||||
std::vector<opcode>& get_exec_code();
|
std::vector<opcode>& get_exec_code(){return exec_code;}
|
||||||
};
|
};
|
||||||
|
|
||||||
nasal_codegen::nasal_codegen()
|
nasal_codegen::nasal_codegen()
|
||||||
|
@ -420,7 +420,7 @@ void nasal_codegen::func_gen(nasal_ast& ast)
|
||||||
exec_code[local_label].num+=i.size();
|
exec_code[local_label].num+=i.size();
|
||||||
local.pop_back();
|
local.pop_back();
|
||||||
|
|
||||||
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return)
|
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_ret)
|
||||||
{
|
{
|
||||||
nil_gen();
|
nil_gen();
|
||||||
gen(op_ret,0);
|
gen(op_ret,0);
|
||||||
|
@ -708,10 +708,10 @@ void nasal_codegen::loop_gen(nasal_ast& ast)
|
||||||
|
|
||||||
void nasal_codegen::load_continue_break(int continue_place,int break_place)
|
void nasal_codegen::load_continue_break(int continue_place,int break_place)
|
||||||
{
|
{
|
||||||
for(int i=0;i<continue_ptr.front().size();++i)
|
for(auto i:continue_ptr.front())
|
||||||
exec_code[continue_ptr.front()[i]].num=continue_place;
|
exec_code[i].num=continue_place;
|
||||||
for(int i=0;i<break_ptr.front().size();++i)
|
for(auto i:break_ptr.front())
|
||||||
exec_code[break_ptr.front()[i]].num=break_place;
|
exec_code[i].num=break_place;
|
||||||
continue_ptr.pop_front();
|
continue_ptr.pop_front();
|
||||||
break_ptr.pop_front();
|
break_ptr.pop_front();
|
||||||
return;
|
return;
|
||||||
|
@ -737,7 +737,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
|
||||||
switch(ast.get_children()[0].get_type())
|
switch(ast.get_children()[0].get_type())
|
||||||
{
|
{
|
||||||
case ast_null:break;
|
case ast_null:break;
|
||||||
case ast_definition:def_gen(ast.get_children()[0]);break;
|
case ast_def:def_gen(ast.get_children()[0]);break;
|
||||||
case ast_multi_assign:multi_assign_gen(ast.get_children()[0]);break;
|
case ast_multi_assign:multi_assign_gen(ast.get_children()[0]);break;
|
||||||
case ast_nil:
|
case ast_nil:
|
||||||
case ast_num:
|
case ast_num:
|
||||||
|
@ -780,7 +780,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
|
||||||
switch(ast.get_children()[2].get_type())
|
switch(ast.get_children()[2].get_type())
|
||||||
{
|
{
|
||||||
case ast_null:break;
|
case ast_null:break;
|
||||||
case ast_definition:def_gen(ast.get_children()[2]);break;
|
case ast_def:def_gen(ast.get_children()[2]);break;
|
||||||
case ast_multi_assign:multi_assign_gen(ast.get_children()[2]);break;
|
case ast_multi_assign:multi_assign_gen(ast.get_children()[2]);break;
|
||||||
case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
||||||
case ast_vec:case ast_hash:
|
case ast_vec:case ast_hash:
|
||||||
|
@ -955,7 +955,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
|
||||||
calc_gen(ast.get_children()[0]);
|
calc_gen(ast.get_children()[0]);
|
||||||
gen(op_unot,0);
|
gen(op_unot,0);
|
||||||
break;
|
break;
|
||||||
case ast_definition:
|
case ast_def:
|
||||||
single_def(ast);
|
single_def(ast);
|
||||||
call_id(ast.get_children()[0]);
|
call_id(ast.get_children()[0]);
|
||||||
break;
|
break;
|
||||||
|
@ -969,7 +969,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
|
||||||
switch(tmp.get_type())
|
switch(tmp.get_type())
|
||||||
{
|
{
|
||||||
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
||||||
case ast_definition:def_gen(tmp);break;
|
case ast_def:def_gen(tmp);break;
|
||||||
case ast_multi_assign:multi_assign_gen(tmp);break;
|
case ast_multi_assign:multi_assign_gen(tmp);break;
|
||||||
case ast_conditional:conditional_gen(tmp);break;
|
case ast_conditional:conditional_gen(tmp);break;
|
||||||
case ast_continue:
|
case ast_continue:
|
||||||
|
@ -1010,7 +1010,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
|
||||||
case ast_or:
|
case ast_or:
|
||||||
case ast_and:
|
case ast_and:
|
||||||
case ast_trino:calc_gen(tmp);pop_gen();break;
|
case ast_trino:calc_gen(tmp);pop_gen();break;
|
||||||
case ast_return:ret_gen(tmp);break;
|
case ast_ret:ret_gen(tmp);break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1045,14 +1045,12 @@ void nasal_codegen::main_progress(nasal_ast& ast)
|
||||||
global.clear();
|
global.clear();
|
||||||
local.clear();
|
local.clear();
|
||||||
gen(op_intg,0);
|
gen(op_intg,0);
|
||||||
int size=ast.get_children().size();
|
for(auto& tmp:ast.get_children())
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
{
|
{
|
||||||
nasal_ast& tmp=ast.get_children()[i];
|
|
||||||
switch(tmp.get_type())
|
switch(tmp.get_type())
|
||||||
{
|
{
|
||||||
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
|
||||||
case ast_definition:def_gen(tmp);break;
|
case ast_def:def_gen(tmp);break;
|
||||||
case ast_multi_assign:multi_assign_gen(tmp);break;
|
case ast_multi_assign:multi_assign_gen(tmp);break;
|
||||||
case ast_conditional:conditional_gen(tmp);break;
|
case ast_conditional:conditional_gen(tmp);break;
|
||||||
case ast_while:
|
case ast_while:
|
||||||
|
@ -1100,31 +1098,22 @@ void nasal_codegen::main_progress(nasal_ast& ast)
|
||||||
|
|
||||||
void nasal_codegen::print_op(int index)
|
void nasal_codegen::print_op(int index)
|
||||||
{
|
{
|
||||||
// print opcode ptr
|
// print opcode index,opcode name,opcode immediate number
|
||||||
printf("0x%.8x: ",index);
|
printf("0x%.8x: %s 0x%.8x",index,code_table[exec_code[index].op].name,exec_code[index].num);
|
||||||
// print opcode name
|
|
||||||
for(int i=0;code_table[i].name;++i)
|
|
||||||
if(exec_code[index].op==code_table[i].type)
|
|
||||||
{
|
|
||||||
std::cout<<code_table[i].name<<" ";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// print opcode index
|
|
||||||
printf("0x%.8x ",exec_code[index].num);
|
|
||||||
// print detail info
|
// print detail info
|
||||||
switch(exec_code[index].op)
|
switch(exec_code[index].op)
|
||||||
{
|
{
|
||||||
case op_pnum:std::cout<<'('<<num_res_table[exec_code[index].num]<<')';break;
|
case op_pnum:printf(" (%lf)\n",num_res_table[exec_code[index].num]);break;
|
||||||
case op_callb:std::cout<<'('<<builtin_func[exec_code[index].num].name<<')';break;
|
case op_callb:printf(" (%s)\n",builtin_func[exec_code[index].num].name);break;
|
||||||
case op_happ:
|
case op_happ:
|
||||||
case op_pstr:
|
case op_pstr:
|
||||||
case op_callh:
|
case op_callh:
|
||||||
case op_mcallh:
|
case op_mcallh:
|
||||||
case op_para:
|
case op_para:
|
||||||
case op_defpara:
|
case op_defpara:
|
||||||
case op_dynpara:std::cout<<'('<<str_res_table[exec_code[index].num]<<')';break;
|
case op_dynpara:printf(" (%s)\n",str_res_table[exec_code[index].num].c_str());break;
|
||||||
|
default:printf("\n");break;
|
||||||
}
|
}
|
||||||
std::cout<<'\n';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1134,30 +1123,9 @@ void nasal_codegen::print_byte_code()
|
||||||
std::cout<<".number "<<num<<'\n';
|
std::cout<<".number "<<num<<'\n';
|
||||||
for(auto& str:str_res_table)
|
for(auto& str:str_res_table)
|
||||||
std::cout<<".symbol "<<str<<'\n';
|
std::cout<<".symbol "<<str<<'\n';
|
||||||
int size=exec_code.size();
|
for(int i=0;i<exec_code.size();++i)
|
||||||
for(int i=0;i<size;++i)
|
|
||||||
print_op(i);
|
print_op(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>& nasal_codegen::get_str_table()
|
|
||||||
{
|
|
||||||
return str_res_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<double>& nasal_codegen::get_num_table()
|
|
||||||
{
|
|
||||||
return num_res_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<opcode>& nasal_codegen::get_exec_code()
|
|
||||||
{
|
|
||||||
return exec_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nasal_codegen::get_error()
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
14
nasal_gc.h
14
nasal_gc.h
|
@ -242,11 +242,11 @@ std::string nasal_val::to_string()
|
||||||
|
|
||||||
struct nasal_gc
|
struct nasal_gc
|
||||||
{
|
{
|
||||||
#define STACK_MAX_DEPTH (65536<<4)
|
#define STACK_MAX_DEPTH (65536<<2)
|
||||||
nasal_val* zero_addr; // reserved address of nasal_val,type vm_num, 0
|
nasal_val* zero_addr; // reserved address of nasal_val,type vm_num, 0
|
||||||
nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1
|
nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1
|
||||||
nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil
|
nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil
|
||||||
nasal_val* val_stack[STACK_MAX_DEPTH];
|
nasal_val* val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow
|
||||||
nasal_val** stack_top; // stack top
|
nasal_val** stack_top; // stack top
|
||||||
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
|
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
|
||||||
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
|
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
|
||||||
|
@ -344,17 +344,15 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
|
||||||
num_addrs.resize(nums.size());
|
num_addrs.resize(nums.size());
|
||||||
for(int i=0;i<nums.size();++i)
|
for(int i=0;i<nums.size();++i)
|
||||||
{
|
{
|
||||||
nasal_val* tmp=new nasal_val(vm_num);
|
num_addrs[i]=new nasal_val(vm_num);
|
||||||
tmp->ptr.num=nums[i];
|
num_addrs[i]->ptr.num=nums[i];
|
||||||
num_addrs[i]=tmp;
|
|
||||||
}
|
}
|
||||||
// init constant strings
|
// init constant strings
|
||||||
str_addrs.resize(strs.size());
|
str_addrs.resize(strs.size());
|
||||||
for(int i=0;i<strs.size();++i)
|
for(int i=0;i<strs.size();++i)
|
||||||
{
|
{
|
||||||
nasal_val* tmp=new nasal_val(vm_str);
|
str_addrs[i]=new nasal_val(vm_str);
|
||||||
*tmp->ptr.str=strs[i];
|
*str_addrs[i]->ptr.str=strs[i];
|
||||||
str_addrs[i]=tmp;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,24 @@
|
||||||
class nasal_import
|
class nasal_import
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
nasal_lexer import_lex;
|
|
||||||
nasal_parse import_par;
|
|
||||||
nasal_ast import_ast;
|
|
||||||
std::vector<std::string> filename_table;
|
|
||||||
int error;
|
int error;
|
||||||
void die(std::string,std::string);
|
nasal_lexer import_lex;
|
||||||
|
nasal_parse import_par;
|
||||||
|
nasal_ast import_ast;
|
||||||
|
std::vector<std::string> filename_table;
|
||||||
|
void die(std::string&,const char*);
|
||||||
bool check_import(nasal_ast&);
|
bool check_import(nasal_ast&);
|
||||||
bool check_exist(std::string);
|
bool check_exist(std::string&);
|
||||||
void linker(nasal_ast&,nasal_ast&);
|
void linker(nasal_ast&,nasal_ast&);
|
||||||
nasal_ast file_import(nasal_ast&);
|
nasal_ast file_import(nasal_ast&);
|
||||||
nasal_ast load(nasal_ast&);
|
nasal_ast load(nasal_ast&);
|
||||||
public:
|
public:
|
||||||
int get_error();
|
int get_error(){return error;}
|
||||||
void link(nasal_ast&);
|
void link(nasal_ast&);
|
||||||
nasal_ast& get_root();
|
nasal_ast& get_root(){return import_ast;}
|
||||||
};
|
};
|
||||||
|
|
||||||
void nasal_import::die(std::string filename,std::string error_stage)
|
void nasal_import::die(std::string& filename,const char* error_stage)
|
||||||
{
|
{
|
||||||
++error;
|
++error;
|
||||||
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n";
|
std::cout<<">> [import] in <\""<<filename<<"\">: error(s) occurred in "<<error_stage<<".\n";
|
||||||
|
@ -51,7 +51,7 @@ only this kind of node can be recognized as 'import':
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nasal_import::check_exist(std::string filename)
|
bool nasal_import::check_exist(std::string& filename)
|
||||||
{
|
{
|
||||||
// avoid importing the same file
|
// avoid importing the same file
|
||||||
for(auto& fname:filename_table)
|
for(auto& fname:filename_table)
|
||||||
|
@ -75,7 +75,7 @@ nasal_ast nasal_import::file_import(nasal_ast& node)
|
||||||
nasal_ast tmp(0,ast_root);
|
nasal_ast tmp(0,ast_root);
|
||||||
|
|
||||||
// get filename and set node to ast_null
|
// get filename and set node to ast_null
|
||||||
std::string filename=node.get_children()[1].get_children()[0].get_str();
|
std::string& filename=node.get_children()[1].get_children()[0].get_str();
|
||||||
node.clear();
|
node.clear();
|
||||||
|
|
||||||
// avoid infinite loading loop
|
// avoid infinite loading loop
|
||||||
|
@ -131,14 +131,4 @@ void nasal_import::link(nasal_ast& root)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_ast& nasal_import::get_root()
|
|
||||||
{
|
|
||||||
return import_ast;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nasal_import::get_error()
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -103,20 +103,20 @@ private:
|
||||||
std::string line_code;
|
std::string line_code;
|
||||||
std::vector<char> res;
|
std::vector<char> res;
|
||||||
std::vector<token> token_list;
|
std::vector<token> token_list;
|
||||||
int get_tok_type(std::string);
|
int get_tok_type(std::string&);
|
||||||
void die(std::string,std::string,int,int);
|
void die(std::string,int);
|
||||||
std::string id_gen();
|
std::string id_gen();
|
||||||
std::string num_gen();
|
std::string num_gen();
|
||||||
std::string str_gen();
|
std::string str_gen();
|
||||||
public:
|
public:
|
||||||
void openfile(std::string);
|
void openfile(std::string&);
|
||||||
void scanner();
|
void scanner();
|
||||||
void print_token();
|
void print_token();
|
||||||
int get_error();
|
int get_error(){return error;}
|
||||||
std::vector<token>& get_token_list();
|
std::vector<token>& get_token_list(){return token_list;}
|
||||||
};
|
};
|
||||||
|
|
||||||
void nasal_lexer::openfile(std::string filename)
|
void nasal_lexer::openfile(std::string& filename)
|
||||||
{
|
{
|
||||||
error=0;
|
error=0;
|
||||||
res.clear();
|
res.clear();
|
||||||
|
@ -126,7 +126,6 @@ void nasal_lexer::openfile(std::string filename)
|
||||||
++error;
|
++error;
|
||||||
std::cout<<">> [lexer] cannot open file \""<<filename<<"\".\n";
|
std::cout<<">> [lexer] cannot open file \""<<filename<<"\".\n";
|
||||||
fin.close();
|
fin.close();
|
||||||
res_size=0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while(!fin.eof())
|
while(!fin.eof())
|
||||||
|
@ -137,11 +136,10 @@ void nasal_lexer::openfile(std::string filename)
|
||||||
res.push_back(c);
|
res.push_back(c);
|
||||||
}
|
}
|
||||||
fin.close();
|
fin.close();
|
||||||
res_size=res.size();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nasal_lexer::get_tok_type(std::string tk_str)
|
int nasal_lexer::get_tok_type(std::string& tk_str)
|
||||||
{
|
{
|
||||||
for(int i=0;token_table[i].str;++i)
|
for(int i=0;token_table[i].str;++i)
|
||||||
if(tk_str==token_table[i].str)
|
if(tk_str==token_table[i].str)
|
||||||
|
@ -149,12 +147,12 @@ int nasal_lexer::get_tok_type(std::string tk_str)
|
||||||
return tok_null;
|
return tok_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_lexer::die(std::string code,std::string error_info,int line=-1,int column=-1)
|
void nasal_lexer::die(std::string error_info,int line)
|
||||||
{
|
{
|
||||||
++error;
|
++error;
|
||||||
std::cout<<">> [lexer] line "<<line<<" column "<<column<<": \n"<<code<<"\n";
|
std::cout<<">> [lexer] line "<<line<<" column "<<line_code.length()<<": \n"<<line_code<<"\n";
|
||||||
for(int i=0;i<column-1;++i)
|
for(auto i:line_code)
|
||||||
std::cout<<(code[i]=='\t'?'\t':' ');
|
std::cout<<(i=='\t'?'\t':' ');
|
||||||
std::cout<<"^ "<<error_info<<'\n';
|
std::cout<<"^ "<<error_info<<'\n';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +181,7 @@ std::string nasal_lexer::num_gen()
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
if(token_str=="0x")
|
if(token_str=="0x")
|
||||||
{
|
{
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
return token_str;
|
return token_str;
|
||||||
|
@ -198,7 +196,7 @@ std::string nasal_lexer::num_gen()
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
if(token_str=="0o")
|
if(token_str=="0o")
|
||||||
{
|
{
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
return token_str;
|
return token_str;
|
||||||
|
@ -214,7 +212,7 @@ std::string nasal_lexer::num_gen()
|
||||||
if(ptr>=res_size)
|
if(ptr>=res_size)
|
||||||
{
|
{
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||||
|
@ -223,7 +221,7 @@ std::string nasal_lexer::num_gen()
|
||||||
if(token_str.back()=='.')
|
if(token_str.back()=='.')
|
||||||
{
|
{
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,7 +232,7 @@ std::string nasal_lexer::num_gen()
|
||||||
if(ptr>=res_size)
|
if(ptr>=res_size)
|
||||||
{
|
{
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
if(ptr<res_size && (res[ptr]=='-' || res[ptr]=='+'))
|
||||||
|
@ -242,7 +240,7 @@ std::string nasal_lexer::num_gen()
|
||||||
if(ptr>=res_size)
|
if(ptr>=res_size)
|
||||||
{
|
{
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
while(ptr<res_size && IS_DIGIT(res[ptr]))
|
||||||
|
@ -251,7 +249,7 @@ std::string nasal_lexer::num_gen()
|
||||||
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
|
if(token_str.back()=='e' || token_str.back()=='E' || token_str.back()=='-' || token_str.back()=='+')
|
||||||
{
|
{
|
||||||
line_code+=token_str;
|
line_code+=token_str;
|
||||||
die(line_code,"incorrect number.",line,line_code.length());
|
die("incorrect number.",line);
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,15 +275,15 @@ std::string nasal_lexer::str_gen()
|
||||||
line_code+=res[++ptr];
|
line_code+=res[++ptr];
|
||||||
switch(res[ptr])
|
switch(res[ptr])
|
||||||
{
|
{
|
||||||
case 'a':token_str.push_back('\a');break;
|
case 'a': token_str.push_back('\a');break;
|
||||||
case 'b':token_str.push_back('\b');break;
|
case 'b': token_str.push_back('\b');break;
|
||||||
case 'f':token_str.push_back('\f');break;
|
case 'f': token_str.push_back('\f');break;
|
||||||
case 'n':token_str.push_back('\n');break;
|
case 'n': token_str.push_back('\n');break;
|
||||||
case 'r':token_str.push_back('\r');break;
|
case 'r': token_str.push_back('\r');break;
|
||||||
case 't':token_str.push_back('\t');break;
|
case 't': token_str.push_back('\t');break;
|
||||||
case 'v':token_str.push_back('\v');break;
|
case 'v': token_str.push_back('\v');break;
|
||||||
case '?':token_str.push_back('\?');break;
|
case '?': token_str.push_back('\?');break;
|
||||||
case '0':token_str.push_back('\0');break;
|
case '0': token_str.push_back('\0');break;
|
||||||
case '\\':token_str.push_back('\\');break;
|
case '\\':token_str.push_back('\\');break;
|
||||||
case '\'':token_str.push_back('\'');break;
|
case '\'':token_str.push_back('\'');break;
|
||||||
case '\"':token_str.push_back('\"');break;
|
case '\"':token_str.push_back('\"');break;
|
||||||
|
@ -297,9 +295,9 @@ std::string nasal_lexer::str_gen()
|
||||||
}
|
}
|
||||||
// check if this string ends with a " or '
|
// check if this string ends with a " or '
|
||||||
if(ptr++>=res_size)
|
if(ptr++>=res_size)
|
||||||
die(line_code,"get EOF when generating string.",line,line_code.length());
|
die("get EOF when generating string.",line);
|
||||||
if(str_begin=='`' && token_str.length()>1)
|
if(str_begin=='`' && token_str.length()>1)
|
||||||
die(line_code,"\'`\' is used for string that includes one character.",line,line_code.length());
|
die("\'`\' is used for string that includes one character.",line);
|
||||||
return token_str;
|
return token_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +307,7 @@ void nasal_lexer::scanner()
|
||||||
line=1;
|
line=1;
|
||||||
ptr=0;
|
ptr=0;
|
||||||
line_code="";
|
line_code="";
|
||||||
|
res_size=res.size();
|
||||||
|
|
||||||
std::string token_str;
|
std::string token_str;
|
||||||
while(ptr<res_size)
|
while(ptr<res_size)
|
||||||
|
@ -351,7 +350,7 @@ void nasal_lexer::scanner()
|
||||||
line_code+=res[ptr];
|
line_code+=res[ptr];
|
||||||
token new_token(line,get_tok_type(token_str),token_str);
|
token new_token(line,get_tok_type(token_str),token_str);
|
||||||
if(!new_token.type)
|
if(!new_token.type)
|
||||||
die(line_code,"incorrect operator.",line,line_code.length());
|
die("incorrect operator.",line);
|
||||||
token_list.push_back(new_token);
|
token_list.push_back(new_token);
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
@ -386,7 +385,7 @@ void nasal_lexer::scanner()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
line_code+=res[ptr++];
|
line_code+=res[ptr++];
|
||||||
die(line_code,"unknown character.",line,line_code.length());
|
die("unknown character.",line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
token tk(line,tok_eof,"");
|
token tk(line,tok_eof,"");
|
||||||
|
@ -397,19 +396,9 @@ void nasal_lexer::scanner()
|
||||||
|
|
||||||
void nasal_lexer::print_token()
|
void nasal_lexer::print_token()
|
||||||
{
|
{
|
||||||
int size=token_list.size();
|
for(auto tok:token_list)
|
||||||
for(int i=0;i<size;++i)
|
std::cout<<"("<<tok.line<<" | "<<tok.str<<")\n";
|
||||||
std::cout<<"("<<token_list[i].line<<" | "<<token_list[i].str<<")\n";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nasal_lexer::get_error()
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<token>& nasal_lexer::get_token_list()
|
|
||||||
{
|
|
||||||
return token_list;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
|
@ -99,20 +99,11 @@ private:
|
||||||
nasal_ast break_expr();
|
nasal_ast break_expr();
|
||||||
nasal_ast ret_expr();
|
nasal_ast ret_expr();
|
||||||
public:
|
public:
|
||||||
int get_error();
|
int get_error(){return error;}
|
||||||
void set_toklist(std::vector<token>&);
|
void set_toklist(std::vector<token>& toks){tok_list=toks;}
|
||||||
void main_process();
|
void main_process();
|
||||||
nasal_ast& get_root();
|
nasal_ast& get_root(){return root;}
|
||||||
};
|
};
|
||||||
int nasal_parse::get_error()
|
|
||||||
{
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
void nasal_parse::set_toklist(std::vector<token>& toks)
|
|
||||||
{
|
|
||||||
tok_list=toks;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void nasal_parse::main_process()
|
void nasal_parse::main_process()
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
@ -147,10 +138,6 @@ void nasal_parse::main_process()
|
||||||
<<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n";
|
<<"please check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nasal_ast& nasal_parse::get_root()
|
|
||||||
{
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
void nasal_parse::reset()
|
void nasal_parse::reset()
|
||||||
{
|
{
|
||||||
ptr=in_function=in_loop=error=0;
|
ptr=in_function=in_loop=error=0;
|
||||||
|
@ -237,7 +224,7 @@ bool nasal_parse::check_function_end(nasal_ast& node)
|
||||||
if(
|
if(
|
||||||
node.get_children().empty() ||
|
node.get_children().empty() ||
|
||||||
(
|
(
|
||||||
type!=ast_definition &&
|
type!=ast_def &&
|
||||||
type!=ast_equal &&
|
type!=ast_equal &&
|
||||||
type!=ast_addeq &&
|
type!=ast_addeq &&
|
||||||
type!=ast_subeq &&
|
type!=ast_subeq &&
|
||||||
|
@ -695,7 +682,7 @@ nasal_ast nasal_parse::scalar()
|
||||||
else if(tok_list[ptr].type==tok_var)
|
else if(tok_list[ptr].type==tok_var)
|
||||||
{
|
{
|
||||||
match(tok_var);
|
match(tok_var);
|
||||||
node.set_type(ast_definition);
|
node.set_type(ast_def);
|
||||||
node.add_child(id_gen());
|
node.add_child(id_gen());
|
||||||
match(tok_id);
|
match(tok_id);
|
||||||
match(tok_eq);
|
match(tok_eq);
|
||||||
|
@ -795,7 +782,7 @@ nasal_ast nasal_parse::subvec()
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::definition()
|
nasal_ast nasal_parse::definition()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_definition);
|
nasal_ast node(tok_list[ptr].line,ast_def);
|
||||||
if(tok_list[ptr].type==tok_var)
|
if(tok_list[ptr].type==tok_var)
|
||||||
{
|
{
|
||||||
match(tok_var);
|
match(tok_var);
|
||||||
|
@ -1058,7 +1045,7 @@ nasal_ast nasal_parse::break_expr()
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::ret_expr()
|
nasal_ast nasal_parse::ret_expr()
|
||||||
{
|
{
|
||||||
nasal_ast node(tok_list[ptr].line,ast_return);
|
nasal_ast node(tok_list[ptr].line,ast_ret);
|
||||||
match(tok_ret);
|
match(tok_ret);
|
||||||
int type=tok_list[ptr].type;
|
int type=tok_list[ptr].type;
|
||||||
if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func ||
|
if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func ||
|
||||||
|
|
74
nasal_vm.h
74
nasal_vm.h
|
@ -82,7 +82,7 @@ private:
|
||||||
void opr_mcallh();
|
void opr_mcallh();
|
||||||
void opr_ret();
|
void opr_ret();
|
||||||
public:
|
public:
|
||||||
nasal_vm();
|
nasal_vm():stack_top(gc.stack_top){};
|
||||||
void init(
|
void init(
|
||||||
std::vector<std::string>&,
|
std::vector<std::string>&,
|
||||||
std::vector<double>&,
|
std::vector<double>&,
|
||||||
|
@ -91,11 +91,6 @@ public:
|
||||||
void run();
|
void run();
|
||||||
};
|
};
|
||||||
|
|
||||||
nasal_vm::nasal_vm():stack_top(gc.stack_top)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nasal_vm::init(
|
void nasal_vm::init(
|
||||||
std::vector<std::string>& strs,
|
std::vector<std::string>& strs,
|
||||||
std::vector<double>& nums,
|
std::vector<double>& nums,
|
||||||
|
@ -123,7 +118,7 @@ void nasal_vm::clear()
|
||||||
}
|
}
|
||||||
void nasal_vm::die(std::string str)
|
void nasal_vm::die(std::string str)
|
||||||
{
|
{
|
||||||
printf(">> [vm] 0x%.8x: %s\n",pc,str.data());
|
printf(">> [vm] 0x%.8x: %s\n",pc,str.c_str());
|
||||||
loop_mark=false;
|
loop_mark=false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +132,7 @@ bool nasal_vm::condition(nasal_val* val_addr)
|
||||||
std::string& str=*val_addr->ptr.str;
|
std::string& str=*val_addr->ptr.str;
|
||||||
double number=str2num(str.c_str());
|
double number=str2num(str.c_str());
|
||||||
if(std::isnan(number))
|
if(std::isnan(number))
|
||||||
return !str.empty();
|
return str.empty();
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -262,20 +257,19 @@ void nasal_vm::opr_unot()
|
||||||
nasal_val* new_val=nullptr;
|
nasal_val* new_val=nullptr;
|
||||||
int type=val->type;
|
int type=val->type;
|
||||||
if(type==vm_nil)
|
if(type==vm_nil)
|
||||||
new_val=gc.one_addr;
|
*stack_top=gc.one_addr;
|
||||||
else if(type==vm_num)
|
else if(type==vm_num)
|
||||||
new_val=val->ptr.num?gc.zero_addr:gc.one_addr;
|
*stack_top=val->ptr.num?gc.zero_addr:gc.one_addr;
|
||||||
else if(type==vm_str)
|
else if(type==vm_str)
|
||||||
{
|
{
|
||||||
double number=str2num(val->ptr.str->c_str());
|
double number=str2num(val->ptr.str->c_str());
|
||||||
if(std::isnan(number))
|
if(std::isnan(number))
|
||||||
new_val=val->ptr.str->empty()?gc.one_addr:gc.zero_addr;
|
*stack_top=val->ptr.str->empty()?gc.one_addr:gc.zero_addr;
|
||||||
else
|
else
|
||||||
new_val=number?gc.zero_addr:gc.one_addr;
|
*stack_top=number?gc.zero_addr:gc.one_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
die("unot: incorrect value type");
|
die("unot: incorrect value type");
|
||||||
*stack_top=new_val;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_usub()
|
void nasal_vm::opr_usub()
|
||||||
|
@ -433,9 +427,7 @@ void nasal_vm::opr_less()
|
||||||
{
|
{
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
if(val1->type==vm_str && val2->type==vm_str)
|
||||||
int b_type=val2->type;
|
|
||||||
if(a_type==vm_str && b_type==vm_str)
|
|
||||||
*stack_top=(*val1->ptr.str<*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
*stack_top=(*val1->ptr.str<*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
||||||
else
|
else
|
||||||
*stack_top=(val1->to_number()<val2->to_number())?gc.one_addr:gc.zero_addr;
|
*stack_top=(val1->to_number()<val2->to_number())?gc.one_addr:gc.zero_addr;
|
||||||
|
@ -445,9 +437,7 @@ void nasal_vm::opr_leq()
|
||||||
{
|
{
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
if(val1->type==vm_str && val2->type==vm_str)
|
||||||
int b_type=val2->type;
|
|
||||||
if(a_type==vm_str && b_type==vm_str)
|
|
||||||
*stack_top=(*val1->ptr.str<=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
*stack_top=(*val1->ptr.str<=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
||||||
else
|
else
|
||||||
*stack_top=(val1->to_number()<=val2->to_number())?gc.one_addr:gc.zero_addr;
|
*stack_top=(val1->to_number()<=val2->to_number())?gc.one_addr:gc.zero_addr;
|
||||||
|
@ -457,9 +447,7 @@ void nasal_vm::opr_grt()
|
||||||
{
|
{
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
if(val1->type==vm_str && val2->type==vm_str)
|
||||||
int b_type=val2->type;
|
|
||||||
if(a_type==vm_str && b_type==vm_str)
|
|
||||||
*stack_top=(*val1->ptr.str>*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
*stack_top=(*val1->ptr.str>*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
||||||
else
|
else
|
||||||
*stack_top=(val1->to_number()>val2->to_number())?gc.one_addr:gc.zero_addr;
|
*stack_top=(val1->to_number()>val2->to_number())?gc.one_addr:gc.zero_addr;
|
||||||
|
@ -469,9 +457,7 @@ void nasal_vm::opr_geq()
|
||||||
{
|
{
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
if(val1->type==vm_str && val2->type==vm_str)
|
||||||
int b_type=val2->type;
|
|
||||||
if(a_type==vm_str && b_type==vm_str)
|
|
||||||
*stack_top=(*val1->ptr.str>=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
*stack_top=(*val1->ptr.str>=*val2->ptr.str)?gc.one_addr:gc.zero_addr;
|
||||||
else
|
else
|
||||||
*stack_top=(val1->to_number()>=val2->to_number())?gc.one_addr:gc.zero_addr;
|
*stack_top=(val1->to_number()>=val2->to_number())?gc.one_addr:gc.zero_addr;
|
||||||
|
@ -502,12 +488,9 @@ void nasal_vm::opr_jf()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_counter()
|
void nasal_vm::opr_counter()
|
||||||
{
|
{
|
||||||
if((*stack_top)->type!=vm_vec)
|
|
||||||
{
|
|
||||||
die("cnt: must use vector in forindex/foreach");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
counter.push(-1);
|
counter.push(-1);
|
||||||
|
if((*stack_top)->type!=vm_vec)
|
||||||
|
die("cnt: must use vector in forindex/foreach");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_cntpop()
|
void nasal_vm::opr_cntpop()
|
||||||
|
@ -556,15 +539,10 @@ void nasal_vm::opr_callv()
|
||||||
int type=vec_addr->type;
|
int type=vec_addr->type;
|
||||||
if(type==vm_vec)
|
if(type==vm_vec)
|
||||||
{
|
{
|
||||||
int num=val->to_number();
|
nasal_val* res=vec_addr->ptr.vec->get_val(val->to_number());
|
||||||
nasal_val* res=vec_addr->ptr.vec->get_val(num);
|
if(!res)
|
||||||
if(res)
|
|
||||||
*stack_top=res;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
die("callv: index out of range");
|
die("callv: index out of range");
|
||||||
return;
|
*stack_top=res;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(type==vm_hash)
|
else if(type==vm_hash)
|
||||||
{
|
{
|
||||||
|
@ -612,10 +590,7 @@ void nasal_vm::opr_callvi()
|
||||||
// cannot use operator[],because this may cause overflow
|
// cannot use operator[],because this may cause overflow
|
||||||
nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num);
|
nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num);
|
||||||
if(!res)
|
if(!res)
|
||||||
{
|
|
||||||
die("callvi: index out of range");
|
die("callvi: index out of range");
|
||||||
return;
|
|
||||||
}
|
|
||||||
*(++stack_top)=res;
|
*(++stack_top)=res;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -646,7 +621,7 @@ void nasal_vm::opr_callfv()
|
||||||
nasal_val* func_addr=*(vec-1);
|
nasal_val* func_addr=*(vec-1);
|
||||||
if(func_addr->type!=vm_func)
|
if(func_addr->type!=vm_func)
|
||||||
{
|
{
|
||||||
die("callfv: called a value that is not a function");
|
die("callfv: must call a function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// push new local scope
|
// push new local scope
|
||||||
|
@ -690,7 +665,7 @@ void nasal_vm::opr_callfh()
|
||||||
nasal_val* func_addr=*(stack_top-1);
|
nasal_val* func_addr=*(stack_top-1);
|
||||||
if(func_addr->type!=vm_func)
|
if(func_addr->type!=vm_func)
|
||||||
{
|
{
|
||||||
die("callfh: called a value that is not a function");
|
die("callfh: must call a function");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// push new local scope
|
// push new local scope
|
||||||
|
@ -756,10 +731,9 @@ void nasal_vm::opr_slc()
|
||||||
default:die("slc: error value type");break;
|
default:die("slc: error value type");break;
|
||||||
}
|
}
|
||||||
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
|
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
|
||||||
if(res)
|
if(!res)
|
||||||
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
|
|
||||||
else
|
|
||||||
die("slc: index out of range");
|
die("slc: index out of range");
|
||||||
|
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_slc2()
|
void nasal_vm::opr_slc2()
|
||||||
|
@ -824,10 +798,7 @@ void nasal_vm::opr_mcallv()
|
||||||
}
|
}
|
||||||
nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);
|
nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num);
|
||||||
if(!res)
|
if(!res)
|
||||||
{
|
|
||||||
die("mcallv: index out of range");
|
die("mcallv: index out of range");
|
||||||
return;
|
|
||||||
}
|
|
||||||
addr_stack.push(res);
|
addr_stack.push(res);
|
||||||
}
|
}
|
||||||
else if(type==vm_hash)
|
else if(type==vm_hash)
|
||||||
|
@ -848,10 +819,7 @@ void nasal_vm::opr_mcallv()
|
||||||
addr_stack.push(res);
|
addr_stack.push(res);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
die("mcallv: cannot get memory space in a string");
|
die("mcallv: cannot get memory space in a string");
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_mcallh()
|
void nasal_vm::opr_mcallh()
|
||||||
|
@ -957,6 +925,8 @@ void nasal_vm::run()
|
||||||
for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc)
|
for(pc=0;loop_mark&&!gc.val_stack[STACK_MAX_DEPTH-1];++pc)
|
||||||
(this->*opr_table[exec_code[pc].op])();
|
(this->*opr_table[exec_code[pc].op])();
|
||||||
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC;
|
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC;
|
||||||
|
if(gc.val_stack[STACK_MAX_DEPTH-1])
|
||||||
|
die("stack overflow");
|
||||||
std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
|
std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue