prepare to use new ast

This commit is contained in:
ValKmjolnir 2023-06-05 00:11:37 +08:00
parent afc8c54487
commit 9bf4eacc62
7 changed files with 250 additions and 72 deletions

View File

@ -4,7 +4,7 @@ on:
schedule:
- cron: "0 16 * * *"
push:
branches: [ master ]
branches: [ master,develop ]
pull_request:
branches: [ master ]
workflow_dispatch:

19
ast/nasal_new_ast.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "nasal_new_ast.h"
bool stmt::accept(ast_visitor* visitor) {
visitor->visit_stmt(this);
return true;
}
bool expr::accept(ast_visitor* visitor) {
visitor->visit_expr(this);
return true;
}
void ast_visitor::visit_stmt(stmt* node) {
node->accept(this);
}
void ast_visitor::visit_expr(expr* node) {
node->accept(this);
}

112
ast/nasal_new_ast.h Normal file
View File

@ -0,0 +1,112 @@
#pragma once
#include "nasal.h"
#include "nasal_err.h"
enum class ast_node_type:u32 {
ast_null=0, // null node
ast_stmt,
ast_expr,
ast_root, // mark the root node of ast
ast_block, // expression block
ast_file, // used to store which file the sub-tree is on, only used in main block
ast_nil, // nil keyword
ast_num, // number, basic value type
ast_str, // string, basic value type
ast_id, // identifier
ast_bool, // bools
ast_func, // func keyword
ast_hash, // hash, basic value type
ast_vec, // vector, basic value type
ast_pair, // pair of key and value in hashmap
ast_call, // mark a sub-tree of calling an identifier
ast_callh, // id.name
ast_callv, // id[index]
ast_callf, // id()
ast_subvec, // id[index:index]
ast_params, // mark a sub-tree of function parameters
ast_default, // default parameter
ast_dynamic, // dynamic parameter
ast_and, // and keyword
ast_or, // or keyword
ast_equal, // =
ast_addeq, // +=
ast_subeq, // -=
ast_multeq, // *=
ast_diveq, // /=
ast_lnkeq, // ~=
ast_btandeq, // &=
ast_btoreq, // |=
ast_btxoreq, // ^=
ast_cmpeq, // ==
ast_neq, // !=
ast_less, // <
ast_leq, // <=
ast_grt, // >
ast_geq, // >=
ast_add, // +
ast_sub, // -
ast_mult, // *
ast_div, // /
ast_link, // ~
ast_neg, // unary -
ast_lnot, // unary !
ast_bnot, // unary ~ bitwise not
ast_bitor, // bitwise or
ast_bitxor, // bitwise xor
ast_bitand, // bitwise and
ast_trino, // ?:
ast_for, // for keyword
ast_forindex, // forindex keyword
ast_foreach, // foreach keyword
ast_while, // while
ast_iter, // iterator, used in forindex/foreach
ast_cond, // mark a sub-tree of conditional expression
ast_if, // if keyword
ast_elsif, // elsif keyword
ast_else, // else keyword
ast_multi_id, // multi identifiers sub-tree
ast_tuple, // tuple, only used in multiple assignment
ast_def, // definition
ast_multi_assign,// multi assignment sub-tree
ast_continue, // continue keyword, only used in loop
ast_break, // break keyword, only used in loop
ast_ret // return keyword, only used in function block
};
class ast_visitor;
class ast_node {
private:
span nd_loc;
ast_node_type nd_type;
public:
ast_node(const span& location,ast_node_type node_type):
nd_loc(location), nd_type(node_type) {}
~ast_node() = default;
virtual bool accept(ast_visitor*) = 0;
};
class stmt:public ast_node {
public:
stmt(const span& location,ast_node_type node_type):
ast_node(location, node_type) {}
~stmt() = default;
virtual bool accept(ast_visitor*);
};
class expr:public ast_node {
private:
public:
expr(const span& location,ast_node_type node_type):
ast_node(location, node_type) {}
~expr() = default;
virtual bool accept(ast_visitor*);
};
class ast_visitor {
public:
virtual void visit_stmt(stmt*);
virtual void visit_expr(expr*);
};

View File

@ -18,11 +18,14 @@ SRC=\
STD=c++14
nasal:$(SRC)
nasal:$(SRC) nasal_new_ast.o
$(CXX) -std=$(STD) -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
nasal.exe:$(SRC)
$(CXX) -std=$(STD) -O3 main.cpp -o nasal.exe -fno-exceptions -Wshadow -Wall -static
nasal_new_ast.o: ast/nasal_new_ast.h ast/nasal_new_ast.cpp nasal.h
$(CXX) -std=$(STD) -c -O3 ast/nasal_new_ast.cpp -fno-exceptions -fPIC -o nasal_new_ast.o -I .
stable-release:$(SRC)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
stable-release-mingw:$(SRC)

View File

