add experimental namespace table

This commit is contained in:
ValKmjolnir 2023-07-16 21:31:51 +08:00
parent eee30b7d8e
commit fe3847d69c
10 changed files with 185 additions and 125 deletions

View File

@ -23,9 +23,11 @@ const u32 VM_TIME = 1<<3;
const u32 VM_EXEC = 1<<4;
const u32 VM_DETAIL = 1<<5;
const u32 VM_DEBUG = 1<<6;
const u32 VM_SYMINFO = 1<<7;
std::ostream& help(std::ostream& out) {
out
<< "\n"
<< " ,--#-,\n"
<< "<3 / \\____\\ <3\n"
<< " |_|__A_|\n"
@ -41,6 +43,7 @@ std::ostream& help(std::ostream& out) {
<< " -a, --ast | view ast after link/optimize process.\n"
<< " --raw-ast | view ast without after-processing.\n"
<< " -c, --code | view generated bytecode.\n"
<< " -s, --symbol | show analysed symbol info.\n"
<< " -e, --exec | execute directly.\n"
<< " -t, --time | show execute time.\n"
<< " -d, --detail | get detail info.\n"
@ -48,12 +51,14 @@ std::ostream& help(std::ostream& out) {
<< "file:\n"
<< " <filename> | execute file.\n"
<< "argv:\n"
<< " <args> | cmd arguments used in program.\n";
<< " <args> | cmd arguments used in program.\n"
<< "\n";
return out;
}
std::ostream& logo(std::ostream& out) {
out
<< "\n"
<< " __ _\n"
<< " /\\ \\ \\__ _ ___ __ _| |\n"
<< " / \\/ / _` / __|/ _` | |\n"
@ -65,7 +70,8 @@ std::ostream& logo(std::ostream& out) {
<< "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
<< "input <nasal -h> to get help .\n";
<< "\n"
<< "input <nasal -h> to get help .\n\n";
return out;
}
@ -133,6 +139,14 @@ void execute(
if (cmd&VM_CODE) {
gen.print(std::cout);
}
if (cmd&VM_SYMINFO) {
for(const auto& domain : gen.get_experimental_namespace()) {
std::cout << domain.first << ":\n";
for(const auto& i : domain.second) {
std::cout << " [" << domain.first << "]@" << i << "\n";
}
}
}
// run
auto start = clk::now();
@ -178,6 +192,8 @@ i32 main(i32 argc, const char* argv[]) {
{"-a", VM_AST},
{"--code", VM_CODE},
{"-c", VM_CODE},
{"--symbol", VM_SYMINFO},
{"-s", VM_SYMINFO},
{"--exec", VM_EXEC},
{"-e", VM_EXEC},
{"--time", VM_TIME|VM_EXEC},

View File

@ -47,7 +47,13 @@ void codegen::regist_str(const std::string& str) {
void codegen::find_symbol(code_block* node) {
auto finder = std::unique_ptr<symbol_finder>(new symbol_finder);
for(const auto& i : finder->do_find(node)) {
add_symbol(i);
if (!experimental_namespace.count(i.file)) {
experimental_namespace[i.file] = {};
}
if (local.empty() && !experimental_namespace.at(i.file).count(i.name)) {
experimental_namespace.at(i.file).insert(i.name);
}
add_symbol(i.name);
}
}

View File

@ -13,6 +13,7 @@
#include <list>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#ifdef _MSC_VER
#pragma warning (disable:4244)
@ -36,6 +37,7 @@ private:
// symbol table
// global : max STACK_DEPTH-1 values
std::unordered_map<std::string, i32> global;
std::unordered_map<std::string, std::unordered_set<std::string>> experimental_namespace;
// local : max 32768 upvalues 65536 values
// but in fact local scope also has less than STACK_DEPTH value
std::list<std::unordered_map<std::string, i32>> local;
@ -94,10 +96,13 @@ private:
void ret_gen(return_expr*);
public:
const std::vector<std::string>& strs() const {return const_string_table;}
const std::vector<f64>& nums() const {return const_number_table;}
const std::vector<opcode>& codes() const {return code;}
const std::unordered_map<std::string, i32>& globals() const {return global;}
const auto& strs() const {return const_string_table;}
const auto& nums() const {return const_number_table;}
const auto& codes() const {return code;}
const auto& globals() const {return global;}
const auto& get_experimental_namespace() const {
return experimental_namespace;
}
public:
codegen(error& e): fileindex(0), err(e), file(nullptr) {}

View File

@ -56,7 +56,8 @@ std::ostream& white(std::ostream& s) {
std::ostream& reset(std::ostream& s) {
#ifdef _WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), reset_ter_color.scr.wAttributes);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
reset_ter_color.scr.wAttributes);
#else
s << "\033[0m";
#endif

View File

@ -137,6 +137,12 @@ void nas_ghost::clear() {
ptr = nullptr;
}
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
out << "<object " << ghost.get_ghost_name();
out << " at 0x" << std::hex << (u64)ghost.ptr << std::dec << ">";
return out;
}
void nas_co::clear() {
for(u32 i = 0; i<STACK_DEPTH; ++i) {
stack[i] = var::nil();
@ -153,6 +159,11 @@ void nas_co::clear() {
status = coroutine_status::suspended;
}
std::ostream& operator<<(std::ostream& out, const nas_co& co) {
out << "<coroutine at 0x" << std::hex << u64(&co) << std::dec << ">";
return out;
}
var nas_map::get_val(const std::string& key) {
if (mapper.count(key)) {
return *mapper.at(key);
@ -251,7 +262,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
case vm_hash: out << ref.hash(); break;
case vm_func: out << "func(..) {..}"; break;
case vm_obj: out << ref.obj(); break;
case vm_co: out << "<coroutine>"; break;
case vm_co: out << ref.co(); break;
case vm_map: out << ref.map(); break;
}
return out;
@ -356,8 +367,8 @@ void gc::do_mark_sweep() {
void gc::mark() {
std::vector<var> bfs;
mark_context(bfs);
if (memory.size()>1048576 && bfs.size()>4) {
mark_context_root(bfs);
if (memory.size()>8192 && bfs.size()>4) {
usize size = bfs.size();
std::thread t0(&gc::concurrent_mark, this, std::ref(bfs), 0, size/4);
std::thread t1(&gc::concurrent_mark, this, std::ref(bfs), size/4, size/2);
@ -402,7 +413,7 @@ void gc::concurrent_mark(std::vector<var>& vec, usize begin, usize end) {
}
}
void gc::mark_context(std::vector<var>& bfs_queue) {
void gc::mark_context_root(std::vector<var>& bfs_queue) {
// scan now running context, this context maybe related to coroutine or main
for(var* i = rctx->stack; i<=rctx->top; ++i) {

View File

@ -101,7 +101,6 @@ public:
bool operator!=(const var& nr) const {
return type!=nr.type || val.gcobj!=nr.val.gcobj;
}
friend std::ostream& operator<<(std::ostream&, var&);
// number and string can be translated to each other
f64 tonum();
@ -267,12 +266,6 @@ public:
void clear();
public:
friend std::ostream& operator<<(std::ostream& out, nas_ghost& ghost) {
out << "<object " << ghost.ghost_type_table->get_ghost_name(ghost.type);
out << " at 0x" << std::hex << (u64)ghost.ptr << std::dec << ">";
return out;
}
const std::string& get_ghost_name() const {
return ghost_type_table->get_ghost_name(type);
}
@ -334,6 +327,8 @@ struct nas_val {
std::ostream& operator<<(std::ostream&, nas_vec&);
std::ostream& operator<<(std::ostream&, nas_hash&);
std::ostream& operator<<(std::ostream&, nas_map&);
std::ostream& operator<<(std::ostream&, const nas_ghost&);
std::ostream& operator<<(std::ostream&, const nas_co&);
std::ostream& operator<<(std::ostream&, var&);
const var zero = var::num(0);
@ -386,7 +381,7 @@ private:
void do_mark_sweep();
void mark();
void concurrent_mark(std::vector<var>&, usize, usize);
void mark_context(std::vector<var>&);
void mark_context_root(std::vector<var>&);
void mark_var(std::vector<var>&, var&);
void mark_vec(std::vector<var>&, nas_vec&);
void mark_hash(std::vector<var>&, nas_hash&);

View File

@ -47,108 +47,117 @@ void vm::init(
void vm::valinfo(var& val) {
const nas_val* p = val.val.gcobj;
switch(val.type) {
case vm_none: std::clog<<"| null |";break;
case vm_ret: std::clog<<"| pc | 0x"<<std::hex
<<val.ret()<<std::dec;break;
case vm_addr: std::clog<<"| addr | 0x"<<std::hex
<<(u64)val.addr()<<std::dec;break;
case vm_cnt: std::clog<<"| cnt | "<<val.cnt();break;
case vm_nil: std::clog<<"| nil |";break;
case vm_num: std::clog<<"| num | "<<val.num();break;
case vm_str: std::clog<<"| str | <0x"<<std::hex<<(u64)p
<<"> "<<rawstr(val.str(),16)
<<std::dec;break;
case vm_func: std::clog<<"| func | <0x"<<std::hex<<(u64)p
<<"> entry:0x"<<val.func().entry
<<std::dec;break;
case vm_upval:std::clog<<"| upval| <0x"<<std::hex<<(u64)p
<<std::dec<<"> ["<<val.upval().size
<<" val]";break;
case vm_vec: std::clog<<"| vec | <0x"<<std::hex<<(u64)p
<<std::dec<<"> ["<<val.vec().size()
<<" val]";break;
case vm_hash: std::clog<<"| hash | <0x"<<std::hex<<(u64)p
<<std::dec<<"> {"<<val.hash().size()
<<" val}";break;
case vm_obj: std::clog<<"| obj | <0x"<<std::hex<<(u64)p
<<"> obj:0x"<<(u64)val.obj().ptr
<<std::dec;break;
case vm_co: std::clog<<"| co | <0x"<<std::hex<<(u64)p
<<std::dec<<"> coroutine";break;
default: std::clog<<"| err | <0x"<<std::hex<<(u64)p
<<std::dec<<"> unknown object";break;
case vm_none: std::clog << "| null |"; break;
case vm_ret: std::clog << "| pc | 0x" << std::hex
<< val.ret() << std::dec; break;
case vm_addr: std::clog << "| addr | 0x" << std::hex
<< (u64)val.addr() << std::dec; break;
case vm_cnt: std::clog << "| cnt | " << val.cnt(); break;
case vm_nil: std::clog << "| nil |"; break;
case vm_num: std::clog << "| num | " << val.num(); break;
case vm_str: std::clog << "| str | <0x" << std::hex << (u64)p
<< "> " << rawstr(val.str(), 16)
<< std::dec; break;
case vm_func: std::clog << "| func | <0x" << std::hex << (u64)p
<< "> entry:0x" << val.func().entry
<< std::dec; break;
case vm_upval:std::clog << "| upval| <0x" << std::hex << (u64)p
<< std::dec << "> [" << val.upval().size
<< " val]"; break;
case vm_vec: std::clog << "| vec | <0x" << std::hex << (u64)p
<< std::dec << "> [" << val.vec().size()
<< " val]"; break;
case vm_hash: std::clog << "| hash | <0x" << std::hex << (u64)p
<< std::dec << "> {" << val.hash().size()
<< " val}"; break;
case vm_obj: std::clog << "| obj | <0x" << std::hex << (u64)p
<< "> obj:0x" << (u64)val.obj().ptr
<< std::dec; break;
case vm_co: std::clog << "| co | <0x" << std::hex << (u64)p
<< std::dec << "> coroutine"; break;
case vm_map: std::clog << "| nmspc| <0x" << std::hex << (u64)p
<< std::dec << "> namespace ["
<< val.map().mapper.size() << " val]"; break;
default: std::clog << "| err | <0x" << std::hex << (u64)p
<< std::dec << "> unknown object"; break;
}
std::clog<<"\n";
std::clog << "\n";
}
void vm::traceback() {
/* bytecode[0].num is the global size */
var* bottom=ngc.rctx->stack==stack?stack+bytecode[0].num:ngc.rctx->stack;
var* ctx_top=ngc.rctx->stack==stack?ctx.top:ngc.rctx->top;
var* bottom = ngc.rctx->stack==stack? stack+bytecode[0].num:ngc.rctx->stack;
var* ctx_top = ngc.rctx->stack==stack? ctx.top:ngc.rctx->top;
std::stack<u32> ret;
for(var* i=bottom;i<=ctx_top;++i) {
for(var* i = bottom; i<=ctx_top; ++i) {
if (i->type==vm_ret && i->ret()!=0) {
ret.push(i->ret());
}
}
ret.push(ctx.pc); // store the position program crashed
std::clog<<"trace back ("<<(ngc.rctx->stack==stack?"main":"coroutine")<<")\n";
std::clog << "trace back ("
<< (ngc.rctx->stack==stack? "main":"coroutine")
<< ")\n";
codestream::set(cnum, cstr, files);
for(u32 p=0,same=0,prev=0xffffffff;!ret.empty();prev=p,ret.pop()) {
if ((p=ret.top())==prev) {
for(u32 p = 0, same = 0, prev = 0xffffffff; !ret.empty(); prev = p, ret.pop()) {
if ((p = ret.top())==prev) {
++same;
continue;
}
if (same) {
std::clog
<<" 0x"<<std::hex<<std::setw(6)<<std::setfill('0')
<<prev<<std::dec<<" "<<same<<" same call(s)\n";
std::clog << " 0x" << std::hex
<< std::setw(6) << std::setfill('0')
<< prev << std::dec << " "
<< same << " same call(s)\n";
}
same=0;
std::clog<<" "<<codestream(bytecode[p],p)<<"\n";
same = 0;
std::clog << " " << codestream(bytecode[p], p) << "\n";
}
// the first called place has no same calls
}
void vm::stackinfo(const u32 limit=10) {
void vm::stackinfo(const u32 limit = 10) {
/* bytecode[0].num is the global size */
const u32 gsize=ngc.rctx->stack==stack?bytecode[0].num:0;
var* t=ctx.top;
var* bottom=ngc.rctx->stack+gsize;
std::clog<<"stack (0x"<<std::hex<<(u64)bottom<<std::dec
<<" <+"<<gsize<<">, limit "<<limit<<", total "
<<(t<bottom? 0:(i64)(t-bottom+1))<<")\n";
for(u32 i=0;i<limit && t>=bottom;++i,--t) {
std::clog<<" 0x"<<std::hex
<<std::setw(6)<<std::setfill('0')
<<(u64)(t-ngc.rctx->stack)<<std::dec
<<" ";
const u32 gsize = ngc.rctx->stack==stack? bytecode[0].num:0;
var* t = ctx.top;
var* bottom = ngc.rctx->stack+gsize;
std::clog << "stack (0x" << std::hex << (u64)bottom << std::dec;
std::clog << " <+" << gsize << ">, limit " << limit << ", total ";
std::clog << (t<bottom? 0:(i64)(t-bottom+1)) << ")\n";
for(u32 i = 0; i<limit && t>=bottom; ++i, --t) {
std::clog << " 0x" << std::hex
<< std::setw(6) << std::setfill('0')
<< (u64)(t-ngc.rctx->stack) << std::dec
<< " ";
valinfo(t[0]);
}
}
void vm::reginfo() {
std::clog<<"registers ("<<(ngc.cort?"coroutine":"main")<<")\n"<<std::hex
<<" [pc ] | pc | 0x"<<ctx.pc<<"\n"
<<" [global] | addr | 0x"<<(u64)stack<<"\n"
<<" [local ] | addr | 0x"<<(u64)ctx.localr<<"\n"
<<" [memr ] | addr | 0x"<<(u64)ctx.memr<<"\n"
<<" [canary] | addr | 0x"<<(u64)ctx.canary<<"\n"
<<" [top ] | addr | 0x"<<(u64)ctx.top<<"\n"
<<std::dec;
std::clog<<" [funcr ] ";valinfo(ctx.funcr);
std::clog<<" [upval ] ";valinfo(ctx.upvalr);
std::clog << "registers (" << (ngc.cort? "coroutine":"main")
<< ")\n" << std::hex
<< " [pc ] | pc | 0x" << ctx.pc << "\n"
<< " [global] | addr | 0x" << (u64)stack << "\n"
<< " [local ] | addr | 0x" << (u64)ctx.localr << "\n"
<< " [memr ] | addr | 0x" << (u64)ctx.memr << "\n"
<< " [canary] | addr | 0x" << (u64)ctx.canary << "\n"
<< " [top ] | addr | 0x" << (u64)ctx.top << "\n"
<< std::dec;
std::clog << " [funcr ] "; valinfo(ctx.funcr);
std::clog << " [upval ] "; valinfo(ctx.upvalr);
}
void vm::gstate() {
if (!bytecode[0].num || stack[0].type==vm_none) { // bytecode[0].op is op_intg
// bytecode[0].op is op_intg
if (!bytecode[0].num || stack[0].type==vm_none) {
return;
}
std::clog<<"global (0x"<<std::hex<<(u64)stack<<" <+0>)\n"<<std::dec;
for(u32 i=0;i<bytecode[0].num;++i) {
std::clog<<" 0x"<<std::hex<<std::setw(6)
<<std::setfill('0')<<i<<std::dec
<<" ";
std::clog << "global (0x" << std::hex
<< (u64)stack << " <+0>)\n" << std::dec;
for(u32 i = 0; i<bytecode[0].num; ++i) {
std::clog << " 0x" << std::hex << std::setw(6)
<< std::setfill('0') << i << std::dec
<< " ";
valinfo(stack[i]);
}
}
@ -157,13 +166,14 @@ void vm::lstate() {
if (!ctx.localr || !ctx.funcr.func().lsize) {
return;
}
const u32 lsize=ctx.funcr.func().lsize;
std::clog<<"local (0x"<<std::hex<<(u64)ctx.localr
<<" <+"<<(u64)(ctx.localr-ngc.rctx->stack)<<">)\n"<<std::dec;
for(u32 i=0;i<lsize;++i) {
std::clog<<" 0x"<<std::hex<<std::setw(6)
<<std::setfill('0')<<i<<std::dec
<<" ";
const u32 lsize = ctx.funcr.func().lsize;
std::clog << "local (0x" << std::hex << (u64)ctx.localr
<< " <+" << (u64)(ctx.localr-ngc.rctx->stack)
<< ">)\n" << std::dec;
for(u32 i = 0; i<lsize; ++i) {
std::clog << " 0x" << std::hex << std::setw(6)
<< std::setfill('0') << i << std::dec
<< " ";
valinfo(ctx.localr[i]);
}
}
@ -172,15 +182,15 @@ void vm::ustate() {
if (ctx.funcr.type==vm_nil || ctx.funcr.func().upval.empty()) {
return;
}
std::clog<<"upvalue\n";
auto& upval=ctx.funcr.func().upval;
for(u32 i=0;i<upval.size();++i) {
std::clog<<" -> upval["<<i<<"]:\n";
auto& uv=upval[i].upval();
for(u32 j=0;j<uv.size;++j) {
std::clog<<" 0x"<<std::hex<<std::setw(6)
<<std::setfill('0')<<j<<std::dec
<<" ";
std::clog << "upvalue\n";
auto& upval = ctx.funcr.func().upval;
for(u32 i = 0; i<upval.size(); ++i) {
std::clog << " -> upval[" << i << "]:\n";
auto& uv = upval[i].upval();
for(u32 j = 0; j<uv.size; ++j) {
std::clog << " 0x" << std::hex << std::setw(6)
<< std::setfill('0') << j << std::dec
<< " ";
valinfo(uv[j]);
}
}
@ -194,7 +204,7 @@ void vm::detail() {
}
void vm::die(const std::string& str) {
std::cerr<<"[vm] error: "<<str<<"\n";
std::cerr << "[vm] error: " << str << "\n";
traceback();
stackinfo();
@ -203,13 +213,14 @@ void vm::die(const std::string& str) {
detail();
}
if (ngc.rctx->stack==stack) { // in main context, exit directly
if (ngc.rctx->stack==stack) {
// in main context, exit directly
std::exit(1);
} else {
// in coroutine, shut down the coroutine and return to main context
ctx.pc=0; // mark coroutine 'dead'
ngc.ctxreserve();
ctx.top[0]=nil;
ctx.pc = 0; // mark coroutine 'dead'
ngc.ctxreserve(); // switch context to main
ctx.top[0] = nil; // generate return value 'nil'
}
}
@ -217,9 +228,8 @@ void vm::run(
const codegen& gen,
const linker& linker,
const std::vector<std::string>& argv,
const bool detail
) {
verbose=detail;
const bool detail) {
verbose = detail;
init(gen.strs(),
gen.nums(),
gen.codes(),
@ -227,7 +237,8 @@ void vm::run(
linker.filelist(),
argv);
#ifndef _MSC_VER
const void* oprs[]={
// using labels as values/computed goto
const void* oprs[] = {
&&vmexit, &&intg, &&intl, &&loadg,
&&loadl, &&loadu, &&pnum, &&pnil,
&&pstr, &&newv, &&newh, &&newf,
@ -252,7 +263,7 @@ void vm::run(
&&mcallv, &&mcallh, &&ret
};
std::vector<const void*> code;
for(auto& i:gen.codes()) {
for(auto& i : gen.codes()) {
code.push_back(oprs[i.op]);
imm.push_back(i.num);
}
@ -260,7 +271,7 @@ void vm::run(
goto *code[ctx.pc];
#else
typedef void (vm::*nafunc)();
const nafunc oprs[]={
const nafunc oprs[] = {
nullptr, &vm::o_intg,
&vm::o_intl, &vm::o_loadg,
&vm::o_loadl, &vm::o_loadu,
@ -307,7 +318,7 @@ void vm::run(
&vm::o_ret
};
std::vector<nafunc> code;
for(auto& i:gen.codes()) {
for(auto& i : gen.codes()) {
code.push_back(oprs[i.op]);
imm.push_back(i.num);
}

View File

@ -2,10 +2,16 @@
bool symbol_finder::visit_definition_expr(definition_expr* node) {
if (node->get_variable_name()) {
symbols.push_back(node->get_variable_name()->get_name());
symbols.push_back({
node->get_variable_name()->get_name(),
node->get_variable_name()->get_location().file
});
} else {
for(auto i : node->get_variables()->get_variables()) {
symbols.push_back(i->get_name());
symbols.push_back({
i->get_name(),
i->get_location().file
});
}
}
if (node->get_tuple()) {
@ -22,12 +28,14 @@ bool symbol_finder::visit_function(function* node) {
bool symbol_finder::visit_iter_expr(iter_expr* node) {
if (node->get_name()) {
symbols.push_back(node->get_name()->get_name());
symbols.push_back({
node->get_name()->get_name(),
node->get_name()->get_location().file});
}
return true;
}
const std::vector<std::string>& symbol_finder::do_find(code_block* root) {
const std::vector<symbol_finder::symbol_info>& symbol_finder::do_find(code_block* root) {
symbols.clear();
root->accept(this);
return symbols;

View File

@ -8,12 +8,18 @@
#include <vector>
class symbol_finder:public ast_visitor {
public:
struct symbol_info {
std::string name;
std::string file;
};
private:
std::vector<std::string> symbols;
std::vector<symbol_info> symbols;
public:
bool visit_definition_expr(definition_expr*) override;
bool visit_function(function*) override;
bool visit_iter_expr(iter_expr*) override;
const std::vector<std::string>& do_find(code_block*);
const std::vector<symbol_finder::symbol_info>& do_find(code_block*);
};

View File

@ -35,3 +35,4 @@ b(1, 2, 3, 4); # 1 [2 3 4]
# command line arguments
println(arg);
println(globals.arg);
println(typeof(globals));