✨ add experimental REPL (cpp)
This commit is contained in:
parent
ae5c76ecd5
commit
a801669888
|
@ -38,7 +38,8 @@ set(NASAL_OBJECT_SOURCE_FILE
|
|||
${CMAKE_SOURCE_DIR}/src/nasal_parse.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_vm.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/optimizer.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp)
|
||||
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/repl.cpp)
|
||||
add_library(nasal-object STATIC ${NASAL_OBJECT_SOURCE_FILE})
|
||||
target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
|
|
7
makefile
7
makefile
|
@ -23,7 +23,8 @@ NASAL_HEADER=\
|
|||
src/math_lib.h\
|
||||
src/dylib_lib.h\
|
||||
src/unix_lib.h\
|
||||
src/coroutine.h
|
||||
src/coroutine.h\
|
||||
src/repl.h
|
||||
|
||||
NASAL_OBJECT=\
|
||||
build/nasal_err.o\
|
||||
|
@ -49,6 +50,7 @@ NASAL_OBJECT=\
|
|||
build/coroutine.o\
|
||||
build/nasal_vm.o\
|
||||
build/nasal_dbg.o\
|
||||
build/repl.o\
|
||||
build/main.o
|
||||
|
||||
# for test
|
||||
|
@ -67,6 +69,9 @@ build/main.o: $(NASAL_HEADER) src/main.cpp | build
|
|||
build/nasal_misc.o: src/nasal.h src/nasal_misc.cpp | build
|
||||
$(CXX) -std=$(STD) -c -O3 src/nasal_misc.cpp -fno-exceptions -fPIC -o build/nasal_misc.o -I .
|
||||
|
||||
build/repl.o: src/nasal.h src/repl.h src/repl.cpp | build
|
||||
$(CXX) -std=$(STD) -c -O3 src/repl.cpp -fno-exceptions -fPIC -o build/repl.o -I .
|
||||
|
||||
build/nasal_err.o: src/nasal.h src/nasal_err.h src/nasal_err.cpp | build
|
||||
$(CXX) -std=$(STD) -c -O3 src/nasal_err.cpp -fno-exceptions -fPIC -o build/nasal_err.o -I .
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nasal_codegen.h"
|
||||
#include "nasal_vm.h"
|
||||
#include "nasal_dbg.h"
|
||||
#include "repl.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
|
@ -53,6 +54,7 @@ std::ostream& help(std::ostream& out) {
|
|||
<< " --prof | show profiling result, available under debug mode.\n"
|
||||
<< " --prof-all | show profiling result of all files,"
|
||||
<< "available under debug mode.\n"
|
||||
<< " -r, --repl | use repl interpreter(experimental).\n"
|
||||
<< "file:\n"
|
||||
<< " <filename> | execute file.\n"
|
||||
<< "argv:\n"
|
||||
|
@ -129,9 +131,8 @@ void execute(
|
|||
ld.link(parse, file, cmd&VM_DETAIL).chkerr();
|
||||
|
||||
// optimizer does simple optimization on ast
|
||||
auto opt = new optimizer;
|
||||
auto opt = std::unique_ptr<optimizer>(new optimizer);
|
||||
opt->do_optimization(parse.tree());
|
||||
delete opt;
|
||||
if (cmd&VM_AST) {
|
||||
auto dumper = std::unique_ptr<ast_dumper>(new ast_dumper);
|
||||
dumper->dump(parse.tree());
|
||||
|
@ -178,6 +179,9 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
std::clog << help;
|
||||
} else if (s=="-v" || s=="--version") {
|
||||
std::clog << version;
|
||||
} else if (s=="-r" || s=="--repl") {
|
||||
auto repl_module = std::unique_ptr<repl::repl>(new repl::repl);
|
||||
repl_module->execute();
|
||||
} else if (s[0]!='-') {
|
||||
execute(s, {}, VM_EXEC);
|
||||
} else {
|
||||
|
|
|
@ -1144,7 +1144,7 @@ void codegen::ret_gen(return_expr* node) {
|
|||
gen(op_ret, 0, node->get_location());
|
||||
}
|
||||
|
||||
const error& codegen::compile(parse& parse, linker& import, bool repl) {
|
||||
const error& codegen::compile(parse& parse, linker& import) {
|
||||
init_native_function();
|
||||
init_file_map(import.get_file_list());
|
||||
|
||||
|
@ -1157,7 +1157,7 @@ const error& codegen::compile(parse& parse, linker& import, bool repl) {
|
|||
|
||||
// search global symbols first
|
||||
find_symbol(parse.tree());
|
||||
gen(op_intg, repl? STACK_DEPTH/2:global.size(), parse.tree()->get_location());
|
||||
gen(op_intg, global.size(), parse.tree()->get_location());
|
||||
|
||||
// generate main block
|
||||
block_gen(parse.tree());
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
public:
|
||||
codegen() = default;
|
||||
const error& compile(parse&, linker&, bool repl = false);
|
||||
const error& compile(parse&, linker&);
|
||||
void print(std::ostream&);
|
||||
void symbol_dump(std::ostream&) const;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
#include "repl.h"
|
||||
#include "nasal_lexer.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
#include "optimizer.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "nasal_vm.h"
|
||||
|
||||
namespace repl {
|
||||
|
||||
std::string repl::readline(std::string prompt = ">>> ") {
|
||||
auto line = std::string("");
|
||||
std::cout << prompt;
|
||||
std::getline(std::cin, line,'\n');
|
||||
return line;
|
||||
}
|
||||
|
||||
void repl::update_temp_file() {
|
||||
auto content = std::string("");
|
||||
for(const auto& i : source) {
|
||||
content += i + "\n";
|
||||
}
|
||||
|
||||
std::ofstream out(".temp.nas", std::ios::binary);
|
||||
out << content;
|
||||
}
|
||||
|
||||
bool repl::check_need_more_input() {
|
||||
while(true) {
|
||||
update_temp_file();
|
||||
auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
|
||||
if (nasal_lexer->scan(".temp.nas").geterr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
i64 in_curve = 0;
|
||||
i64 in_bracket = 0;
|
||||
i64 in_brace = 0;
|
||||
for(const auto& t : nasal_lexer->result()) {
|
||||
switch(t.type) {
|
||||
case tok::lcurve: ++in_curve; break;
|
||||
case tok::rcurve: --in_curve; break;
|
||||
case tok::lbracket: ++in_bracket; break;
|
||||
case tok::rbracket: --in_bracket; break;
|
||||
case tok::lbrace: ++in_brace; break;
|
||||
case tok::rbrace: --in_brace; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (!in_curve && !in_bracket && !in_brace) {
|
||||
break;
|
||||
}
|
||||
auto line = readline("... ");
|
||||
source.back() += "\n" + line;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void repl::help() {
|
||||
std::cout << ".h, .help | show help\n";
|
||||
std::cout << ".e, .exit | quit the REPL\n";
|
||||
std::cout << ".q, .quit | quit the REPL\n";
|
||||
std::cout << ".c, .clear | clear the screen\n";
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
bool repl::run() {
|
||||
update_temp_file();
|
||||
|
||||
auto nasal_lexer = std::unique_ptr<lexer>(new lexer);
|
||||
auto nasal_parser = std::unique_ptr<parse>(new parse);
|
||||
auto nasal_linker = std::unique_ptr<linker>(new linker);
|
||||
auto nasal_opt = std::unique_ptr<optimizer>(new optimizer);
|
||||
auto nasal_codegen = std::unique_ptr<codegen>(new codegen);
|
||||
auto nasal_runtime = std::unique_ptr<vm>(new vm);
|
||||
|
||||
if (nasal_lexer->scan(".temp.nas").geterr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nasal_parser->compile(*nasal_lexer).geterr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nasal_linker->link(*nasal_parser, ".temp.nas", true).geterr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nasal_opt->do_optimization(nasal_parser->tree());
|
||||
if (nasal_codegen->compile(*nasal_parser, *nasal_linker).geterr()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nasal_runtime->run(*nasal_codegen, *nasal_linker, {}, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void repl::execute() {
|
||||
source = {};
|
||||
std::cout << "Nasal REPL interpreter(experimental).\n";
|
||||
help();
|
||||
|
||||
while(true) {
|
||||
auto line = readline();
|
||||
if (!line.length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line == ".e" || line == ".exit" || line == ".q" || line == ".quit") {
|
||||
break;
|
||||
} else if (line == ".h" || line == ".help") {
|
||||
help();
|
||||
continue;
|
||||
} else if (line == ".c" || line == ".clear") {
|
||||
std::cout << "\033c";
|
||||
continue;
|
||||
} else if (line[0] == "."[0]) {
|
||||
std::cout << "no such command \"" << line;
|
||||
std::cout << "\", input \".help\" for help\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
source.push_back(line);
|
||||
if (!check_need_more_input()) {
|
||||
source.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!run()) {
|
||||
source.pop_back();
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "nasal.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace repl {
|
||||
|
||||
class repl {
|
||||
private:
|
||||
std::vector<std::string> source;
|
||||
|
||||
private:
|
||||
std::string readline(std::string);
|
||||
bool check_need_more_input();
|
||||
void update_temp_file();
|
||||
void help();
|
||||
bool run();
|
||||
|
||||
public:
|
||||
void execute();
|
||||
};
|
||||
|
||||
}
|
|
@ -31,6 +31,9 @@ var count_bracket = func(line) {
|
|||
|
||||
while(1) {
|
||||
var line = readline(">>> ");
|
||||
if (!size(line)) {
|
||||
continue;
|
||||
}
|
||||
if (line == ".exit" or line == ".quit") {
|
||||
break;
|
||||
} elsif (line == ".help") {
|
||||
|
|
Loading…
Reference in New Issue