@ -4,9 +4,61 @@
#include "nasal_err.h"
#include "nasal_opcode.h"
#include "nasal_vm.h"
#include <cstring>
#include <algorithm>
#include <unordered_map>
class dbg:public vm {
private:
enum class dbg_cmd {
cmd_error,
cmd_help,
cmd_backtrace,
cmd_continue,
cmd_list_file,
cmd_global,
cmd_local,
cmd_upval,
cmd_register,
cmd_show_all,
cmd_next,
cmd_break_point,
cmd_exit
};
private:
const std::unordered_map<string, dbg_cmd> command_table = {
{"h", dbg_cmd::cmd_help},
{"help", dbg_cmd::cmd_help},
{"bt", dbg_cmd::cmd_backtrace},
{"backtrace", dbg_cmd::cmd_backtrace},
{"c", dbg_cmd::cmd_continue},
{"continue", dbg_cmd::cmd_continue},
{"f", dbg_cmd::cmd_list_file},
{"file", dbg_cmd::cmd_list_file},
{"g", dbg_cmd::cmd_global},
{"global", dbg_cmd::cmd_global},
{"l", dbg_cmd::cmd_local},
{"local", dbg_cmd::cmd_local},
{"u", dbg_cmd::cmd_upval},
{"upval", dbg_cmd::cmd_upval},
{"r", dbg_cmd::cmd_register},
{"register", dbg_cmd::cmd_register},
{"a", dbg_cmd::cmd_show_all},
{"all", dbg_cmd::cmd_show_all},
{"n", dbg_cmd::cmd_next},
{"next", dbg_cmd::cmd_next},
{"bk", dbg_cmd::cmd_break_point},
{"break", dbg_cmd::cmd_break_point},
{"q", dbg_cmd::cmd_exit},
{"exit", dbg_cmd::cmd_exit}
};
dbg_cmd get_cmd_type(const string& cmd) const {
return command_table.count(cmd)?
command_table.at(cmd):dbg_cmd::cmd_error;
}
private:
bool next;
usize fsize;
@ -15,11 +67,12 @@ private:
error& src;
std::vector<string> parse(const string&);
u16 fileindex(const string&);
u16 file_index(const string&) const;
void err();
void help();
void callsort(const u64*);
void stepinfo();
void list_file() const;
void call_sort(const u64*) const;
void step_info();
void interact();
public:
dbg(error& err):
@ -50,7 +103,7 @@ std::vector<string> dbg::parse(const string& cmd) {
return res;
}
u16 dbg::fileindex(const string& filename) {
u16 dbg::file_index(const string& filename) const {
for(u16 i=0;i<fsize;++i) {
if (filename==files[i]) {
return i;
@ -66,24 +119,30 @@ void dbg::err() {
}
void dbg::help() {
std::cout
std::clog
<<"<option>\n"
<<"\th, help | get help\n"
<<"\tbt, backtrace | get function call trace\n"
<<"\tc, continue | run program until break point or exit\n"
<<"\tf, file | see all the compiled files\n"
<<"\tg, global | see global values\n"
<<"\tl, local | see local values\n"
<<"\tu, upval | see upvalue\n"
<<"\tr, register | show vm register detail\n"
<<"\ta, all | show global,local and upvalue\n"
<<"\tn, next | execute next bytecode\n"
<<"\tq, exit | exit debugger\n"
<<" h, help | get help\n"
<<" bt, backtrace | get function call trace\n"
<<" c, continue | run program until break point or exit\n"
<<" f, file | see all the compiled files\n"
<<" g, global | see global values\n"
<<" l, local | see local values\n"
<<" u, upval | see upvalue\n"
<<" r, register | show vm register detail\n"
<<" a, all | show global,local and upvalue\n"
<<" n, next | execute next bytecode\n"
<<" q, exit | exit debugger\n"
<<"<option> <filename> <line>\n"
<<"\tbk, break | set break point\n";
<<" bk, break | set break point\n";
}
void dbg::callsort(const u64* arr) {
void dbg::list_file() const {
for(usize i=0; i<fsize; ++i) {
std::clog<<"["<<i<<"] "<<files[i]<<"\n";
}
}
void dbg::call_sort(const u64* arr) const {
typedef std::pair<u32,u64> op;
std::vector<op> opcall;
u64 total=0;
@ -105,22 +164,22 @@ void dbg::callsort(const u64* arr) {
std::clog<<" total : "<<total<<'\n';
}
void dbg::stepinfo() {
void dbg::step_info() {
u32 line=bytecode[ctx.pc].line==0?0:bytecode[ctx.pc].line-1;
u32 begin=(line>>3)==0?0:((line>>3)<<3);
u32 end=(1+(line>>3))<<3;
src.load(files[bytecode[ctx.pc].fidx]);
std::cout<<"\nsource code:\n";
std::clog<<"\nsource code:\n";
for(u32 i=begin;i<end && i<src.size();++i) {
std::cout<<(i==line?back_white:reset)<<(i==line?"--> ":" ")<<src[i]<<reset<<"\n";
std::clog<<(i==line?back_white:reset)<<(i==line?"--> ":" ")<<src[i]<<reset<<"\n";
}
begin=(ctx.pc>>3)==0?0:((ctx.pc>>3)<<3);
end=(1+(ctx.pc>>3))<<3;
codestream::set(cnum, cstr, files);
std::cout<<"next bytecode:\n";
std::clog<<"next bytecode:\n";
for(u32 i=begin;i<end && bytecode[i].op!=op_exit;++i) {
std::cout
std::clog
<<(i==ctx.pc?back_white:reset)
<<(i==ctx.pc?"--> ":" ")
<<codestream(bytecode[i], i)
@ -130,65 +189,51 @@ void dbg::stepinfo() {
}
void dbg::interact() {
// special operand
// special operand, end execution
if (bytecode[ctx.pc].op==op_exit) {
return;
}
if (
(bytecode[ctx.pc].fidx!=bk_fidx || bytecode[ctx.pc].line!=bk_line) && // break point
!next // next step
) {
if ((bytecode[ctx.pc].fidx!=bk_fidx ||
bytecode[ctx.pc].line!=bk_line) && // break point
!next) {// next step
return;
}
next=false;
string cmd;
stepinfo();
step_info();
while(true) {
std::cout<<">> ";
std::clog<<">> ";
std::getline(std::cin, cmd);
auto res=parse(cmd);
if (res.size()==0) {
stepinfo();
step_info();
} else if (res.size()==1) {
if (res[0]=="h" || res[0]=="help") {
help();
} else if (res[0]=="bt" || res[0]=="backtrace") {
traceback();
} else if (res[0]=="c" || res[0]=="continue") {
return;
} else if (res[0]=="f" || res[0]=="file") {
for(usize i=0;i<fsize;++i) {
std::cout<<"["<<i<<"] "<<files[i]<<"\n";
}
} else if (res[0]=="g" || res[0]=="global") {
gstate();
} else if (res[0]=="l" || res[0]=="local") {
lstate();
} else if (res[0]=="u" || res[0]=="upval") {
ustate();
} else if (res[0]=="r" || res[0]=="register") {
reginfo();
} else if (res[0]=="a" || res[0]=="all") {
detail();
} else if (res[0]=="n" || res[0]=="next") {
next=true;
return;
} else if (res[0]=="q" || res[0]=="exit")
std::exit(0);
else {
err();
switch(get_cmd_type(res[0])) {
case dbg_cmd::cmd_help: help(); break;
case dbg_cmd::cmd_backtrace: traceback(); break;
case dbg_cmd::cmd_continue: return;
case dbg_cmd::cmd_list_file: list_file(); break;
case dbg_cmd::cmd_global: gstate(); break;
case dbg_cmd::cmd_local: lstate(); break;
case dbg_cmd::cmd_upval: ustate(); break;
case dbg_cmd::cmd_register: reginfo(); break;
case dbg_cmd::cmd_show_all: detail(); break;
case dbg_cmd::cmd_next: next=true; return;
case dbg_cmd::cmd_exit: std::exit(0);
default: err(); break;
}
} else if (res.size()==3 && (res[0]=="bk" || res[0]=="break")) {
bk_fidx=fileindex(res[1]);
} else if (res.size()==3 &&
get_cmd_type(res[0])==dbg_cmd::cmd_break_point) {
bk_fidx=file_index(res[1]);
if (bk_fidx==65535) {
std::cout<<"cannot find file named `"<<res[1]<<"`\n";
bk_fidx=0;
std::clog<<"cannot find file named `"<<res[1]<<"`\n";
continue;
}
i32 tmp=atoi(res[2].c_str());
if (tmp<=0) {
std::cout<<"incorrect line number `"<<res[2]<<"`\n";
std::clog<<"incorrect line number `"<<res[2]<<"`\n";
} else {
bk_line=tmp;
}
@ -201,8 +246,7 @@ void dbg::interact() {
void dbg::run(
const codegen& gen,
const linker& linker,
const std::vector<string>& argv
) {
const std::vector<string>& argv) {
verbose=true;
fsize=linker.filelist().size();
init(gen.strs(), gen.nums(), gen.codes(), linker.filelist(), argv);
@ -269,7 +313,7 @@ void dbg::run(
++ctx.pc;
}
callsort(count);
call_sort(count);
ngc.info();
ngc.clear();
imm.clear();

View File

@ -249,7 +249,7 @@ public:
if (mapper.count(name)) {
std::cerr<<"nasal_gc.h: ghost_register_table::register_ghost_type: ";
std::cerr<<"ghost type \""<<name<<"\" already exists.\n";
std::exit(-1);
std::exit(1);
}
auto res=destructors.size();
mapper[name]=res;
@ -754,7 +754,7 @@ void gc::extend(u8 type) {
if (!tmp) {
std::cerr<<"nasal_gc.h: gc::extend: ";
std::cerr<<"failed to allocate memory\n";
std::exit(-1);
std::exit(1);
}
// add to heap
@ -762,7 +762,7 @@ void gc::extend(u8 type) {
unused[index].push_back(tmp);
}
incr[index]*=2;
incr[index]=incr[index]+incr[index]/2;
}
void gc::init(const std::vector<string>& s, const std::vector<string>& argv) {

View File

@ -11,7 +11,7 @@ var new_map=func(width,height){
}
var prt=func(map){
var s='\ec\e[1;1H';
var s='\e[H';
foreach(var line;map){
foreach(var elem;line)
s~=elem~' ';