🚀 switch build script to new nasal

This commit is contained in:
ValKmjolnir 2023-07-02 00:32:13 +08:00
parent 597c0388cb
commit a7a2f47d1e
12 changed files with 348 additions and 340 deletions

View File

@ -16,9 +16,9 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: make - name: make
run: | run: |
make make -j
cd module cd module
make all make all -j
cd .. cd ..
make test make test
tar -czf nasal-mac-nightly.tgz . tar -czf nasal-mac-nightly.tgz .
@ -42,9 +42,9 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: make - name: make
run: | run: |
make make -j
cd module cd module
make all make all -j
cd .. cd ..
make test make test
touch nasal-linux-x86_64-nightly.tgz touch nasal-linux-x86_64-nightly.tgz

View File

@ -4,7 +4,7 @@ project(nasal VERSION 10.1)
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}") message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
# -std=c++14 -Wshadow -Wall # -std=c++17 -Wshadow -Wall
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall") set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wshadow -Wall")
@ -14,24 +14,45 @@ set(CMAKE_BUILD_TYPE "Release")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp) add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_library(key SHARED ${CMAKE_SOURCE_DIR}/module/keyboard.cpp) add_library(key SHARED ${CMAKE_SOURCE_DIR}/module/keyboard.cpp)
target_include_directories(key PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(key PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_library(mat SHARED ${CMAKE_SOURCE_DIR}/module/matrix.cpp) add_library(mat SHARED ${CMAKE_SOURCE_DIR}/module/matrix.cpp)
target_include_directories(mat PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(mat PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp) add_library(nasock SHARED ${CMAKE_SOURCE_DIR}/module/nasocket.cpp)
target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}) target_include_directories(nasock PRIVATE ${CMAKE_SOURCE_DIR}/src)
add_executable(nasal main.cpp) set(NASAL_OBJECT_SOURCE_FILE
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_ast.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_builtin.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_codegen.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_dbg.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_err.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_gc.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_import.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_lexer.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_misc.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_opcode.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_parse.cpp
${CMAKE_SOURCE_DIR}/src/nasal_new_vm.cpp
${CMAKE_SOURCE_DIR}/src/optimizer.cpp
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp)
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/nasal_new_main.cpp)
add_library(nasal-object STATIC ${NASAL_OBJECT_SOURCE_FILE})
target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(nasal nasal-object)
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
target_link_libraries(nasal dl) target_link_libraries(nasal dl)
endif() endif()
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR})
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows") if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
add_custom_command( add_custom_command(

View File

@ -4,7 +4,7 @@
![GitHub code size](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github) ![GitHub code size](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github) ![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![in dev](https://img.shields.io/badge/dev-v10.1-blue?style=flat-square&logo=github) ![in dev](https://img.shields.io/badge/dev-v11.0-blue?style=flat-square&logo=github)
[![license](https://img.shields.io/badge/license-MIT-green?style=flat-square&logo=github)](./LICENSE) [![license](https://img.shields.io/badge/license-MIT-green?style=flat-square&logo=github)](./LICENSE)
> This document is also available in: [__中文__](./doc/README_zh.md) | [__English__](./README.md) > This document is also available in: [__中文__](./doc/README_zh.md) | [__English__](./README.md)

View File

@ -4,7 +4,7 @@
![GitHub code size](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github) ![GitHub code size](https://img.shields.io/github/languages/code-size/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github) ![GitHub release(latest by date)](https://img.shields.io/github/v/release/ValKmjolnir/Nasal-Interpreter?style=flat-square&logo=github)
![in dev](https://img.shields.io/badge/dev-v10.1-blue?style=flat-square&logo=github) ![in dev](https://img.shields.io/badge/dev-v11.0-blue?style=flat-square&logo=github)
[![license](https://img.shields.io/badge/license-MIT-green?style=flat-square&logo=github)](../LICENSE) [![license](https://img.shields.io/badge/license-MIT-green?style=flat-square&logo=github)](../LICENSE)
> 这篇文档包含多语言版本: [__中文__](../doc/README_zh.md) | [__English__](../README.md) > 这篇文档包含多语言版本: [__中文__](../doc/README_zh.md) | [__English__](../README.md)

154
makefile
View File

@ -1,79 +1,8 @@
.PHONY:test clean .PHONY:test clean
SRC=\
main.cpp\
nasal_ast.h\
nasal_err.h\
nasal_builtin.h\
nasal_opcode.h\
nasal_opt.h\
nasal_codegen.h\
nasal_gc.h\
nasal_import.h\
nasal_lexer.h\
nasal_parse.h\
nasal_vm.h\
nasal_dbg.h\
nasal.h
STD=c++17 STD=c++17
nasal:$(SRC) NASAL_OBJECT=\
$(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
stable-release:$(SRC)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall
stable-release-mingw:$(SRC)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal.exe -fno-exceptions -Wshadow -Wall -static
clean:
@ echo "[clean] nasal" && if [ -e nasal ]; then rm nasal; fi
@ echo "[clean] nasal.exe" && if [ -e nasal.exe ]; then rm nasal.exe; fi
test:nasal
@ ./nasal -e test/ascii-art.nas
@ ./nasal -t -d test/bfs.nas
@ ./nasal -t test/bigloop.nas
@ ./nasal -t test/bp.nas
@ ./nasal -d test/calc.nas
@ ./nasal -e test/choice.nas
@ ./nasal -e test/class.nas
@ ./nasal -t -d test/console3D.nas 20
@ ./nasal -e test/coroutine.nas
@ ./nasal -t -d test/datalog.nas
@ ./nasal -e test/diff.nas
@ ./nasal -e test/donuts.nas 15
-@ ./nasal -d test/exception.nas
@ ./nasal -t -d test/fib.nas
@ ./nasal -e test/filesystem.nas
@ ./nasal -d test/hexdump.nas
@ ./nasal -e test/json.nas
@ ./nasal -e test/leetcode1319.nas
@ ./nasal -d test/lexer.nas
@ ./nasal -d test/life.nas
@ ./nasal -t test/loop.nas
@ ./nasal -t test/mandelbrot.nas
@ ./nasal -t test/md5.nas
@ ./nasal -t -d test/md5compare.nas
@ ./nasal -d test/module_test.nas
@ ./nasal -e test/nasal_test.nas
@ ./nasal -t -d test/occupation.nas 2
@ ./nasal -t -d test/pi.nas
@ ./nasal -t -d test/prime.nas
@ ./nasal -e test/qrcode.nas
@ ./nasal -t -d test/quick_sort.nas
@ ./nasal -e test/scalar.nas hello world
@ ./nasal -e test/trait.nas
@ ./nasal -t -d test/turingmachine.nas
@ ./nasal -d test/wavecollapse.nas
@ ./nasal test/word_collector.nas test/md5compare.nas
@ ./nasal -t -d test/ycombinator.nas
NASAL_NEW_AST=\
nasal_new_err.o\ nasal_new_err.o\
nasal_new_ast.o\ nasal_new_ast.o\
ast_visitor.o\ ast_visitor.o\
@ -93,11 +22,11 @@ NASAL_NEW_AST=\
nasal_new_main.o nasal_new_main.o
# for test # for test
nnew: $(NASAL_NEW_AST) nasal: $(NASAL_OBJECT)
$(CXX) $(NASAL_NEW_AST) -O3 -o nnew -ldl $(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl
nnew.exe: $(NASAL_NEW_AST) nasal.exe: $(NASAL_OBJECT)
$(CXX) $(NASAL_NEW_AST) -O3 -o nnew.exe $(CXX) $(NASAL_OBJECT) -O3 -o nasal.exe
nasal_new_main.o: src/nasal_new_main.cpp nasal_new_main.o: src/nasal_new_main.cpp
$(CXX) -std=$(STD) -c -O3 src/nasal_new_main.cpp -fno-exceptions -fPIC -o nasal_new_main.o -I . $(CXX) -std=$(STD) -c -O3 src/nasal_new_main.cpp -fno-exceptions -fPIC -o nasal_new_main.o -I .
@ -152,4 +81,75 @@ nasal_new_dbg.o: src/nasal_new_dbg.h src/nasal_new_dbg.cpp
.PHONY: nasal_new_clean .PHONY: nasal_new_clean
nasal_new_clean: nasal_new_clean:
rm $(NASAL_NEW_AST) rm $(NASAL_OBJECT)
SRC=\
main.cpp\
nasal_ast.h\
nasal_err.h\
nasal_builtin.h\
nasal_opcode.h\
nasal_opt.h\
nasal_codegen.h\
nasal_gc.h\
nasal_import.h\
nasal_lexer.h\
nasal_parse.h\
nasal_vm.h\
nasal_dbg.h\
nasal.h
nasal_old:$(SRC)
$(CXX) -std=$(STD) -O3 main.cpp -o nasal_old -fno-exceptions -ldl -Wshadow -Wall
nasal_old.exe:$(SRC)
$(CXX) -std=$(STD) -O3 main.cpp -o nasal_old.exe -fno-exceptions -Wshadow -Wall -static
stable-release:$(SRC)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal_old -fno-exceptions -ldl -Wshadow -Wall
stable-release-mingw:$(SRC)
$(CXX) -std=$(STD) -O2 main.cpp -o nasal_old.exe -fno-exceptions -Wshadow -Wall -static
clean:
@ echo "[clean] nasal" && if [ -e nasal ]; then rm nasal; fi
@ echo "[clean] nasal.exe" && if [ -e nasal.exe ]; then rm nasal.exe; fi
test:nasal
@ ./nasal -e test/ascii-art.nas
@ ./nasal -t -d test/bfs.nas
@ ./nasal -t test/bigloop.nas
@ ./nasal -t test/bp.nas
@ ./nasal -d test/calc.nas
@ ./nasal -e test/choice.nas
@ ./nasal -e test/class.nas
@ ./nasal -t -d test/console3D.nas 20
@ ./nasal -e test/coroutine.nas
@ ./nasal -t -d test/datalog.nas
@ ./nasal -e test/diff.nas
@ ./nasal -e test/donuts.nas 15
-@ ./nasal -d test/exception.nas
@ ./nasal -t -d test/fib.nas
@ ./nasal -e test/filesystem.nas
@ ./nasal -d test/hexdump.nas
@ ./nasal -e test/json.nas
@ ./nasal -e test/leetcode1319.nas
@ ./nasal -d test/lexer.nas
@ ./nasal -d test/life.nas
@ ./nasal -t test/loop.nas
@ ./nasal -t test/mandelbrot.nas
@ ./nasal -t test/md5.nas
@ ./nasal -t -d test/md5compare.nas
@ ./nasal -d test/module_test.nas
@ ./nasal -e test/nasal_test.nas
@ ./nasal -t -d test/occupation.nas 2
@ ./nasal -t -d test/pi.nas
@ ./nasal -t -d test/prime.nas
@ ./nasal -e test/qrcode.nas
@ ./nasal -t -d test/quick_sort.nas
@ ./nasal -e test/scalar.nas hello world
@ ./nasal -e test/trait.nas
@ ./nasal -t -d test/turingmachine.nas
@ ./nasal -d test/wavecollapse.nas
@ ./nasal test/word_collector.nas test/md5compare.nas
@ ./nasal -t -d test/ycombinator.nas

View File

@ -3,7 +3,7 @@
dynamic_libs_so=libfib.so libkey.so libnasock.so libmat.so dynamic_libs_so=libfib.so libkey.so libnasock.so libmat.so
dynamic_libs_dll=libfib.dll libkey.dll libnasock.dll libmat.dll dynamic_libs_dll=libfib.dll libkey.dll libnasock.dll libmat.dll
used_header= ../nasal.h ../nasal_gc.h used_header= ../src/nasal_new_header.h ../src/nasal_new_gc.h
STD=c++17 STD=c++17

View File

@ -100,34 +100,34 @@ void codegen::gen(u8 operation_code, u32 num, u32 line) {
void codegen::num_gen(number_literal* node) { void codegen::num_gen(number_literal* node) {
f64 num = node->get_number(); f64 num = node->get_number();
regist_num(num); regist_num(num);
gen(op_pnum,num_table.at(num), node->get_location().begin_line); gen(op_pnum,num_table.at(num), node->get_line());
} }
void codegen::str_gen(string_literal* node) { void codegen::str_gen(string_literal* node) {
regist_str(node->get_content()); regist_str(node->get_content());
gen(op_pstr, str_table.at(node->get_content()), node->get_location().begin_line); gen(op_pstr, str_table.at(node->get_content()), node->get_line());
} }
void codegen::bool_gen(bool_literal* node) { void codegen::bool_gen(bool_literal* node) {
f64 num = node->get_flag()? 1:0; f64 num = node->get_flag()? 1:0;
regist_num(num); regist_num(num);
gen(op_pnum, num_table.at(num), node->get_location().begin_line); gen(op_pnum, num_table.at(num), node->get_line());
} }
void codegen::vec_gen(vector_expr* node) { void codegen::vec_gen(vector_expr* node) {
for(auto child : node->get_elements()) { for(auto child : node->get_elements()) {
calc_gen(child); calc_gen(child);
} }
gen(op_newv, node->get_elements().size(), node->get_location().begin_line); gen(op_newv, node->get_elements().size(), node->get_line());
} }
void codegen::hash_gen(hash_expr* node) { void codegen::hash_gen(hash_expr* node) {
gen(op_newh, 0, node->get_location().begin_line); gen(op_newh, 0, node->get_line());
for(auto child : node->get_members()) { for(auto child : node->get_members()) {
calc_gen(child->get_value()); calc_gen(child->get_value());
const auto& field_name = child->get_name(); const auto& field_name = child->get_name();
regist_str(field_name); regist_str(field_name);
gen(op_happ, str_table.at(field_name), child->get_location().begin_line); gen(op_happ, str_table.at(field_name), child->get_line());
} }
} }
@ -167,9 +167,9 @@ void codegen::func_gen(function* node) {
} }
usize newf=code.size(); usize newf=code.size();
gen(op_newf, 0, node->get_location().begin_line); gen(op_newf, 0, node->get_line());
usize lsize=code.size(); usize lsize=code.size();
gen(op_intl, 0, node->get_location().begin_line); gen(op_intl, 0, node->get_line());
// add special keyword 'me' into symbol table // add special keyword 'me' into symbol table
// this symbol is only used in local scope(function's scope) // this symbol is only used in local scope(function's scope)
@ -188,14 +188,14 @@ void codegen::func_gen(function* node) {
regist_str(name); regist_str(name);
switch(tmp->get_parameter_type()) { switch(tmp->get_parameter_type()) {
case parameter::param_type::normal_parameter: case parameter::param_type::normal_parameter:
gen(op_para, str_table.at(name), tmp->get_location().begin_line); gen(op_para, str_table.at(name), tmp->get_line());
break; break;
case parameter::param_type::default_parameter: case parameter::param_type::default_parameter:
calc_gen(tmp->get_default_value()); calc_gen(tmp->get_default_value());
gen(op_deft, str_table.at(name), tmp->get_location().begin_line); gen(op_deft, str_table.at(name), tmp->get_line());
break; break;
case parameter::param_type::dynamic_parameter: case parameter::param_type::dynamic_parameter:
gen(op_dyn, str_table.at(name), tmp->get_location().begin_line); gen(op_dyn, str_table.at(name), tmp->get_line());
break; break;
} }
add_sym(name); add_sym(name);
@ -203,7 +203,7 @@ void codegen::func_gen(function* node) {
code[newf].num = code.size()+1; // entry code[newf].num = code.size()+1; // entry
usize jmp_ptr = code.size(); usize jmp_ptr = code.size();
gen(op_jmp, 0, node->get_location().begin_line); gen(op_jmp, 0, node->get_line());
auto block = node->get_code_block(); auto block = node->get_code_block();
// search symbols first, must use after loading parameters // search symbols first, must use after loading parameters
@ -221,8 +221,8 @@ void codegen::func_gen(function* node) {
if (!block->get_expressions().size() || if (!block->get_expressions().size() ||
block->get_expressions().back()->get_type()!=expr_type::ast_ret) { block->get_expressions().back()->get_type()!=expr_type::ast_ret) {
gen(op_pnil, 0, block->get_location().begin_line); gen(op_pnil, 0, block->get_line());
gen(op_ret, 0, block->get_location().begin_line); gen(op_ret, 0, block->get_line());
} }
code[jmp_ptr].num = code.size(); code[jmp_ptr].num = code.size();
} }
@ -245,7 +245,7 @@ void codegen::call_id(identifier* node) {
const auto& name = node->get_name(); const auto& name = node->get_name();
for(u32 i = 0; builtin[i].name; ++i) { for(u32 i = 0; builtin[i].name; ++i) {
if (builtin[i].name==name) { if (builtin[i].name==name) {
gen(op_callb, i, node->get_location().begin_line); gen(op_callb, i, node->get_line());
if (local.empty()) { if (local.empty()) {
die("should warp native function in local scope", die("should warp native function in local scope",
node->get_location()); node->get_location());
@ -255,15 +255,15 @@ void codegen::call_id(identifier* node) {
} }
i32 index; i32 index;
if ((index=local_find(name))>=0) { if ((index=local_find(name))>=0) {
gen(op_calll, index, node->get_location().begin_line); gen(op_calll, index, node->get_line());
return; return;
} }
if ((index=upvalue_find(name))>=0) { if ((index=upvalue_find(name))>=0) {
gen(op_upval, index, node->get_location().begin_line); gen(op_upval, index, node->get_line());
return; return;
} }
if ((index=global_find(name))>=0) { if ((index=global_find(name))>=0) {
gen(op_callg, index, node->get_location().begin_line); gen(op_callg, index, node->get_line());
return; return;
} }
die("undefined symbol \"" + name + "\"", node->get_location()); die("undefined symbol \"" + name + "\"", node->get_location());
@ -271,7 +271,7 @@ void codegen::call_id(identifier* node) {
void codegen::call_hash_gen(call_hash* node) { void codegen::call_hash_gen(call_hash* node) {
regist_str(node->get_field()); regist_str(node->get_field());
gen(op_callh, str_table.at(node->get_field()), node->get_location().begin_line); gen(op_callh, str_table.at(node->get_field()), node->get_line());
} }
void codegen::call_vec(call_vector* node) { void codegen::call_vec(call_vector* node) {
@ -279,39 +279,39 @@ void codegen::call_vec(call_vector* node) {
if (node->get_slices().size()==1 && if (node->get_slices().size()==1 &&
!node->get_slices()[0]->get_end()) { !node->get_slices()[0]->get_end()) {
calc_gen(node->get_slices()[0]->get_begin()); calc_gen(node->get_slices()[0]->get_begin());
gen(op_callv, 0, node->get_slices()[0]->get_location().begin_line); gen(op_callv, 0, node->get_slices()[0]->get_line());
return; return;
} }
gen(op_slcbeg, 0, node->get_location().begin_line); gen(op_slcbeg, 0, node->get_line());
for(auto tmp : node->get_slices()) { for(auto tmp : node->get_slices()) {
if (!tmp->get_end()) { if (!tmp->get_end()) {
calc_gen(tmp->get_begin()); calc_gen(tmp->get_begin());
gen(op_slc, 0, tmp->get_location().begin_line); gen(op_slc, 0, tmp->get_line());
} else { } else {
calc_gen(tmp->get_begin()); calc_gen(tmp->get_begin());
calc_gen(tmp->get_end()); calc_gen(tmp->get_end());
gen(op_slc2, 0, tmp->get_location().begin_line); gen(op_slc2, 0, tmp->get_line());
} }
} }
gen(op_slcend, 0, node->get_location().begin_line); gen(op_slcend, 0, node->get_line());
} }
void codegen::call_func(call_function* node) { void codegen::call_func(call_function* node) {
if (node->get_argument().size() && if (node->get_argument().size() &&
node->get_argument()[0]->get_type()==expr_type::ast_pair) { node->get_argument()[0]->get_type()==expr_type::ast_pair) {
gen(op_newh, 0, node->get_location().begin_line); gen(op_newh, 0, node->get_line());
for(auto child : node->get_argument()) { for(auto child : node->get_argument()) {
calc_gen(((hash_pair*)child)->get_value()); calc_gen(((hash_pair*)child)->get_value());
const auto& field_name = ((hash_pair*)child)->get_name(); const auto& field_name = ((hash_pair*)child)->get_name();
regist_str(field_name); regist_str(field_name);
gen(op_happ, str_table.at(field_name), child->get_location().begin_line); gen(op_happ, str_table.at(field_name), child->get_line());
} }
gen(op_callfh, 0, node->get_location().begin_line); gen(op_callfh, 0, node->get_line());
} else { } else {
for(auto child : node->get_argument()) { for(auto child : node->get_argument()) {
calc_gen(child); calc_gen(child);
} }
gen(op_callfv, node->get_argument().size(), node->get_location().begin_line); gen(op_callfv, node->get_argument().size(), node->get_line());
} }
} }
@ -365,15 +365,15 @@ void codegen::mcall_id(identifier* node) {
} }
i32 index; i32 index;
if ((index=local_find(name))>=0) { if ((index=local_find(name))>=0) {
gen(op_mcalll, index, node->get_location().begin_line); gen(op_mcalll, index, node->get_line());
return; return;
} }
if ((index=upvalue_find(name))>=0) { if ((index=upvalue_find(name))>=0) {
gen(op_mupval, index, node->get_location().begin_line); gen(op_mupval, index, node->get_line());
return; return;
} }
if ((index=global_find(name))>=0) { if ((index=global_find(name))>=0) {
gen(op_mcallg, index, node->get_location().begin_line); gen(op_mcallg, index, node->get_line());
return; return;
} }
die("undefined symbol \"" + name + "\"", node->get_location()); die("undefined symbol \"" + name + "\"", node->get_location());
@ -390,20 +390,20 @@ void codegen::mcall_vec(call_vector* node) {
return; return;
} }
calc_gen(call->get_begin()); calc_gen(call->get_begin());
gen(op_mcallv, 0, node->get_location().begin_line); gen(op_mcallv, 0, node->get_line());
} }
void codegen::mcall_hash(call_hash* node) { void codegen::mcall_hash(call_hash* node) {
regist_str(node->get_field()); regist_str(node->get_field());
gen(op_mcallh, str_table.at(node->get_field()), node->get_location().begin_line); gen(op_mcallh, str_table.at(node->get_field()), node->get_line());
} }
void codegen::single_def(definition_expr* node) { void codegen::single_def(definition_expr* node) {
const auto& str = node->get_variable_name()->get_name(); const auto& str = node->get_variable_name()->get_name();
calc_gen(node->get_value()); calc_gen(node->get_value());
local.empty()? local.empty()?
gen(op_loadg, global_find(str), node->get_location().begin_line): gen(op_loadg, global_find(str), node->get_line()):
gen(op_loadl, local_find(str), node->get_location().begin_line); gen(op_loadl, local_find(str), node->get_line());
} }
void codegen::multi_def(definition_expr* node) { void codegen::multi_def(definition_expr* node) {
@ -420,19 +420,19 @@ void codegen::multi_def(definition_expr* node) {
calc_gen(vals[i]); calc_gen(vals[i]);
const auto& name = identifiers[i]->get_name(); const auto& name = identifiers[i]->get_name();
local.empty()? local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_location().begin_line): gen(op_loadg, global_find(name), identifiers[i]->get_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_location().begin_line); gen(op_loadl, local_find(name), identifiers[i]->get_line());
} }
} else { // (var a,b,c)=[0,1,2]; } else { // (var a,b,c)=[0,1,2];
calc_gen(node->get_value()); calc_gen(node->get_value());
for(usize i = 0; i<size; ++i) { for(usize i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_location().begin_line); gen(op_callvi, i, node->get_value()->get_line());
const auto& name = identifiers[i]->get_name(); const auto& name = identifiers[i]->get_name();
local.empty()? local.empty()?
gen(op_loadg, global_find(name), identifiers[i]->get_location().begin_line): gen(op_loadg, global_find(name), identifiers[i]->get_line()):
gen(op_loadl, local_find(name), identifiers[i]->get_location().begin_line); gen(op_loadl, local_find(name), identifiers[i]->get_line());
} }
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
} }
} }
@ -449,7 +449,7 @@ void codegen::assignment_gen(assignment_expr* node) {
case assignment_expr::assign_type::equal: case assignment_expr::assign_type::equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_meq, 0, node->get_location().begin_line); gen(op_meq, 0, node->get_line());
break; break;
case assignment_expr::assign_type::add_equal: case assignment_expr::assign_type::add_equal:
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
@ -457,11 +457,11 @@ void codegen::assignment_gen(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_addeq, 0, node->get_location().begin_line); gen(op_addeq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_addeqc, num_table[num], node->get_location().begin_line); gen(op_addeqc, num_table[num], node->get_line());
} }
break; break;
case assignment_expr::assign_type::sub_equal: case assignment_expr::assign_type::sub_equal:
@ -470,11 +470,11 @@ void codegen::assignment_gen(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_subeq, 0, node->get_location().begin_line); gen(op_subeq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_subeqc, num_table[num], node->get_location().begin_line); gen(op_subeqc, num_table[num], node->get_line());
} }
break; break;
case assignment_expr::assign_type::mult_equal: case assignment_expr::assign_type::mult_equal:
@ -483,11 +483,11 @@ void codegen::assignment_gen(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_muleq, 0, node->get_location().begin_line); gen(op_muleq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_muleqc, num_table[num], node->get_location().begin_line); gen(op_muleqc, num_table[num], node->get_line());
} }
break; break;
case assignment_expr::assign_type::div_equal: case assignment_expr::assign_type::div_equal:
@ -496,11 +496,11 @@ void codegen::assignment_gen(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
gen(op_diveq, 0, node->get_location().begin_line); gen(op_diveq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_diveqc, num_table[num], node->get_location().begin_line); gen(op_diveqc, num_table[num], node->get_line());
} }
break; break;
case assignment_expr::assign_type::concat_equal: case assignment_expr::assign_type::concat_equal:
@ -509,27 +509,27 @@ void codegen::assignment_gen(assignment_expr* node) {
} }
mcall(node->get_left()); mcall(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) { if (node->get_right()->get_type()!=expr_type::ast_str) {
gen(op_lnkeq, 0, node->get_location().begin_line); gen(op_lnkeq, 0, node->get_line());
} else { } else {
const auto& str = ((string_literal*)node->get_right())->get_content(); const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str); regist_str(str);
gen(op_lnkeqc, str_table[str], node->get_location().begin_line); gen(op_lnkeqc, str_table[str], node->get_line());
} }
break; break;
case assignment_expr::assign_type::bitwise_and_equal: case assignment_expr::assign_type::bitwise_and_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btandeq, 0, node->get_location().begin_line); gen(op_btandeq, 0, node->get_line());
break; break;
case assignment_expr::assign_type::bitwise_or_equal: case assignment_expr::assign_type::bitwise_or_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btoreq, 0, node->get_location().begin_line); gen(op_btoreq, 0, node->get_line());
break; break;
case assignment_expr::assign_type::bitwise_xor_equal: case assignment_expr::assign_type::bitwise_xor_equal:
calc_gen(node->get_right()); calc_gen(node->get_right());
mcall(node->get_left()); mcall(node->get_left());
gen(op_btxoreq, 0, node->get_location().begin_line); gen(op_btxoreq, 0, node->get_line());
break; break;
} }
} }
@ -553,7 +553,7 @@ void codegen::assign_statement(assignment_expr* node) {
if (code.back().op==op_meq) { if (code.back().op==op_meq) {
code.back().num=1; code.back().num=1;
} else { } else {
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
} }
} }
break; break;
@ -571,7 +571,7 @@ void codegen::assign_statement(assignment_expr* node) {
} else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) { } else if (op_addeqc<=code.back().op && code.back().op<=op_lnkeqc) {
code.back().op=code.back().op-op_addeqc+op_addecp; code.back().op=code.back().op-op_addeqc+op_addecp;
} else { } else {
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
} }
break; break;
} }
@ -602,14 +602,14 @@ void codegen::multi_assign_gen(multi_assign* node) {
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op=op_loadg;
} else { } else {
gen(op_meq, 1, tuple[i]->get_location().begin_line); gen(op_meq, 1, tuple[i]->get_line());
} }
} }
} else { } else {
calc_gen(node->get_value()); calc_gen(node->get_value());
auto& tuple = node->get_tuple()->get_elements(); auto& tuple = node->get_tuple()->get_elements();
for(i32 i = 0; i<size; ++i) { for(i32 i = 0; i<size; ++i) {
gen(op_callvi, i, node->get_value()->get_location().begin_line); gen(op_callvi, i, node->get_value()->get_line());
// multi assign user loadl and loadg to avoid meq's stack-- // multi assign user loadl and loadg to avoid meq's stack--
// and this operation changes local and global value directly // and this operation changes local and global value directly
mcall(tuple[i]); mcall(tuple[i]);
@ -620,10 +620,10 @@ void codegen::multi_assign_gen(multi_assign* node) {
} else if (code.back().op==op_mcallg) { } else if (code.back().op==op_mcallg) {
code.back().op=op_loadg; code.back().op=op_loadg;
} else { } else {
gen(op_meq, 1, tuple[i]->get_location().begin_line); gen(op_meq, 1, tuple[i]->get_line());
} }
} }
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
} }
} }
@ -631,25 +631,25 @@ void codegen::cond_gen(condition_expr* node) {
std::vector<usize> jmp_label; std::vector<usize> jmp_label;
calc_gen(node->get_if_statement()->get_condition()); calc_gen(node->get_if_statement()->get_condition());
auto ptr = code.size(); auto ptr = code.size();
gen(op_jf, 0, node->get_if_statement()->get_location().begin_line); gen(op_jf, 0, node->get_if_statement()->get_line());
block_gen(node->get_if_statement()->get_code_block()); block_gen(node->get_if_statement()->get_code_block());
if (node->get_elsif_stataments().size() || if (node->get_elsif_stataments().size() ||
node->get_else_statement()) { node->get_else_statement()) {
jmp_label.push_back(code.size()); jmp_label.push_back(code.size());
gen(op_jmp, 0, node->get_if_statement()->get_location().begin_line); gen(op_jmp, 0, node->get_if_statement()->get_line());
} }
code[ptr].num = code.size(); code[ptr].num = code.size();
for(auto tmp : node->get_elsif_stataments()) { for(auto tmp : node->get_elsif_stataments()) {
calc_gen(tmp->get_condition()); calc_gen(tmp->get_condition());
ptr = code.size(); ptr = code.size();
gen(op_jf, 0, tmp->get_location().begin_line); gen(op_jf, 0, tmp->get_line());
block_gen(tmp->get_code_block()); block_gen(tmp->get_code_block());
// the last condition doesn't need to jmp // the last condition doesn't need to jmp
if (tmp!=node->get_elsif_stataments().back() || if (tmp!=node->get_elsif_stataments().back() ||
node->get_else_statement()) { node->get_else_statement()) {
jmp_label.push_back(code.size()); jmp_label.push_back(code.size());
gen(op_jmp, 0, tmp->get_location().begin_line); gen(op_jmp, 0, tmp->get_line());
} }
code[ptr].num=code.size(); code[ptr].num=code.size();
} }
@ -671,13 +671,7 @@ void codegen::loop_gen(expr* node) {
case expr_type::ast_for: case expr_type::ast_for:
for_gen((for_expr*)node); break; for_gen((for_expr*)node); break;
case expr_type::ast_forei: case expr_type::ast_forei:
if (((forei_expr*)node)->get_loop_type()== forei_gen((forei_expr*)node); break;
forei_expr::forei_loop_type::forindex) {
forindex_gen((forei_expr*)node);
} else {
foreach_gen((forei_expr*)node);
}
break;
} }
} }
@ -696,10 +690,10 @@ void codegen::while_gen(while_expr* node) {
usize loop_ptr = code.size(); usize loop_ptr = code.size();
calc_gen(node->get_condition()); calc_gen(node->get_condition());
usize condition_ptr = code.size(); usize condition_ptr = code.size();
gen(op_jf, 0, node->get_condition()->get_location().begin_line); gen(op_jf, 0, node->get_condition()->get_line());
block_gen(node->get_code_block()); block_gen(node->get_code_block());
gen(op_jmp, loop_ptr, node->get_code_block()->get_location().begin_line); gen(op_jmp, loop_ptr, node->get_code_block()->get_line());
code[condition_ptr].num = code.size(); code[condition_ptr].num = code.size();
load_continue_break(code.size()-1, code.size()); load_continue_break(code.size()-1, code.size());
} }
@ -709,22 +703,58 @@ void codegen::for_gen(for_expr* node) {
usize jmp_place = code.size(); usize jmp_place = code.size();
if (node->get_condition()->get_type()==expr_type::ast_null) { if (node->get_condition()->get_type()==expr_type::ast_null) {
regist_num(1); regist_num(1);
gen(op_pnum, num_table.at(1), node->get_condition()->get_location().begin_line); gen(op_pnum, num_table.at(1), node->get_condition()->get_line());
} else { } else {
calc_gen(node->get_condition()); calc_gen(node->get_condition());
} }
usize label_exit = code.size(); usize label_exit = code.size();
gen(op_jf, 0, node->get_condition()->get_location().begin_line); gen(op_jf, 0, node->get_condition()->get_line());
block_gen(node->get_code_block()); block_gen(node->get_code_block());
usize continue_place = code.size(); usize continue_place = code.size();
expr_gen(node->get_step()); expr_gen(node->get_step());
gen(op_jmp, jmp_place, node->get_step()->get_location().begin_line); gen(op_jmp, jmp_place, node->get_step()->get_line());
code[label_exit].num = code.size(); code[label_exit].num = code.size();
load_continue_break(continue_place, code.size()); load_continue_break(continue_place, code.size());
} }
void codegen::forei_gen(forei_expr* node) {
calc_gen(node->get_value());
gen(op_cnt, 0, node->get_value()->get_line());
usize ptr = code.size();
if (node->get_loop_type()==forei_expr::forei_loop_type::forindex) {
gen(op_findex, 0, node->get_line());
} else {
gen(op_feach, 0, node->get_line());
}
if (node->get_iterator()->get_name()) { // define a new iterator
const auto& str = node->get_iterator()->get_name()->get_name();
local.empty()?
gen(op_loadg, global_find(str), node->get_iterator()->get_name()->get_line()):
gen(op_loadl, local_find(str), node->get_iterator()->get_name()->get_line());
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} else if (code.back().op==op_mcalll) {
code.back().op=op_loadl;
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq, 1, node->get_iterator()->get_line());
}
}
++in_iterloop.top();
block_gen(node->get_code_block());
--in_iterloop.top();
gen(op_jmp, ptr, node->get_line());
code[ptr].num=code.size();
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node->get_value()->get_line());// pop vector
gen(op_pop, 0, node->get_line());// pop iterator
}
void codegen::expr_gen(expr* node) { void codegen::expr_gen(expr* node) {
switch(node->get_type()) { switch(node->get_type()) {
case expr_type::ast_null:break; case expr_type::ast_null:break;
@ -735,112 +765,48 @@ void codegen::expr_gen(expr* node) {
case expr_type::ast_assign: case expr_type::ast_assign:
assign_statement((assignment_expr*)node); break; assign_statement((assignment_expr*)node); break;
case expr_type::ast_nil:case expr_type::ast_num: case expr_type::ast_nil:case expr_type::ast_num:
case expr_type::ast_str:case expr_type::ast_bool:break; case expr_type::ast_str:case expr_type::ast_bool: break;
case expr_type::ast_vec:case expr_type::ast_hash: case expr_type::ast_vec:case expr_type::ast_hash:
case expr_type::ast_func:case expr_type::ast_call: case expr_type::ast_func:case expr_type::ast_call:
case expr_type::ast_unary: case expr_type::ast_unary:
case expr_type::ast_binary: case expr_type::ast_binary:
case expr_type::ast_ternary: case expr_type::ast_ternary:
calc_gen(node); calc_gen(node);
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
break; break;
} }
} }
void codegen::forindex_gen(forei_expr* node) {
calc_gen(node->get_value());
gen(op_cnt, 0, node->get_value()->get_location().begin_line);
usize ptr = code.size();
gen(op_findex, 0, node->get_location().begin_line);
if (node->get_iterator()->get_name()) { // define a new iterator
const auto& str = node->get_iterator()->get_name()->get_name();
local.empty()?
gen(op_loadg, global_find(str), node->get_iterator()->get_name()->get_location().begin_line):
gen(op_loadl, local_find(str), node->get_iterator()->get_name()->get_location().begin_line);
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} else if (code.back().op==op_mcalll) {
code.back().op=op_loadl;
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq, 1, node->get_iterator()->get_location().begin_line);
}
}
++in_iterloop.top();
block_gen(node->get_code_block());
--in_iterloop.top();
gen(op_jmp, ptr, node->get_location().begin_line);
code[ptr].num=code.size();
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node->get_value()->get_location().begin_line);// pop vector
gen(op_pop, 0, node->get_location().begin_line);// pop iterator
}
void codegen::foreach_gen(forei_expr* node) {
calc_gen(node->get_value());
gen(op_cnt, 0, node->get_location().begin_line);
usize ptr = code.size();
gen(op_feach, 0, node->get_location().begin_line);
if (node->get_iterator()->get_name()) { // define a new iterator
const auto& str = node->get_iterator()->get_name()->get_name();
local.empty()?
gen(op_loadg, global_find(str), node->get_iterator()->get_name()->get_location().begin_line):
gen(op_loadl, local_find(str), node->get_iterator()->get_name()->get_location().begin_line);
} else { // use exist variable as the iterator
mcall(node->get_iterator()->get_call());
if (code.back().op==op_mcallg) {
code.back().op=op_loadg;
} else if (code.back().op==op_mcalll) {
code.back().op=op_loadl;
} else if (code.back().op==op_mupval) {
code.back().op=op_loadu;
} else {
gen(op_meq, 1, node->get_iterator()->get_location().begin_line);
}
}
++in_iterloop.top();
block_gen(node->get_code_block());
--in_iterloop.top();
gen(op_jmp, ptr, node->get_location().begin_line);
code[ptr].num=code.size();
load_continue_break(code.size()-1, code.size());
gen(op_pop, 0, node->get_value()->get_location().begin_line); // pop vector
gen(op_pop, 0, node->get_location().begin_line); // pop iterator
}
void codegen::or_gen(binary_operator* node) { void codegen::or_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
usize l1 = code.size(); usize l1 = code.size();
gen(op_jt, 0, node->get_left()->get_location().begin_line); gen(op_jt, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_left()->get_location().begin_line); gen(op_pop, 0, node->get_left()->get_line());
calc_gen(node->get_right()); calc_gen(node->get_right());
usize l2=code.size(); usize l2=code.size();
gen(op_jt, 0, node->get_right()->get_location().begin_line); gen(op_jt, 0, node->get_right()->get_line());
gen(op_pop, 0, node->get_right()->get_location().begin_line); gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_location().begin_line); gen(op_pnil, 0, node->get_right()->get_line());
code[l1].num = code[l2].num = code.size(); code[l1].num = code[l2].num = code.size();
} }
void codegen::and_gen(binary_operator* node) { void codegen::and_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
gen(op_jt, code.size()+2, node->get_left()->get_location().begin_line); gen(op_jt, code.size()+2, node->get_left()->get_line());
usize lfalse = code.size(); usize lfalse = code.size();
gen(op_jmp, 0, node->get_left()->get_location().begin_line); gen(op_jmp, 0, node->get_left()->get_line());
gen(op_pop, 0, node->get_right()->get_location().begin_line);// jt jumps here gen(op_pop, 0, node->get_right()->get_line());// jt jumps here
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_jt, code.size()+3, node->get_right()->get_location().begin_line); gen(op_jt, code.size()+3, node->get_right()->get_line());
code[lfalse].num = code.size(); code[lfalse].num = code.size();
gen(op_pop, 0, node->get_right()->get_location().begin_line); gen(op_pop, 0, node->get_right()->get_line());
gen(op_pnil, 0, node->get_right()->get_location().begin_line); gen(op_pnil, 0, node->get_right()->get_line());
// jt jumps here // jt jumps here
} }
@ -848,11 +814,11 @@ void codegen::unary_gen(unary_operator* node) {
calc_gen(node->get_value()); calc_gen(node->get_value());
switch(node->get_operator_type()) { switch(node->get_operator_type()) {
case unary_operator::unary_type::negative: case unary_operator::unary_type::negative:
gen(op_usub, 0, node->get_location().begin_line); break; gen(op_usub, 0, node->get_line()); break;
case unary_operator::unary_type::logical_not: case unary_operator::unary_type::logical_not:
gen(op_lnot, 0, node->get_location().begin_line); break; gen(op_lnot, 0, node->get_line()); break;
case unary_operator::unary_type::bitwise_not: case unary_operator::unary_type::bitwise_not:
gen(op_bnot, 0, node->get_location().begin_line); break; gen(op_bnot, 0, node->get_line()); break;
} }
} }
@ -866,27 +832,27 @@ void codegen::binary_gen(binary_operator* node) {
case binary_operator::binary_type::cmpeq: case binary_operator::binary_type::cmpeq:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_eq, 0, node->get_location().begin_line); gen(op_eq, 0, node->get_line());
return; return;
case binary_operator::binary_type::cmpneq: case binary_operator::binary_type::cmpneq:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_neq, 0, node->get_location().begin_line); gen(op_neq, 0, node->get_line());
return; return;
case binary_operator::binary_type::bitwise_or: case binary_operator::binary_type::bitwise_or:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btor, 0, node->get_location().begin_line); gen(op_btor, 0, node->get_line());
return; return;
case binary_operator::binary_type::bitwise_xor: case binary_operator::binary_type::bitwise_xor:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btxor, 0, node->get_location().begin_line); gen(op_btxor, 0, node->get_line());
return; return;
case binary_operator::binary_type::bitwise_and: case binary_operator::binary_type::bitwise_and:
calc_gen(node->get_left()); calc_gen(node->get_left());
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_btand, 0, node->get_location().begin_line); gen(op_btand, 0, node->get_line());
return; return;
default: break; default: break;
} }
@ -895,99 +861,99 @@ void codegen::binary_gen(binary_operator* node) {
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_add, 0, node->get_location().begin_line); gen(op_add, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_addc, num_table.at(num), node->get_location().begin_line); gen(op_addc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::sub: case binary_operator::binary_type::sub:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_sub, 0, node->get_location().begin_line); gen(op_sub, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_subc, num_table.at(num), node->get_location().begin_line); gen(op_subc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::mult: case binary_operator::binary_type::mult:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_mul, 0, node->get_location().begin_line); gen(op_mul, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_mulc, num_table.at(num), node->get_location().begin_line); gen(op_mulc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::div: case binary_operator::binary_type::div:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_div, 0, node->get_location().begin_line); gen(op_div, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_divc, num_table.at(num), node->get_location().begin_line); gen(op_divc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::concat: case binary_operator::binary_type::concat:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_str) { if (node->get_right()->get_type()!=expr_type::ast_str) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_lnk, 0, node->get_location().begin_line); gen(op_lnk, 0, node->get_line());
} else { } else {
const auto& str = ((string_literal*)node->get_right())->get_content(); const auto& str = ((string_literal*)node->get_right())->get_content();
regist_str(str); regist_str(str);
gen(op_lnkc, str_table.at(str), node->get_location().begin_line); gen(op_lnkc, str_table.at(str), node->get_line());
} }
break; break;
case binary_operator::binary_type::less: case binary_operator::binary_type::less:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_less, 0, node->get_location().begin_line); gen(op_less, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_lessc, num_table.at(num), node->get_location().begin_line); gen(op_lessc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::leq: case binary_operator::binary_type::leq:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_leq, 0, node->get_location().begin_line); gen(op_leq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_leqc, num_table.at(num), node->get_location().begin_line); gen(op_leqc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::grt: case binary_operator::binary_type::grt:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_grt, 0, node->get_location().begin_line); gen(op_grt, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_grtc, num_table.at(num), node->get_location().begin_line); gen(op_grtc, num_table.at(num), node->get_line());
} }
return; return;
case binary_operator::binary_type::geq: case binary_operator::binary_type::geq:
calc_gen(node->get_left()); calc_gen(node->get_left());
if (node->get_right()->get_type()!=expr_type::ast_num) { if (node->get_right()->get_type()!=expr_type::ast_num) {
calc_gen(node->get_right()); calc_gen(node->get_right());
gen(op_geq, 0, node->get_location().begin_line); gen(op_geq, 0, node->get_line());
} else { } else {
auto num = ((number_literal*)node->get_right())->get_number(); auto num = ((number_literal*)node->get_right())->get_number();
regist_num(num); regist_num(num);
gen(op_geqc, num_table.at(num), node->get_location().begin_line); gen(op_geqc, num_table.at(num), node->get_line());
} }
return; return;
} }
@ -996,10 +962,10 @@ void codegen::binary_gen(binary_operator* node) {
void codegen::trino_gen(ternary_operator* node) { void codegen::trino_gen(ternary_operator* node) {
calc_gen(node->get_condition()); calc_gen(node->get_condition());
usize lfalse = code.size(); usize lfalse = code.size();
gen(op_jf, 0, node->get_condition()->get_location().begin_line); gen(op_jf, 0, node->get_condition()->get_line());
calc_gen(node->get_left()); calc_gen(node->get_left());
usize lexit = code.size(); usize lexit = code.size();
gen(op_jmp, 0, node->get_left()->get_location().begin_line); gen(op_jmp, 0, node->get_left()->get_line());
code[lfalse].num = code.size(); code[lfalse].num = code.size();
calc_gen(node->get_right()); calc_gen(node->get_right());
code[lexit].num = code.size(); code[lexit].num = code.size();
@ -1008,7 +974,7 @@ void codegen::trino_gen(ternary_operator* node) {
void codegen::calc_gen(expr* node) { void codegen::calc_gen(expr* node) {
switch(node->get_type()) { switch(node->get_type()) {
case expr_type::ast_nil: case expr_type::ast_nil:
gen(op_pnil, 0, node->get_location().begin_line); break; gen(op_pnil, 0, node->get_line()); break;
case expr_type::ast_num: case expr_type::ast_num:
num_gen((number_literal*)node); break; num_gen((number_literal*)node); break;
case expr_type::ast_str: case expr_type::ast_str:
@ -1050,16 +1016,17 @@ void codegen::block_gen(code_block* node) {
case expr_type::ast_nil:case expr_type::ast_num: case expr_type::ast_nil:case expr_type::ast_num:
case expr_type::ast_str:case expr_type::ast_bool:break; case expr_type::ast_str:case expr_type::ast_bool:break;
case expr_type::ast_file_info: case expr_type::ast_file_info:
fileindex = ((file_info*)tmp)->get_index(); break; // special node type in main block // special node type in main block
fileindex = ((file_info*)tmp)->get_index(); break;
case expr_type::ast_cond: case expr_type::ast_cond:
cond_gen((condition_expr*)tmp); break; cond_gen((condition_expr*)tmp); break;
case expr_type::ast_continue: case expr_type::ast_continue:
continue_ptr.front().push_back(code.size()); continue_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_location().begin_line); gen(op_jmp, 0, tmp->get_line());
break; break;
case expr_type::ast_break: case expr_type::ast_break:
break_ptr.front().push_back(code.size()); break_ptr.front().push_back(code.size());
gen(op_jmp, 0, tmp->get_location().begin_line); gen(op_jmp, 0, tmp->get_line());
break; break;
case expr_type::ast_while: case expr_type::ast_while:
case expr_type::ast_for: case expr_type::ast_for:
@ -1082,11 +1049,11 @@ void codegen::block_gen(code_block* node) {
void codegen::ret_gen(return_expr* node) { void codegen::ret_gen(return_expr* node) {
for(u32 i = 0; i<in_iterloop.top(); ++i) { for(u32 i = 0; i<in_iterloop.top(); ++i) {
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
gen(op_pop, 0, node->get_location().begin_line); gen(op_pop, 0, node->get_line());
} }
calc_gen(node->get_value()); calc_gen(node->get_value());
gen(op_ret, 0, node->get_location().begin_line); gen(op_ret, 0, node->get_line());
} }
const error& codegen::compile(parse& parse, linker& import) { const error& codegen::compile(parse& parse, linker& import) {
@ -1101,19 +1068,23 @@ const error& codegen::compile(parse& parse, linker& import) {
// size out of bound check // size out of bound check
if (num_res.size()>0xffffff) { if (num_res.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code", "too many constant numbers: "+std::to_string(num_res.size())); err.err("code",
"too many constant numbers: " + std::to_string(num_res.size()));
} }
if (str_res.size()>0xffffff) { if (str_res.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code", "too many constant strings: "+std::to_string(str_res.size())); err.err("code",
"too many constant strings: " + std::to_string(str_res.size()));
} }
if (global.size()>=STACK_DEPTH) { if (global.size()>=STACK_DEPTH) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code", "too many global variants: "+std::to_string(global.size())); err.err("code",
"too many global variants: " + std::to_string(global.size()));
} }
if (code.size()>0xffffff) { if (code.size()>0xffffff) {
err.load(file[0]); // load main execute file err.load(file[0]); // load main execute file
err.err("code", "bytecode size overflow: "+std::to_string(code.size())); err.err("code",
"bytecode size overflow: " + std::to_string(code.size()));
} }
return err; return err;
} }
@ -1125,12 +1096,12 @@ void codegen::print() {
// print const numbers // print const numbers
for(auto num : num_res) { for(auto num : num_res) {
std::cout<<" .number "<<num<<"\n"; std::cout << " .number " << num << "\n";
} }
// print const strings // print const strings
for(const auto& str : str_res) { for(const auto& str : str_res) {
std::cout<<" .symbol \""<<rawstr(str)<<"\"\n"; std::cout << " .symbol \"" << rawstr(str) << "\"\n";
} }
// print code // print code
@ -1140,7 +1111,7 @@ void codegen::print() {
// print opcode index, opcode name, opcode immediate number // print opcode index, opcode name, opcode immediate number
const auto& c = code[i]; const auto& c = code[i];
if (!festk.empty() && i==festk.top()) { if (!festk.empty() && i==festk.top()) {
std::cout<<std::hex<<"<0x"<<fbstk.top()<<std::dec<<">;\n"; std::cout << std::hex << "<0x" << fbstk.top() << std::dec << ">;\n";
// avoid two empty lines // avoid two empty lines
if (c.op!=op_newf) { if (c.op!=op_newf) {
std::cout<<"\n"; std::cout<<"\n";
@ -1151,7 +1122,7 @@ void codegen::print() {
// get function begin index and end index // get function begin index and end index
if (c.op==op_newf) { if (c.op==op_newf) {
std::cout<<std::hex<<"\nfunc <0x"<<i<<std::dec<<">:\n"; std::cout << std::hex << "\nfunc <0x" << i << std::dec << ">:\n";
for(u32 j = i; j<code.size(); ++j) { for(u32 j = i; j<code.size(); ++j) {
if (code[j].op==op_jmp) { if (code[j].op==op_jmp) {
fbstk.push(i); fbstk.push(i);
@ -1162,6 +1133,6 @@ void codegen::print() {
} }
// output bytecode // output bytecode
std::cout<<" "<<codestream(c,i)<<"\n"; std::cout << " " << codestream(c,i) << "\n";
} }
} }

View File

@ -83,8 +83,7 @@ private:
void while_gen(while_expr*); void while_gen(while_expr*);
void for_gen(for_expr*); void for_gen(for_expr*);
void expr_gen(expr*); void expr_gen(expr*);
void forindex_gen(forei_expr*); void forei_gen(forei_expr*);
void foreach_gen(forei_expr*);
void or_gen(binary_operator*); void or_gen(binary_operator*);
void and_gen(binary_operator*); void and_gen(binary_operator*);
void unary_gen(unary_operator*); void unary_gen(unary_operator*);

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#ifndef __nasver #ifndef __nasver
#define __nasver "10.1" #define __nasver "11.0"
#endif #endif
#include <cstdint> #include <cstdint>

View File

@ -14,6 +14,7 @@
#include <unordered_map> #include <unordered_map>
#include <thread> #include <thread>
#include <cstdlib>
const u32 VM_RAW_AST = 1; const u32 VM_RAW_AST = 1;
const u32 VM_AST = 1<<1; const u32 VM_AST = 1<<1;
@ -25,53 +26,67 @@ const u32 VM_DEBUG = 1<<6;
std::ostream& help(std::ostream& out) { std::ostream& help(std::ostream& out) {
out out
<<" ,--#-,\n" << " ,--#-,\n"
<<"<3 / \\____\\ <3\n" << "<3 / \\____\\ <3\n"
<<" |_|__A_|\n" << " |_|__A_|\n"
#ifdef _WIN32 #ifdef _WIN32
<<"use command <chcp 65001> to use unicode.\n" << "use command <chcp 65001> to use unicode.\n"
#endif #endif
<<"\nnasal <option>\n" << "\nnasal <option>\n"
<<"option:\n" << "option:\n"
<<" -h, --help | get help.\n" << " -h, --help | get help.\n"
<<"\nnasal [option] <file> [argv]\n" << " -v, --version | get version.\n"
<<"option:\n" << "\nnasal [option] <file> [argv]\n"
<<" -a, --ast | view ast (after link/optimize process).\n" << "option:\n"
<<" --raw-ast | view ast without after-processing.\n" << " -a, --ast | view ast after link/optimize process.\n"
<<" -c, --code | view bytecode.\n" << " --raw-ast | view ast without after-processing.\n"
<<" -e, --exec | execute.\n" << " -c, --code | view generated bytecode.\n"
<<" -t, --time | show execute time.\n" << " -e, --exec | execute directly.\n"
<<" -d, --detail | get detail info.\n" << " -t, --time | show execute time.\n"
<<" -dbg, --debug | debug mode.\n" << " -d, --detail | get detail info.\n"
<<"file:\n" << " -dbg, --debug | debug mode.\n"
<<" <filename> | execute file.\n" << "file:\n"
<<"argv:\n" << " <filename> | execute file.\n"
<<" <args> | cmd arguments used in program.\n"; << "argv:\n"
<< " <args> | cmd arguments used in program.\n";
return out; return out;
} }
std::ostream& logo(std::ostream& out) { std::ostream& logo(std::ostream& out) {
out out
<<" __ _\n" << " __ _\n"
<<" /\\ \\ \\__ _ ___ __ _| |\n" << " /\\ \\ \\__ _ ___ __ _| |\n"
<<" / \\/ / _` / __|/ _` | |\n" << " / \\/ / _` / __|/ _` | |\n"
<<" / /\\ / (_| \\__ \\ (_| | |\n" << " / /\\ / (_| \\__ \\ (_| | |\n"
<<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" << " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
<<"ver : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n" << "ver : " << __nasver << " (" << __DATE__ << " " << __TIME__ << ")\n"
<<"std : c++ "<<__cplusplus<<"\n" << "std : c++ " << __cplusplus << "\n"
<<"core : "<<std::thread::hardware_concurrency()<<" core(s)\n" << "core : " << std::thread::hardware_concurrency() << " core(s)\n"
<<"repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n" << "repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n"
<<"repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n" << "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
<<"wiki : https://wiki.flightgear.org/Nasal_scripting_language\n" << "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
<<"input <nasal -h> to get help .\n"; << "input <nasal -h> to get help .\n";
return out; return out;
} }
std::ostream& version(std::ostream& out) {
std::srand(std::time(nullptr));
f64 num = 0;
for(u32 i = 0; i<5; ++i) {
num = (num+rand())*(1.0/(RAND_MAX+1.0));
}
if (num<0.01) {
parse::easter_egg();
}
out << "version " << __nasver;
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
}
[[noreturn]] [[noreturn]]
void err() { void err() {
std::cerr std::cerr
<<"invalid argument(s).\n" << "invalid argument(s).\n"
<<"use <nasal -h> to get help.\n"; << "use <nasal -h> to get help.\n";
std::exit(1); std::exit(1);
} }
@ -80,8 +95,8 @@ void execute(
const std::vector<std::string>& argv, const std::vector<std::string>& argv,
const u32 cmd) { const u32 cmd) {
using clk=std::chrono::high_resolution_clock; using clk = std::chrono::high_resolution_clock;
const auto den=clk::duration::period::den; const auto den = clk::duration::period::den;
error err; error err;
lexer lex(err); lexer lex(err);
@ -131,14 +146,14 @@ void execute(
// get running time // get running time
if (cmd&VM_TIME) { if (cmd&VM_TIME) {
f64 tm=(clk::now()-start).count()*1.0/den; f64 tm=(clk::now()-start).count()*1.0/den;
std::clog<<"process exited after "<<tm<<"s.\n\n"; std::clog << "process exited after " << tm << "s.\n\n";
} }
} }
i32 main(i32 argc, const char* argv[]) { i32 main(i32 argc, const char* argv[]) {
// output version info // output version info
if (argc<=1) { if (argc<=1) {
std::clog<<logo; std::clog << logo;
return 0; return 0;
} }
@ -146,7 +161,9 @@ i32 main(i32 argc, const char* argv[]) {
if (argc==2) { if (argc==2) {
std::string s(argv[1]); std::string s(argv[1]);
if (s=="-h" || s=="--help") { if (s=="-h" || s=="--help") {
std::clog<<help; std::clog << help;
} else if (s=="-v" || s=="--version") {
std::clog << version;
} else if (s[0]!='-') { } else if (s[0]!='-') {
execute(s, {}, VM_EXEC); execute(s, {}, VM_EXEC);
} else { } else {
@ -171,14 +188,14 @@ i32 main(i32 argc, const char* argv[]) {
{"--debug", VM_DEBUG}, {"--debug", VM_DEBUG},
{"-dbg", VM_DEBUG} {"-dbg", VM_DEBUG}
}; };
u32 cmd=0; u32 cmd = 0;
std::string filename=""; std::string filename = "";
std::vector<std::string> vm_argv; std::vector<std::string> vm_argv;
for(i32 i=1; i<argc; ++i) { for(i32 i = 1; i<argc; ++i) {
if (cmdlst.count(argv[i])) { if (cmdlst.count(argv[i])) {
cmd|=cmdlst.at(argv[i]); cmd |= cmdlst.at(argv[i]);
} else if (!filename.length()) { } else if (!filename.length()) {
filename=argv[i]; filename = argv[i];
} else { } else {
vm_argv.push_back(argv[i]); vm_argv.push_back(argv[i]);
} }
@ -186,6 +203,6 @@ i32 main(i32 argc, const char* argv[]) {
if (!filename.length()) { if (!filename.length()) {
err(); err();
} }
execute(filename, vm_argv, cmd?cmd:VM_EXEC); execute(filename, vm_argv, cmd? cmd:VM_EXEC);
return 0; return 0;
} }

View File

@ -20,7 +20,7 @@ const error& parse::compile(const lexer& lexer) {
return err; return err;
} }
void parse::easter_egg() const { void parse::easter_egg() {
std::clog std::clog
<< " _,,,_ \n" << " _,,,_ \n"
<< " .' `'. \n" << " .' `'. \n"

View File

@ -157,5 +157,5 @@ public:
} }
} }
const error& compile(const lexer&); const error& compile(const lexer&);
void easter_egg() const; static void easter_egg();
}; };