🐛 fix ast print bug & delete some macros
This commit is contained in:
parent
0c216e5f16
commit
aaccfbda11
9
main.cpp
9
main.cpp
|
@ -90,12 +90,11 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
|
|||
vm ctx;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(file);
|
||||
|
||||
lex.scan(file).chkerr();
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lex);
|
||||
parse.compile(lex).chkerr();
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
ld.link(parse,file,cmd&VM_DETAIL);
|
||||
ld.link(parse,file,cmd&VM_DETAIL).chkerr();
|
||||
// optimizer does simple optimization on ast
|
||||
if(cmd&VM_OPT)
|
||||
optimize(parse.tree());
|
||||
|
@ -103,7 +102,7 @@ void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
|
|||
parse.print();
|
||||
|
||||
// code generator gets parser's ast and linker's import file list to generate code
|
||||
gen.compile(parse,ld);
|
||||
gen.compile(parse,ld).chkerr();
|
||||
if(cmd&VM_CODE)
|
||||
gen.print();
|
||||
|
||||
|
|
28
nasal_ast.h
28
nasal_ast.h
|
@ -67,20 +67,20 @@ enum ast_node:u32
|
|||
|
||||
const char* ast_name[]=
|
||||
{
|
||||
"null", "root", "block", "file",
|
||||
"nil", "num", "str", "id",
|
||||
"func", "hash", "vec", "pair",
|
||||
"call", "callh", "callv", "callf",
|
||||
"subvec", "args", "default", "dynamic",
|
||||
"and", "or", "=", "+=",
|
||||
"-=", "*=", "/=" "~=",
|
||||
"==", "!=", "<", "<=",
|
||||
">", ">=", "+", "-",
|
||||
"*", "/", "~", "neg",
|
||||
"!", "trino", "for", "forindex",
|
||||
"foreach", "while", "iter", "cond",
|
||||
"if", "elsif", "else", "multi-id",
|
||||
"tuple", "def", "multi-assign", "continue",
|
||||
"null", "root", "block", "file",
|
||||
"nil", "num", "str", "id",
|
||||
"func", "hash", "vec", "pair",
|
||||
"call", "callh", "callv", "callf",
|
||||
"subvec", "args", "default", "dynamic",
|
||||
"and", "or", "=", "+=",
|
||||
"-=", "*=", "/=", "~=",
|
||||
"==", "!=", "<", "<=",
|
||||
">", ">=", "+", "-",
|
||||
"*", "/", "~", "neg",
|
||||
"!", "trino", "for", "forindex",
|
||||
"foreach", "while", "iter", "cond",
|
||||
"if", "elsif", "else", "ltuple",
|
||||
"tuple", "def", "massign", "continue",
|
||||
"break", "return"
|
||||
};
|
||||
|
||||
|
|
|
@ -98,10 +98,10 @@ var builtin_fin(var* local,gc& ngc)
|
|||
var val=local[1];
|
||||
if(val.type!=vm_str)
|
||||
return nas_err("io::fin","\"filename\" must be string");
|
||||
std::ifstream fin(val.str(),std::ios::binary);
|
||||
std::ifstream in(val.str(),std::ios::binary);
|
||||
std::stringstream rd;
|
||||
if(!fin.fail())
|
||||
rd<<fin.rdbuf();
|
||||
if(!in.fail())
|
||||
rd<<in.rdbuf();
|
||||
return ngc.newstr(rd.str());
|
||||
}
|
||||
var builtin_fout(var* local,gc& ngc)
|
||||
|
@ -110,10 +110,10 @@ var builtin_fout(var* local,gc& ngc)
|
|||
var str=local[2];
|
||||
if(val.type!=vm_str)
|
||||
return nas_err("io::fout","\"filename\" must be string");
|
||||
std::ofstream fout(val.str());
|
||||
if(fout.fail())
|
||||
std::ofstream out(val.str());
|
||||
if(out.fail())
|
||||
return nas_err("io::fout","cannot open <"+val.str()+">");
|
||||
fout<<str;
|
||||
out<<str;
|
||||
return nil;
|
||||
}
|
||||
var builtin_split(var* local,gc& ngc)
|
||||
|
@ -330,17 +330,15 @@ var builtin_time(var* local,gc& ngc)
|
|||
{
|
||||
var val=local[1];
|
||||
if(val.type!=vm_num)
|
||||
return nas_err("time","\"begin_time\" must be number");
|
||||
time_t begin_time=(time_t)val.num();
|
||||
return {vm_num,(f64)time(&begin_time)};
|
||||
return nas_err("time","\"begin\" must be number");
|
||||
time_t begin=(time_t)val.num();
|
||||
return {vm_num,(f64)time(&begin)};
|
||||
}
|
||||
var builtin_contains(var* local,gc& ngc)
|
||||
{
|
||||
var hash=local[1];
|
||||
var key=local[2];
|
||||
if(hash.type!=vm_hash)
|
||||
return nas_err("contains","\"hash\" must be hash");
|
||||
if(key.type!=vm_str)
|
||||
if(hash.type!=vm_hash || key.type!=vm_str)
|
||||
return zero;
|
||||
return hash.hash().elems.count(key.str())?one:zero;
|
||||
}
|
||||
|
@ -734,7 +732,7 @@ var builtin_pipe(var* local,gc& ngc)
|
|||
res.vec().elems.push_back({vm_num,(f64)fd[1]});
|
||||
return res;
|
||||
#endif
|
||||
return nas_err("pipe","not supported for windows");
|
||||
return nas_err("pipe","not supported");
|
||||
}
|
||||
var builtin_fork(var* local,gc& ngc)
|
||||
{
|
||||
|
@ -744,7 +742,7 @@ var builtin_fork(var* local,gc& ngc)
|
|||
return nas_err("fork","failed to fork a process");
|
||||
return {vm_num,(f64)res};
|
||||
#endif
|
||||
return nas_err("fork","not supported for windows");
|
||||
return nas_err("fork","not supported");
|
||||
}
|
||||
var builtin_waitpid(var* local,gc& ngc)
|
||||
{
|
||||
|
@ -760,7 +758,7 @@ var builtin_waitpid(var* local,gc& ngc)
|
|||
vec.vec().elems.push_back({vm_num,(f64)status});
|
||||
return vec;
|
||||
#endif
|
||||
return nas_err("waitpid","not supported for windows");
|
||||
return nas_err("waitpid","not supported");
|
||||
}
|
||||
void obj_dir_dtor(void* ptr)
|
||||
{
|
||||
|
@ -1032,18 +1030,18 @@ var builtin_md5(var* local,gc& ngc)
|
|||
|
||||
var builtin_cocreate(var* local,gc& ngc)
|
||||
{
|
||||
// +-----------------+
|
||||
// | old pc | <- top[0]
|
||||
// +-----------------+
|
||||
// | old localr | <- top[-1]
|
||||
// +-----------------+
|
||||
// | old upvalr | <- top[-2]
|
||||
// +-----------------+
|
||||
// | local scope |
|
||||
// | ... |
|
||||
// +-----------------+ <- local pointer stored in localr
|
||||
// | old funcr | <- old function stored in funcr
|
||||
// +-----------------+
|
||||
// +-------------+
|
||||
// | old pc | <- top[0]
|
||||
// +-------------+
|
||||
// | old localr | <- top[-1]
|
||||
// +-------------+
|
||||
// | old upvalr | <- top[-2]
|
||||
// +-------------+
|
||||
// | local scope |
|
||||
// | ... |
|
||||
// +-------------+ <- local pointer stored in localr
|
||||
// | old funcr | <- old function stored in funcr
|
||||
// +-------------+
|
||||
var func=local[1];
|
||||
if(func.type!=vm_func)
|
||||
return nas_err("coroutine::create","must use a function to create coroutine");
|
||||
|
@ -1124,7 +1122,15 @@ var builtin_logtime(var* local,gc& ngc)
|
|||
time_t t=time(nullptr);
|
||||
tm* tm_t=localtime(&t);
|
||||
char s[128];
|
||||
sprintf(s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",tm_t->tm_year+1900,tm_t->tm_mon+1,tm_t->tm_mday,tm_t->tm_hour,tm_t->tm_min,tm_t->tm_sec);
|
||||
sprintf(
|
||||
s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",
|
||||
tm_t->tm_year+1900,
|
||||
tm_t->tm_mon+1,
|
||||
tm_t->tm_mday,
|
||||
tm_t->tm_hour,
|
||||
tm_t->tm_min,
|
||||
tm_t->tm_sec
|
||||
);
|
||||
return ngc.newstr(s);
|
||||
}
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ private:
|
|||
void singleop(const u32);
|
||||
public:
|
||||
codegen(error& e):fileindex(0),err(e),file(nullptr){}
|
||||
void compile(const parse&,const linker&);
|
||||
const error& compile(const parse&,const linker&);
|
||||
void print();
|
||||
const std::vector<string>& strs() const {return str_res;}
|
||||
const std::vector<f64>& nums() const {return num_res;}
|
||||
|
@ -1235,7 +1235,7 @@ void codegen::ret_gen(const ast& node)
|
|||
gen(op_ret,0,node.line());
|
||||
}
|
||||
|
||||
void codegen::compile(const parse& parse,const linker& import)
|
||||
const error& codegen::compile(const parse& parse,const linker& import)
|
||||
{
|
||||
fileindex=0;
|
||||
file=import.filelist().data();
|
||||
|
@ -1248,7 +1248,7 @@ void codegen::compile(const parse& parse,const linker& import)
|
|||
die("too many global variants: "+std::to_string(global.size()),0,0);
|
||||
if(code.size()>0xffffffff)
|
||||
die("too large generated bytecode file: "+std::to_string(code.size()),0,0);
|
||||
err.chkerr();
|
||||
return err;
|
||||
}
|
||||
|
||||
void codegen::singleop(const u32 index)
|
||||
|
|
41
nasal_err.h
41
nasal_err.h
|
@ -71,7 +71,7 @@ std::ostream& reset(std::ostream& s)
|
|||
return s;
|
||||
}
|
||||
|
||||
class fstreamline
|
||||
class flstream
|
||||
{
|
||||
protected:
|
||||
string file;
|
||||
|
@ -100,7 +100,7 @@ public:
|
|||
usize size(){return res.size();}
|
||||
};
|
||||
|
||||
class error:public fstreamline
|
||||
class error:public flstream
|
||||
{
|
||||
private:
|
||||
u32 cnt;
|
||||
|
@ -115,26 +115,29 @@ public:
|
|||
void err(const string& stage,const string& info)
|
||||
{
|
||||
++cnt;
|
||||
std::cerr<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n\n";
|
||||
std::cerr
|
||||
<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n\n";
|
||||
}
|
||||
void err(const string& stage,u32 line,u32 col,const string& info)
|
||||
{
|
||||
++cnt;
|
||||
const string& code=res[line-1];
|
||||
const string iden=identation(std::to_string(line).length());
|
||||
std::cerr<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n"
|
||||
<<cyan<<" --> "<<reset
|
||||
<<orange<<file<<":"<<line<<":"<<col<<"\n";
|
||||
std::cerr
|
||||
<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n"
|
||||
<<cyan<<" --> "<<reset
|
||||
<<orange<<file<<":"<<line<<":"<<col<<"\n";
|
||||
if(!line)
|
||||
{
|
||||
std::cerr<<"\n";
|
||||
return;
|
||||
}
|
||||
std::cerr<<cyan<<iden<<" | "<<reset<<"\n"
|
||||
<<cyan<<line<<" | "<<reset<<code<<"\n"
|
||||
<<cyan<<iden<<" | "<<reset;
|
||||
std::cerr
|
||||
<<cyan<<iden<<" | "<<reset<<"\n"
|
||||
<<cyan<<line<<" | "<<reset<<code<<"\n"
|
||||
<<cyan<<iden<<" | "<<reset;
|
||||
for(i32 i=0;i<(i32)col-1;++i)
|
||||
std::cerr<<char(" \t"[code[i]=='\t']);
|
||||
std::cerr<<red<<"^ "<<info<<reset<<"\n\n";
|
||||
|
@ -143,18 +146,20 @@ public:
|
|||
{
|
||||
++cnt;
|
||||
const string iden=identation(std::to_string(line).length());
|
||||
std::cerr<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n"
|
||||
<<cyan<<" --> "<<reset
|
||||
<<orange<<file<<":"<<line<<"\n";
|
||||
std::cerr
|
||||
<<red<<stage<<": "
|
||||
<<white<<info<<reset<<"\n"
|
||||
<<cyan<<" --> "<<reset
|
||||
<<orange<<file<<":"<<line<<"\n";
|
||||
if(!line)
|
||||
{
|
||||
std::cerr<<"\n";
|
||||
return;
|
||||
}
|
||||
std::cerr<<cyan<<iden<<" | "<<reset<<"\n"
|
||||
<<cyan<<line<<" | "<<reset<<res[line-1]<<"\n"
|
||||
<<cyan<<iden<<" | "<<reset<<"\n\n";
|
||||
std::cerr
|
||||
<<cyan<<iden<<" | "<<reset<<"\n"
|
||||
<<cyan<<line<<" | "<<reset<<res[line-1]<<"\n"
|
||||
<<cyan<<iden<<" | "<<reset<<"\n\n";
|
||||
}
|
||||
void chkerr() const {if(cnt)std::exit(1);}
|
||||
};
|
||||
|
|
12
nasal_gc.h
12
nasal_gc.h
|
@ -108,9 +108,9 @@ struct nas_vec
|
|||
|
||||
nas_vec():printed(false){}
|
||||
friend std::ostream& operator<<(std::ostream&,nas_vec&);
|
||||
usize size(){return elems.size();}
|
||||
var get_val(const i32);
|
||||
var* get_mem(const i32);
|
||||
usize size(){return elems.size();}
|
||||
var get_val(const i32);
|
||||
var* get_mem(const i32);
|
||||
};
|
||||
|
||||
struct nas_hash
|
||||
|
@ -120,9 +120,9 @@ struct nas_hash
|
|||
|
||||
nas_hash():printed(false){}
|
||||
friend std::ostream& operator<<(std::ostream&,nas_hash&);
|
||||
usize size(){return elems.size();}
|
||||
var get_val(const string&);
|
||||
var* get_mem(const string&);
|
||||
usize size(){return elems.size();}
|
||||
var get_val(const string&);
|
||||
var* get_mem(const string&);
|
||||
};
|
||||
|
||||
struct nas_func
|
||||
|
|
|
@ -30,7 +30,7 @@ private:
|
|||
ast load(ast&,u16);
|
||||
public:
|
||||
linker(error&);
|
||||
void link(parse&,const string&,bool);
|
||||
const error& link(parse&,const string&,bool);
|
||||
const std::vector<string>& filelist() const {return files;}
|
||||
};
|
||||
|
||||
|
@ -213,7 +213,7 @@ ast linker::load(ast& root,u16 fileindex)
|
|||
return tree;
|
||||
}
|
||||
|
||||
void linker::link(parse& parse,const string& self,bool spath=false)
|
||||
const error& linker::link(parse& parse,const string& self,bool spath=false)
|
||||
{
|
||||
show_path=spath;
|
||||
// initializing
|
||||
|
@ -221,5 +221,5 @@ void linker::link(parse& parse,const string& self,bool spath=false)
|
|||
// scan root and import files,then generate a new ast and return to import_ast
|
||||
// the main file's index is 0
|
||||
parse.tree()=load(parse.tree(),0);
|
||||
err.chkerr();
|
||||
return err;
|
||||
}
|
||||
|
|
150
nasal_lexer.h
150
nasal_lexer.h
|
@ -67,12 +67,8 @@ struct token
|
|||
u32 col;
|
||||
u32 type;
|
||||
string str;
|
||||
token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s=""):str(s)
|
||||
{
|
||||
line=l;
|
||||
col=c;
|
||||
type=t;
|
||||
}
|
||||
token(u32 l=0,u32 c=0,u32 t=tok_null,const string& s="")
|
||||
:line(l),col(c),type(t),str(s){}
|
||||
};
|
||||
|
||||
class lexer
|
||||
|
@ -85,54 +81,55 @@ private:
|
|||
error& err;
|
||||
std::vector<token> toks;
|
||||
std::unordered_map<string,u32> typetbl {
|
||||
{"for" ,tok_for },
|
||||
{"forindex",tok_forindex },
|
||||
{"foreach" ,tok_foreach },
|
||||
{"while" ,tok_while },
|
||||
{"var" ,tok_var },
|
||||
{"func" ,tok_func },
|
||||
{"break" ,tok_break },
|
||||
{"continue",tok_continue },
|
||||
{"return" ,tok_ret },
|
||||
{"if" ,tok_if },
|
||||
{"elsif" ,tok_elsif },
|
||||
{"else" ,tok_else },
|
||||
{"nil" ,tok_nil },
|
||||
{"(" ,tok_lcurve },
|
||||
{")" ,tok_rcurve },
|
||||
{"[" ,tok_lbracket },
|
||||
{"]" ,tok_rbracket },
|
||||
{"{" ,tok_lbrace },
|
||||
{"}" ,tok_rbrace },
|
||||
{";" ,tok_semi },
|
||||
{"and" ,tok_and },
|
||||
{"or" ,tok_or },
|
||||
{"," ,tok_comma },
|
||||
{"." ,tok_dot },
|
||||
{"..." ,tok_ellipsis },
|
||||
{"?" ,tok_quesmark },
|
||||
{":" ,tok_colon },
|
||||
{"+" ,tok_add },
|
||||
{"-" ,tok_sub },
|
||||
{"*" ,tok_mult },
|
||||
{"/" ,tok_div },
|
||||
{"~" ,tok_link },
|
||||
{"!" ,tok_not },
|
||||
{"=" ,tok_eq },
|
||||
{"+=" ,tok_addeq },
|
||||
{"-=" ,tok_subeq },
|
||||
{"*=" ,tok_multeq },
|
||||
{"/=" ,tok_diveq },
|
||||
{"~=" ,tok_lnkeq },
|
||||
{"==" ,tok_cmpeq },
|
||||
{"!=" ,tok_neq },
|
||||
{"<" ,tok_less },
|
||||
{"<=" ,tok_leq },
|
||||
{">" ,tok_grt },
|
||||
{">=" ,tok_geq }
|
||||
{"for" ,tok_for },
|
||||
{"forindex",tok_forindex},
|
||||
{"foreach" ,tok_foreach },
|
||||
{"while" ,tok_while },
|
||||
{"var" ,tok_var },
|
||||
{"func" ,tok_func },
|
||||
{"break" ,tok_break },
|
||||
{"continue",tok_continue},
|
||||
{"return" ,tok_ret },
|
||||
{"if" ,tok_if },
|
||||
{"elsif" ,tok_elsif },
|
||||
{"else" ,tok_else },
|
||||
{"nil" ,tok_nil },
|
||||
{"(" ,tok_lcurve },
|
||||
{")" ,tok_rcurve },
|
||||
{"[" ,tok_lbracket},
|
||||
{"]" ,tok_rbracket},
|
||||
{"{" ,tok_lbrace },
|
||||
{"}" ,tok_rbrace },
|
||||
{";" ,tok_semi },
|
||||
{"and" ,tok_and },
|
||||
{"or" ,tok_or },
|
||||
{"," ,tok_comma },
|
||||
{"." ,tok_dot },
|
||||
{"..." ,tok_ellipsis},
|
||||
{"?" ,tok_quesmark},
|
||||
{":" ,tok_colon },
|
||||
{"+" ,tok_add },
|
||||
{"-" ,tok_sub },
|
||||
{"*" ,tok_mult },
|
||||
{"/" ,tok_div },
|
||||
{"~" ,tok_link },
|
||||
{"!" ,tok_not },
|
||||
{"=" ,tok_eq },
|
||||
{"+=" ,tok_addeq },
|
||||
{"-=" ,tok_subeq },
|
||||
{"*=" ,tok_multeq },
|
||||
{"/=" ,tok_diveq },
|
||||
{"~=" ,tok_lnkeq },
|
||||
{"==" ,tok_cmpeq },
|
||||
{"!=" ,tok_neq },
|
||||
{"<" ,tok_less },
|
||||
{"<=" ,tok_leq },
|
||||
{">" ,tok_grt },
|
||||
{">=" ,tok_geq }
|
||||
};
|
||||
|
||||
u32 get_type(const string&);
|
||||
bool skip(char);
|
||||
bool is_id(char);
|
||||
bool is_hex(char);
|
||||
bool is_oct(char);
|
||||
|
@ -140,22 +137,23 @@ private:
|
|||
bool is_str(char);
|
||||
bool is_single_opr(char);
|
||||
bool is_calc_opr(char);
|
||||
void die(const string& info){err.err("lexer",line,column,info);}
|
||||
void die(const string&);
|
||||
void open(const string&);
|
||||
string utf8_gen();
|
||||
string id_gen();
|
||||
string num_gen();
|
||||
string str_gen();
|
||||
public:
|
||||
lexer(error& e):
|
||||
line(1),column(0),
|
||||
ptr(0),res(""),
|
||||
err(e){}
|
||||
void scan(const string&);
|
||||
void print();
|
||||
lexer(error& e):line(1),column(0),ptr(0),res(""),err(e){}
|
||||
const error& scan(const string&);
|
||||
const std::vector<token>& result() const {return toks;}
|
||||
};
|
||||
|
||||
bool lexer::skip(char c)
|
||||
{
|
||||
return c==' '||c=='\n'||c=='\t'||c=='\r'||c==0;
|
||||
}
|
||||
|
||||
bool lexer::is_id(char c)
|
||||
{
|
||||
return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0);
|
||||
|
@ -194,7 +192,16 @@ bool lexer::is_single_opr(char c)
|
|||
|
||||
bool lexer::is_calc_opr(char c)
|
||||
{
|
||||
return c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~';
|
||||
return (
|
||||
c=='='||c=='+'||c=='-'||c=='*'||
|
||||
c=='!'||c=='/'||c=='<'||c=='>'||
|
||||
c=='~'
|
||||
);
|
||||
}
|
||||
|
||||
void lexer::die(const string& info)
|
||||
{
|
||||
err.err("lexer",line,column,info);
|
||||
}
|
||||
|
||||
void lexer::open(const string& file)
|
||||
|
@ -205,21 +212,19 @@ void lexer::open(const string& file)
|
|||
err.err("lexer","<"+file+"> is not a regular file");
|
||||
err.chkerr();
|
||||
}
|
||||
std::ifstream fin(file,std::ios::binary);
|
||||
if(fin.fail())
|
||||
std::ifstream in(file,std::ios::binary);
|
||||
if(in.fail())
|
||||
err.err("lexer","failed to open <"+file+">");
|
||||
else
|
||||
err.load(file);
|
||||
std::stringstream ss;
|
||||
ss<<fin.rdbuf();
|
||||
ss<<in.rdbuf();
|
||||
res=ss.str();
|
||||
}
|
||||
|
||||
u32 lexer::get_type(const string& str)
|
||||
{
|
||||
if(typetbl.count(str))
|
||||
return typetbl.at(str);
|
||||
return tok_null;
|
||||
return typetbl.count(str)?typetbl.at(str):tok_null;
|
||||
}
|
||||
|
||||
string lexer::utf8_gen()
|
||||
|
@ -241,7 +246,8 @@ string lexer::utf8_gen()
|
|||
string utf_info="0x"+chrhex(tmp[0]);
|
||||
for(u32 i=1;i<tmp.size();++i)
|
||||
utf_info+=" 0x"+chrhex(tmp[i]);
|
||||
die("invalid utf-8 character `"+utf_info+"`, make sure it is utf8-text file");
|
||||
die("invalid utf-8 <"+utf_info+">");
|
||||
err.err("lexer","fatal error occurred, stop");
|
||||
std::exit(1);
|
||||
}
|
||||
str+=tmp;
|
||||
|
@ -385,7 +391,7 @@ string lexer::str_gen()
|
|||
return str;
|
||||
}
|
||||
|
||||
void lexer::scan(const string& file)
|
||||
const error& lexer::scan(const string& file)
|
||||
{
|
||||
line=1;
|
||||
column=0;
|
||||
|
@ -395,7 +401,7 @@ void lexer::scan(const string& file)
|
|||
string str;
|
||||
while(ptr<res.size())
|
||||
{
|
||||
while(ptr<res.size() && (res[ptr]==' ' || res[ptr]=='\n' || res[ptr]=='\t' || res[ptr]=='\r' || res[ptr]==0))
|
||||
while(ptr<res.size() && skip(res[ptr]))
|
||||
{
|
||||
// these characters will be ignored, and '\n' will cause ++line
|
||||
++column;
|
||||
|
@ -461,11 +467,5 @@ void lexer::scan(const string& file)
|
|||
}
|
||||
toks.push_back({line,column,tok_eof,"<eof>"});
|
||||
res="";
|
||||
err.chkerr();
|
||||
}
|
||||
|
||||
void lexer::print()
|
||||
{
|
||||
for(auto& tok:toks)
|
||||
std::cout<<"("<<tok.line<<" | "<<rawstr(tok.str,32)<<")\n";
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
class parse
|
||||
{
|
||||
#define err_line (toks[ptr].line)
|
||||
#define is_call(type) ((type)==tok_lcurve || (type)==tok_lbracket || (type)==tok_dot)
|
||||
private:
|
||||
u32 ptr;
|
||||
u32 in_func; // count function block
|
||||
|
@ -97,10 +96,12 @@ private:
|
|||
};
|
||||
|
||||
void die(u32,string,bool);
|
||||
void next() {++ptr;};
|
||||
void match(u32 type,const char* info=nullptr);
|
||||
bool lookahead(u32 type);
|
||||
bool lookahead(u32);
|
||||
bool is_call(u32);
|
||||
bool check_comma(const u32*);
|
||||
bool check_multi_scalar();
|
||||
bool check_tuple();
|
||||
bool check_func_end(const ast&);
|
||||
bool check_special_call();
|
||||
bool need_semi_check(const ast&);
|
||||
|
@ -152,11 +153,11 @@ public:
|
|||
toks(nullptr),root(0,0,ast_root),
|
||||
err(e){}
|
||||
void print(){root.print_tree();}
|
||||
void compile(const lexer&);
|
||||
const error& compile(const lexer&);
|
||||
ast& tree(){return root;}
|
||||
const ast& tree() const {return root;}
|
||||
};
|
||||
void parse::compile(const lexer& lexer)
|
||||
const error& parse::compile(const lexer& lexer)
|
||||
{
|
||||
toks=lexer.result().data();
|
||||
ptr=in_func=in_loop=0;
|
||||
|
@ -171,7 +172,7 @@ void parse::compile(const lexer& lexer)
|
|||
else if(need_semi_check(root.child().back()) && !lookahead(tok_eof))
|
||||
die(err_line,"expected \";\"",true);
|
||||
}
|
||||
err.chkerr();
|
||||
return err;
|
||||
}
|
||||
void parse::die(u32 line,string info,bool report_prev=false)
|
||||
{
|
||||
|
@ -205,12 +206,16 @@ void parse::match(u32 type,const char* info)
|
|||
}
|
||||
if(lookahead(tok_eof))
|
||||
return;
|
||||
++ptr;
|
||||
next();
|
||||
}
|
||||
bool parse::lookahead(u32 type)
|
||||
{
|
||||
return toks[ptr].type==type;
|
||||
}
|
||||
bool parse::is_call(u32 type)
|
||||
{
|
||||
return type==tok_lcurve || type==tok_lbracket || type==tok_dot;
|
||||
}
|
||||
bool parse::check_comma(const u32* panic_set)
|
||||
{
|
||||
for(u32 i=0;panic_set[i];++i)
|
||||
|
@ -221,7 +226,7 @@ bool parse::check_comma(const u32* panic_set)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
bool parse::check_multi_scalar()
|
||||
bool parse::check_tuple()
|
||||
{
|
||||
u32 check_ptr=ptr,curve=1,bracket=0,brace=0;
|
||||
while(toks[++check_ptr].type!=tok_eof && curve)
|
||||
|
@ -486,7 +491,7 @@ ast parse::lcurve_expr()
|
|||
{
|
||||
if(toks[ptr+1].type==tok_var)
|
||||
return definition();
|
||||
return check_multi_scalar()?multi_assgin():calc();
|
||||
return check_tuple()?multi_assgin():calc();
|
||||
}
|
||||
ast parse::expr()
|
||||
{
|
||||
|
@ -519,7 +524,7 @@ ast parse::expr()
|
|||
case tok_semi: break;
|
||||
default:
|
||||
die(err_line,"incorrect token <"+toks[ptr].str+">");
|
||||
++ptr;
|
||||
next();
|
||||
break;
|
||||
}
|
||||
return {toks[ptr].line,toks[ptr].col,ast_null};
|
||||
|
@ -808,7 +813,7 @@ ast parse::definition()
|
|||
node.add(incurve_def());
|
||||
match(tok_eq);
|
||||
if(lookahead(tok_lcurve))
|
||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
||||
node.add(check_tuple()?multi_scalar(false):calc());
|
||||
else
|
||||
node.add(calc());
|
||||
if(node[0].type()==ast_id && node[1].type()==ast_tuple)
|
||||
|
@ -889,7 +894,7 @@ ast parse::multi_assgin()
|
|||
return node;
|
||||
}
|
||||
if(lookahead(tok_lcurve))
|
||||
node.add(check_multi_scalar()?multi_scalar(false):calc());
|
||||
node.add(check_tuple()?multi_scalar(false):calc());
|
||||
else
|
||||
node.add(calc());
|
||||
if(node[1].type()==ast_tuple
|
||||
|
|
22
nasal_vm.h
22
nasal_vm.h
|
@ -49,7 +49,7 @@ protected:
|
|||
void die(const string&);
|
||||
#define vm_error(info) {die(info);return;}
|
||||
/* vm calculation functions*/
|
||||
bool condition(var);
|
||||
bool cond(var&);
|
||||
/* vm operands */
|
||||
void o_intg();
|
||||
void o_intl();
|
||||
|
@ -232,8 +232,8 @@ void vm::stackinfo(const u32 limit=10)
|
|||
{
|
||||
/* bytecode[0].num is the global size */
|
||||
const u32 gsize=ngc.stack==stack?bytecode[0].num:0;
|
||||
var* t=top;
|
||||
var* bottom=ngc.stack+gsize;
|
||||
var* t=top;
|
||||
var* bottom=ngc.stack+gsize;
|
||||
std::cout<<"vm stack (0x"<<std::hex<<(u64)bottom<<std::dec
|
||||
<<" <sp+"<<gsize<<">, limit "<<limit<<", total "
|
||||
<<(t<bottom? 0:(i64)(t-bottom+1))<<")\n";
|
||||
|
@ -324,7 +324,7 @@ void vm::die(const string& str)
|
|||
top[0]=nil;
|
||||
}
|
||||
}
|
||||
inline bool vm::condition(var val)
|
||||
inline bool vm::cond(var& val)
|
||||
{
|
||||
if(val.type==vm_num)
|
||||
return val.num();
|
||||
|
@ -578,12 +578,12 @@ inline void vm::o_jmp()
|
|||
}
|
||||
inline void vm::o_jt()
|
||||
{
|
||||
if(condition(top[0]))
|
||||
if(cond(top[0]))
|
||||
pc=imm[pc]-1;
|
||||
}
|
||||
inline void vm::o_jf()
|
||||
{
|
||||
if(!condition(top[0]))
|
||||
if(!cond(top[0]))
|
||||
pc=imm[pc]-1;
|
||||
--top;
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ inline void vm::o_callv()
|
|||
{
|
||||
top[0]=vec.vec().get_val(val.tonum());
|
||||
if(top[0].type==vm_none)
|
||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||
}
|
||||
else if(vec.type==vm_hash)
|
||||
{
|
||||
|
@ -653,7 +653,7 @@ inline void vm::o_callv()
|
|||
i32 num=val.tonum();
|
||||
i32 len=str.length();
|
||||
if(num<-len || num>=len)
|
||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||
top[0]={vm_num,f64((u8)str[num>=0? num:num+len])};
|
||||
}
|
||||
else
|
||||
|
@ -667,7 +667,7 @@ inline void vm::o_callvi()
|
|||
// cannot use operator[],because this may cause overflow
|
||||
(++top)[0]=val.vec().get_val(imm[pc]);
|
||||
if(top[0].type==vm_none)
|
||||
vm_error("index out of range:"+std::to_string(imm[pc]));
|
||||
vm_error("out of range:"+std::to_string(imm[pc]));
|
||||
}
|
||||
inline void vm::o_callh()
|
||||
{
|
||||
|
@ -796,7 +796,7 @@ inline void vm::o_slc()
|
|||
var val=(top--)[0];
|
||||
var res=top[-1].vec().get_val(val.tonum());
|
||||
if(res.type==vm_none)
|
||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||
top[0].vec().elems.push_back(res);
|
||||
}
|
||||
inline void vm::o_slc2()
|
||||
|
@ -856,7 +856,7 @@ inline void vm::o_mcallv()
|
|||
{
|
||||
memr=vec.vec().get_mem(val.tonum());
|
||||
if(!memr)
|
||||
vm_error("index out of range:"+std::to_string(val.tonum()));
|
||||
vm_error("out of range:"+std::to_string(val.tonum()));
|
||||
}else if(vec.type==vm_hash) // do mcallh but use the mcallv way
|
||||
{
|
||||
if(val.type!=vm_str)
|
||||
|
|
|
@ -19,7 +19,7 @@ var prt=func(){
|
|||
}
|
||||
s~='+--------------------+\n';
|
||||
print(s);
|
||||
unix.sleep(1/144);
|
||||
unix.sleep(1/200);
|
||||
}
|
||||
|
||||
var bfs=func(begin,end){
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
# 2022/5/19
|
||||
import.stl.process_bar;
|
||||
|
||||
if(os.platform()=="windows"){
|
||||
system("chcp 65001");
|
||||
system("color");
|
||||
}
|
||||
|
||||
var fib=func(){
|
||||
var (a,b)=(1,1);
|
||||
coroutine.yield(a);
|
||||
|
@ -76,10 +81,6 @@ var total=1000; # ms
|
|||
var co=coroutine.create(productor);
|
||||
var tm=maketimestamp();
|
||||
|
||||
if(os.platform()=="windows"){
|
||||
system("chcp 65001");
|
||||
system("color");
|
||||
}
|
||||
var counter=0;
|
||||
var bar=process_bar.high_resolution_bar(40);
|
||||
var consumer=func(){
|
||||
|
|
|
@ -25,7 +25,7 @@ var prt=func()
|
|||
s~='\n';
|
||||
}
|
||||
print(s);
|
||||
unix.sleep(1/144);
|
||||
unix.sleep(1/160);
|
||||
}
|
||||
|
||||
func(){
|
||||
|
|
Loading…
Reference in New Issue