166 lines
4.7 KiB
C++
166 lines
4.7 KiB
C++
#include "nasal.h"
|
|
#include "nasal_err.h"
|
|
#include "nasal_lexer.h"
|
|
#include "nasal_ast.h"
|
|
#include "nasal_parse.h"
|
|
#include "nasal_import.h"
|
|
#include "nasal_opt.h"
|
|
#include "nasal_gc.h"
|
|
#include "nasal_builtin.h"
|
|
#include "nasal_codegen.h"
|
|
#include "nasal_vm.h"
|
|
#include "nasal_dbg.h"
|
|
|
|
#include <unordered_map>
|
|
|
|
using ch_clk=std::chrono::high_resolution_clock;
|
|
|
|
const u32 VM_AST =0x01;
|
|
const u32 VM_CODE =0x02;
|
|
const u32 VM_TIME =0x04;
|
|
const u32 VM_EXEC =0x08;
|
|
const u32 VM_DETAIL=0x10;
|
|
const u32 VM_DEBUG =0x20;
|
|
const u32 VM_OPT =0x40;
|
|
|
|
std::ostream& help(std::ostream& out)
|
|
{
|
|
out
|
|
<<" ,--#-,\n"
|
|
<<"<3 / \\____\\ <3\n"
|
|
<<" |_|__A_|\n"
|
|
#ifdef _WIN32
|
|
<<"use command <chcp 65001> to use unicode.\n"
|
|
#endif
|
|
<<"\nnasal <option>\n"
|
|
<<"option:\n"
|
|
<<" -h, --help | get help.\n"
|
|
<<"\nnasal [option] <file> [argv]\n"
|
|
<<"option:\n"
|
|
<<" -a, --ast | view abstract syntax tree.\n"
|
|
<<" -c, --code | view bytecode.\n"
|
|
<<" -e, --exec | execute.\n"
|
|
<<" -t, --time | show execute time.\n"
|
|
<<" -d, --detail | get detail crash info.\n"
|
|
<<" | get detail path-not-found info.\n"
|
|
<<" | get detail gc info.\n"
|
|
<<" -o, --optimize | use optimizer (beta).\n"
|
|
<<" | use <-o -e> to run optimized code.\n"
|
|
<<" -dbg, --debug | debug mode (ignore -t -d).\n"
|
|
<<"file:\n"
|
|
<<" <filename> | execute file.\n"
|
|
<<"argv:\n"
|
|
<<" <args> | cmd arguments used in program.\n";
|
|
return out;
|
|
}
|
|
|
|
std::ostream& logo(std::ostream& out)
|
|
{
|
|
out
|
|
<<" __ _\n"
|
|
<<" /\\ \\ \\__ _ ___ __ _| |\n"
|
|
<<" / \\/ / _` / __|/ _` | |\n"
|
|
<<" / /\\ / (_| \\__ \\ (_| | |\n"
|
|
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
|
<<"version : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n"
|
|
<<"c++ std : "<<__cplusplus<<"\n"
|
|
<<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
|
|
<<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
|
<<"lang wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
|
<<"input <nasal -h> to get help .\n";
|
|
return out;
|
|
}
|
|
|
|
[[noreturn]]
|
|
void err()
|
|
{
|
|
std::cerr
|
|
<<"invalid argument(s).\n"
|
|
<<"use <nasal -h> to get help.\n";
|
|
std::exit(1);
|
|
}
|
|
|
|
void execute(const string& file,const std::vector<string>& argv,const u32 cmd)
|
|
{
|
|
error err;
|
|
lexer lex(err);
|
|
parse parse(err);
|
|
linker ld(err);
|
|
codegen gen(err);
|
|
vm ctx;
|
|
|
|
// lexer scans file to get tokens
|
|
lex.scan(file).chkerr();
|
|
// parser gets lexer's token list to compile
|
|
parse.compile(lex).chkerr();
|
|
// linker gets parser's ast and load import files to this ast
|
|
ld.link(parse,file,cmd&VM_DETAIL).chkerr();
|
|
// optimizer does simple optimization on ast
|
|
if(cmd&VM_OPT)
|
|
optimize(parse.tree());
|
|
if(cmd&VM_AST)
|
|
parse.print();
|
|
|
|
// code generator gets parser's ast and linker's import file list to generate code
|
|
gen.compile(parse,ld).chkerr();
|
|
if(cmd&VM_CODE)
|
|
gen.print();
|
|
|
|
// run
|
|
if(cmd&VM_DEBUG)
|
|
debugger(err).run(gen,ld,argv);
|
|
else if(cmd&VM_TIME)
|
|
{
|
|
auto start=ch_clk::now();
|
|
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
|
auto end=ch_clk::now();
|
|
std::clog<<"process exited after "<<(end-start).count()*1.0/ch_clk::duration::period::den<<"s.\n";
|
|
}
|
|
else if(cmd&VM_EXEC)
|
|
ctx.run(gen,ld,argv,cmd&VM_DETAIL);
|
|
}
|
|
|
|
i32 main(i32 argc,const char* argv[])
|
|
{
|
|
if(argc<=1)
|
|
{
|
|
std::clog<<logo;
|
|
return 0;
|
|
}
|
|
if(argc==2)
|
|
{
|
|
string s(argv[1]);
|
|
if(s=="-h" || s=="--help")
|
|
std::clog<<help;
|
|
else if(s[0]!='-')
|
|
execute(s,{},VM_EXEC);
|
|
else
|
|
err();
|
|
return 0;
|
|
}
|
|
std::unordered_map<string,u32> cmdlst={
|
|
{"--ast",VM_AST},{"-a",VM_AST},
|
|
{"--code",VM_CODE},{"-c",VM_CODE},
|
|
{"--exec",VM_EXEC},{"-e",VM_EXEC},
|
|
{"--time",VM_TIME|VM_EXEC},{"-t",VM_TIME|VM_EXEC},
|
|
{"--detail",VM_DETAIL|VM_EXEC},{"-d",VM_DETAIL|VM_EXEC},
|
|
{"--optimize",VM_OPT},{"-o",VM_OPT},
|
|
{"--debug",VM_DEBUG},{"-dbg",VM_DEBUG}
|
|
};
|
|
u32 cmd=0;
|
|
string filename="";
|
|
std::vector<string> vm_argv;
|
|
for(i32 i=1;i<argc;++i)
|
|
{
|
|
if(cmdlst.count(argv[i]))
|
|
cmd|=cmdlst[argv[i]];
|
|
else if(!filename.length())
|
|
filename=argv[i];
|
|
else
|
|
vm_argv.push_back(argv[i]);
|
|
}
|
|
if(!filename.length())
|
|
err();
|
|
execute(filename,vm_argv,cmd?cmd:VM_EXEC);
|
|
return 0;
|
|
} |