forked from xxq250/Nasal-Interpreter
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
536baa0fe8 | ||
|
|
03ac911291 | ||
|
|
72933f4bf6 | ||
|
|
f04996201a |
@@ -41,10 +41,10 @@ set(NASAL_OBJECT_SOURCE_FILE
|
|||||||
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/util/gc_stat.cpp
|
${CMAKE_SOURCE_DIR}/src/util/gc_stat.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
${CMAKE_SOURCE_DIR}/src/ast/ast_dumper.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ast_format.cpp
|
${CMAKE_SOURCE_DIR}/src/ast/ast_format.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
${CMAKE_SOURCE_DIR}/src/ast/ast_visitor.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
${CMAKE_SOURCE_DIR}/src/ast/ast.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp
|
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp
|
||||||
|
|||||||
281
makefile
281
makefile
@@ -9,290 +9,10 @@ else
|
|||||||
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src
|
CXXFLAGS = -std=$(STD) -c -O3 -fPIC -I src
|
||||||
endif
|
endif
|
||||||
|
|
||||||
NASAL_HEADER = \
|
|
||||||
src/ast_dumper.h\
|
|
||||||
src/ast_visitor.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/natives/builtin.h\
|
|
||||||
src/nasal_codegen.h\
|
|
||||||
src/nasal_dbg.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/nasal_import.h\
|
|
||||||
src/nasal_lexer.h\
|
|
||||||
src/nasal_opcode.h\
|
|
||||||
src/nasal_parse.h\
|
|
||||||
src/nasal_vm.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal.h\
|
|
||||||
src/optimizer.h\
|
|
||||||
src/symbol_finder.h\
|
|
||||||
src/cli/cli.h\
|
|
||||||
src/natives/fg_props.h\
|
|
||||||
src/natives/bits_lib.h\
|
|
||||||
src/natives/io_lib.h\
|
|
||||||
src/natives/math_lib.h\
|
|
||||||
src/natives/dylib_lib.h\
|
|
||||||
src/natives/json_lib.h\
|
|
||||||
src/natives/unix_lib.h\
|
|
||||||
src/natives/coroutine.h\
|
|
||||||
src/natives/regex_lib.h\
|
|
||||||
src/natives/subprocess.h\
|
|
||||||
src/repl/repl.h\
|
|
||||||
src/util/fs.h\
|
|
||||||
src/util/util.h
|
|
||||||
|
|
||||||
NASAL_OBJECT = \
|
|
||||||
build/nasal_err.o\
|
|
||||||
build/nasal_ast.o\
|
|
||||||
build/ast_visitor.o\
|
|
||||||
build/bits_lib.o\
|
|
||||||
build/ast_dumper.o\
|
|
||||||
build/nasal_lexer.o\
|
|
||||||
build/nasal_parse.o\
|
|
||||||
build/nasal_import.o\
|
|
||||||
build/optimizer.o\
|
|
||||||
build/nasal_opcode.o\
|
|
||||||
build/symbol_finder.o\
|
|
||||||
build/nasal_codegen.o\
|
|
||||||
build/nasal_gc.o\
|
|
||||||
build/builtin.o\
|
|
||||||
build/fg_props.o\
|
|
||||||
build/io_lib.o\
|
|
||||||
build/math_lib.o\
|
|
||||||
build/unix_lib.o\
|
|
||||||
build/dylib_lib.o\
|
|
||||||
build/subprocess.o\
|
|
||||||
build/json_lib.o\
|
|
||||||
build/coroutine.o\
|
|
||||||
build/nasal_type.o\
|
|
||||||
build/nasal_vm.o\
|
|
||||||
build/nasal_dbg.o\
|
|
||||||
build/regex_lib.o\
|
|
||||||
build/repl.o\
|
|
||||||
build/cli.o\
|
|
||||||
build/fs.o\
|
|
||||||
build/util.o\
|
|
||||||
build/main.o
|
|
||||||
|
|
||||||
|
|
||||||
# for test
|
|
||||||
nasal: $(NASAL_OBJECT) | build
|
|
||||||
@if [ OS = "Darwin" ]; then\
|
|
||||||
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl -lpthread -stdlib=libc++ -static-libstdc++;\
|
|
||||||
else\
|
|
||||||
$(CXX) $(NASAL_OBJECT) -O3 -o nasal -ldl -lpthread;\
|
|
||||||
fi
|
|
||||||
|
|
||||||
nasal.exe: $(NASAL_OBJECT) | build
|
|
||||||
$(CXX) $(NASAL_OBJECT) -O3 -o nasal.exe
|
|
||||||
|
|
||||||
build:
|
|
||||||
@ if [ ! -d build ]; then mkdir build; fi
|
|
||||||
|
|
||||||
build/main.o: $(NASAL_HEADER) src/main.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/main.cpp -o build/main.o
|
|
||||||
|
|
||||||
build/cli.o: src/cli/cli.h src/cli/cli.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/cli/cli.cpp -o build/cli.o
|
|
||||||
|
|
||||||
build/util.o: src/util/util.h src/util/util.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/util/util.cpp -o build/util.o
|
|
||||||
|
|
||||||
build/fs.o: src/nasal.h src/util/util.h src/util/fs.h src/util/fs.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/util/fs.cpp -o build/fs.o
|
|
||||||
|
|
||||||
build/repl.o: $(NASAL_HEADER) src/repl/repl.h src/repl/repl.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/repl/repl.cpp -o build/repl.o
|
|
||||||
|
|
||||||
build/nasal_err.o: src/nasal.h src/repl/repl.h src/nasal_err.h src/nasal_err.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_err.cpp -o build/nasal_err.o
|
|
||||||
|
|
||||||
build/nasal_type.o:\
|
|
||||||
src/nasal.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/nasal_type.h src/nasal_type.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_type.cpp -o build/nasal_type.o
|
|
||||||
|
|
||||||
build/nasal_gc.o:\
|
|
||||||
src/nasal.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/nasal_gc.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_gc.cpp -o build/nasal_gc.o
|
|
||||||
|
|
||||||
build/nasal_import.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/nasal_lexer.h\
|
|
||||||
src/nasal_parse.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/util/fs.h\
|
|
||||||
src/nasal_import.h src/nasal_import.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_import.cpp -o build/nasal_import.o
|
|
||||||
|
|
||||||
build/nasal_lexer.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/repl/repl.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/util/fs.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_lexer.h src/nasal_lexer.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_lexer.cpp -o build/nasal_lexer.o
|
|
||||||
|
|
||||||
build/nasal_ast.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_ast.h src/nasal_ast.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_ast.cpp -o build/nasal_ast.o
|
|
||||||
|
|
||||||
build/builtin.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/natives/builtin.h\
|
|
||||||
src/natives/builtin.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/builtin.cpp -o build/builtin.o
|
|
||||||
|
|
||||||
build/coroutine.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/coroutine.h src/natives/coroutine.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/coroutine.cpp -o build/coroutine.o
|
|
||||||
|
|
||||||
build/bits_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/bits_lib.h src/natives/bits_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/bits_lib.cpp -o build/bits_lib.o
|
|
||||||
|
|
||||||
build/math_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/math_lib.h src/natives/math_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/math_lib.cpp -o build/math_lib.o
|
|
||||||
|
|
||||||
build/io_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/util/fs.h\
|
|
||||||
src/natives/io_lib.h src/natives/io_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/io_lib.cpp -o build/io_lib.o
|
|
||||||
|
|
||||||
build/dylib_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/util/fs.h\
|
|
||||||
src/natives/dylib_lib.h src/natives/dylib_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/dylib_lib.cpp -o build/dylib_lib.o
|
|
||||||
|
|
||||||
build/json_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/natives/json_lib.h src/natives/json_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/json_lib.cpp -o build/json_lib.o
|
|
||||||
|
|
||||||
build/unix_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/unix_lib.h src/natives/unix_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/unix_lib.cpp -o build/unix_lib.o
|
|
||||||
|
|
||||||
build/regex_lib.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/regex_lib.h src/natives/regex_lib.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/regex_lib.cpp -o build/regex_lib.o
|
|
||||||
|
|
||||||
build/subprocess.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/subprocess.h src/natives/subprocess.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/subprocess.cpp -o build/subprocess.o
|
|
||||||
|
|
||||||
|
|
||||||
build/fg_props.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_type.h\
|
|
||||||
src/nasal_gc.h\
|
|
||||||
src/natives/fg_props.h src/natives/fg_props.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/natives/fg_props.cpp -o build/fg_props.o
|
|
||||||
|
|
||||||
build/nasal_codegen.o: $(NASAL_HEADER) src/nasal_codegen.h src/nasal_codegen.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_codegen.cpp -o build/nasal_codegen.o
|
|
||||||
|
|
||||||
build/nasal_opcode.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/natives/builtin.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/nasal_opcode.h src/nasal_opcode.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_opcode.cpp -o build/nasal_opcode.o
|
|
||||||
|
|
||||||
build/nasal_parse.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/nasal_lexer.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/nasal_parse.h src/nasal_parse.cpp src/nasal_ast.h | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_parse.cpp -o build/nasal_parse.o
|
|
||||||
|
|
||||||
build/optimizer.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/ast_visitor.h\
|
|
||||||
src/optimizer.h src/optimizer.cpp src/nasal_ast.h | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/optimizer.cpp -o build/optimizer.o
|
|
||||||
|
|
||||||
build/symbol_finder.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/ast_visitor.h\
|
|
||||||
src/symbol_finder.h src/symbol_finder.cpp src/nasal_ast.h | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/symbol_finder.cpp -o build/symbol_finder.o
|
|
||||||
|
|
||||||
build/ast_visitor.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/ast_visitor.h src/ast_visitor.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/ast_visitor.cpp -o build/ast_visitor.o
|
|
||||||
|
|
||||||
build/ast_dumper.o: \
|
|
||||||
src/nasal.h\
|
|
||||||
src/nasal_err.h\
|
|
||||||
src/nasal_ast.h\
|
|
||||||
src/ast_visitor.h\
|
|
||||||
src/util/util.h\
|
|
||||||
src/ast_dumper.h src/ast_dumper.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/ast_dumper.cpp -o build/ast_dumper.o
|
|
||||||
|
|
||||||
build/nasal_vm.o: $(NASAL_HEADER) src/nasal_vm.h src/nasal_vm.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_vm.cpp -o build/nasal_vm.o
|
|
||||||
|
|
||||||
build/nasal_dbg.o: $(NASAL_HEADER) src/nasal_dbg.h src/nasal_dbg.cpp | build
|
|
||||||
$(CXX) $(CXXFLAGS) src/nasal_dbg.cpp -o build/nasal_dbg.o
|
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@ echo "[clean] nasal" && if [ -e nasal ]; then rm nasal; fi
|
@ echo "[clean] nasal" && if [ -e nasal ]; then rm nasal; fi
|
||||||
@ echo "[clean] nasal.exe" && if [ -e nasal.exe ]; then rm nasal.exe; fi
|
@ echo "[clean] nasal.exe" && if [ -e nasal.exe ]; then rm nasal.exe; fi
|
||||||
@ rm $(NASAL_OBJECT)
|
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test:
|
test:
|
||||||
@@ -303,6 +23,7 @@ test:
|
|||||||
@ ./nasal -t test/bigloop.nas
|
@ ./nasal -t test/bigloop.nas
|
||||||
@ ./nasal -t test/bp.nas
|
@ ./nasal -t test/bp.nas
|
||||||
@ ./nasal -d test/calc.nas
|
@ ./nasal -d test/calc.nas
|
||||||
|
@ ./nasal test/caller.nas
|
||||||
@ ./nasal -e test/choice.nas
|
@ ./nasal -e test/choice.nas
|
||||||
@ ./nasal -e test/class.nas
|
@ ./nasal -e test/class.nas
|
||||||
@ ./nasal -t -d test/console3D.nas 20
|
@ ./nasal -t -d test/console3D.nas 20
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "nasal_ast.h"
|
#include "ast.h"
|
||||||
#include "ast_visitor.h"
|
#include "ast_visitor.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal_ast.h"
|
#include "ast.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "cli/cli.h"
|
#include "cli/cli.h"
|
||||||
#include "ast_format.h"
|
#include "ast/ast_format.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
#include "nasal_gc.h"
|
#include "nasal_gc.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
|
#include "ast/ast_visitor.h"
|
||||||
|
#include "ast/ast_dumper.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
#include "ast_visitor.h"
|
|
||||||
#include "ast_dumper.h"
|
|
||||||
#include "symbol_finder.h"
|
#include "symbol_finder.h"
|
||||||
#include "optimizer.h"
|
#include "optimizer.h"
|
||||||
#include "nasal_codegen.h"
|
#include "nasal_codegen.h"
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
#include "nasal_opcode.h"
|
#include "nasal_opcode.h"
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "ast_visitor.h"
|
#include "ast/ast_visitor.h"
|
||||||
#include "symbol_finder.h"
|
#include "symbol_finder.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "nasal_import.h"
|
#include "nasal_import.h"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "nasal_parse.h"
|
#include "nasal_parse.h"
|
||||||
#include "symbol_finder.h"
|
#include "symbol_finder.h"
|
||||||
|
|||||||
@@ -103,94 +103,94 @@ enum opcode_type: u8 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static std::unordered_map<opcode_type, std::string> operand_name_table = {
|
static std::unordered_map<opcode_type, std::string> operand_name_table = {
|
||||||
{opcode_type::op_exit, "exit "},
|
{opcode_type::op_exit, "exit "},
|
||||||
{opcode_type::op_repl, "repl "},
|
{opcode_type::op_repl, "repl "},
|
||||||
{opcode_type::op_intl, "intl "},
|
{opcode_type::op_intl, "intl "},
|
||||||
{opcode_type::op_loadg, "loadg "},
|
{opcode_type::op_loadg, "loadg "},
|
||||||
{opcode_type::op_loadl, "loadl "},
|
{opcode_type::op_loadl, "loadl "},
|
||||||
{opcode_type::op_loadu, "loadu "},
|
{opcode_type::op_loadu, "loadu "},
|
||||||
{opcode_type::op_dup, "dup "},
|
{opcode_type::op_dup, "dup "},
|
||||||
{opcode_type::op_pnum, "pnum "},
|
{opcode_type::op_pnum, "pnum "},
|
||||||
{opcode_type::op_pnil, "pnil "},
|
{opcode_type::op_pnil, "pnil "},
|
||||||
{opcode_type::op_pstr, "pstr "},
|
{opcode_type::op_pstr, "pstr "},
|
||||||
{opcode_type::op_newv, "newv "},
|
{opcode_type::op_newv, "newv "},
|
||||||
{opcode_type::op_newh, "newh "},
|
{opcode_type::op_newh, "newh "},
|
||||||
{opcode_type::op_newf, "newf "},
|
{opcode_type::op_newf, "newf "},
|
||||||
{opcode_type::op_happ, "happ "},
|
{opcode_type::op_happ, "happ "},
|
||||||
{opcode_type::op_para, "para "},
|
{opcode_type::op_para, "para "},
|
||||||
{opcode_type::op_deft, "def "},
|
{opcode_type::op_deft, "def "},
|
||||||
{opcode_type::op_dyn, "dyn "},
|
{opcode_type::op_dyn, "dyn "},
|
||||||
{opcode_type::op_lnot, "lnot "},
|
{opcode_type::op_lnot, "lnot "},
|
||||||
{opcode_type::op_usub, "usub "},
|
{opcode_type::op_usub, "usub "},
|
||||||
{opcode_type::op_bnot, "bitnot"},
|
{opcode_type::op_bnot, "bitnot"},
|
||||||
{opcode_type::op_btor, "bitor "},
|
{opcode_type::op_btor, "bitor "},
|
||||||
{opcode_type::op_btxor, "bitxor"},
|
{opcode_type::op_btxor, "bitxor"},
|
||||||
{opcode_type::op_btand, "bitand"},
|
{opcode_type::op_btand, "bitand"},
|
||||||
{opcode_type::op_add, "add "},
|
{opcode_type::op_add, "add "},
|
||||||
{opcode_type::op_sub, "sub "},
|
{opcode_type::op_sub, "sub "},
|
||||||
{opcode_type::op_mul, "mult "},
|
{opcode_type::op_mul, "mult "},
|
||||||
{opcode_type::op_div, "div "},
|
{opcode_type::op_div, "div "},
|
||||||
{opcode_type::op_lnk, "lnk "},
|
{opcode_type::op_lnk, "lnk "},
|
||||||
{opcode_type::op_addc, "addc "},
|
{opcode_type::op_addc, "addc "},
|
||||||
{opcode_type::op_subc, "subc "},
|
{opcode_type::op_subc, "subc "},
|
||||||
{opcode_type::op_mulc, "multc "},
|
{opcode_type::op_mulc, "multc "},
|
||||||
{opcode_type::op_divc, "divc "},
|
{opcode_type::op_divc, "divc "},
|
||||||
{opcode_type::op_lnkc, "lnkc "},
|
{opcode_type::op_lnkc, "lnkc "},
|
||||||
{opcode_type::op_addeq, "addeq "},
|
{opcode_type::op_addeq, "addeq "},
|
||||||
{opcode_type::op_subeq, "subeq "},
|
{opcode_type::op_subeq, "subeq "},
|
||||||
{opcode_type::op_muleq, "muleq "},
|
{opcode_type::op_muleq, "muleq "},
|
||||||
{opcode_type::op_diveq, "diveq "},
|
{opcode_type::op_diveq, "diveq "},
|
||||||
{opcode_type::op_lnkeq, "lnkeq "},
|
{opcode_type::op_lnkeq, "lnkeq "},
|
||||||
{opcode_type::op_btandeq, "bandeq"},
|
{opcode_type::op_btandeq, "bandeq"},
|
||||||
{opcode_type::op_btoreq, "boreq "},
|
{opcode_type::op_btoreq, "boreq "},
|
||||||
{opcode_type::op_btxoreq, "bxoreq"},
|
{opcode_type::op_btxoreq, "bxoreq"},
|
||||||
{opcode_type::op_addeqc, "addeqc"},
|
{opcode_type::op_addeqc, "addeqc"},
|
||||||
{opcode_type::op_subeqc, "subeqc"},
|
{opcode_type::op_subeqc, "subeqc"},
|
||||||
{opcode_type::op_muleqc, "muleqc"},
|
{opcode_type::op_muleqc, "muleqc"},
|
||||||
{opcode_type::op_diveqc, "diveqc"},
|
{opcode_type::op_diveqc, "diveqc"},
|
||||||
{opcode_type::op_lnkeqc, "lnkeqc"},
|
{opcode_type::op_lnkeqc, "lnkeqc"},
|
||||||
{opcode_type::op_addecp, "addecp"},
|
{opcode_type::op_addecp, "addecp"},
|
||||||
{opcode_type::op_subecp, "subecp"},
|
{opcode_type::op_subecp, "subecp"},
|
||||||
{opcode_type::op_mulecp, "mulecp"},
|
{opcode_type::op_mulecp, "mulecp"},
|
||||||
{opcode_type::op_divecp, "divecp"},
|
{opcode_type::op_divecp, "divecp"},
|
||||||
{opcode_type::op_lnkecp, "lnkecp"},
|
{opcode_type::op_lnkecp, "lnkecp"},
|
||||||
{opcode_type::op_meq, "meq "},
|
{opcode_type::op_meq, "meq "},
|
||||||
{opcode_type::op_eq, "eq "},
|
{opcode_type::op_eq, "eq "},
|
||||||
{opcode_type::op_neq, "neq "},
|
{opcode_type::op_neq, "neq "},
|
||||||
{opcode_type::op_less, "less "},
|
{opcode_type::op_less, "less "},
|
||||||
{opcode_type::op_leq, "leq "},
|
{opcode_type::op_leq, "leq "},
|
||||||
{opcode_type::op_grt, "grt "},
|
{opcode_type::op_grt, "grt "},
|
||||||
{opcode_type::op_geq, "geq "},
|
{opcode_type::op_geq, "geq "},
|
||||||
{opcode_type::op_lessc, "lessc "},
|
{opcode_type::op_lessc, "lessc "},
|
||||||
{opcode_type::op_leqc, "leqc "},
|
{opcode_type::op_leqc, "leqc "},
|
||||||
{opcode_type::op_grtc, "grtc "},
|
{opcode_type::op_grtc, "grtc "},
|
||||||
{opcode_type::op_geqc, "geqc "},
|
{opcode_type::op_geqc, "geqc "},
|
||||||
{opcode_type::op_pop, "pop "},
|
{opcode_type::op_pop, "pop "},
|
||||||
{opcode_type::op_jmp, "jmp "},
|
{opcode_type::op_jmp, "jmp "},
|
||||||
{opcode_type::op_jt, "jt "},
|
{opcode_type::op_jt, "jt "},
|
||||||
{opcode_type::op_jf, "jf "},
|
{opcode_type::op_jf, "jf "},
|
||||||
{opcode_type::op_cnt, "cnt "},
|
{opcode_type::op_cnt, "cnt "},
|
||||||
{opcode_type::op_findex, "findx "},
|
{opcode_type::op_findex, "findx "},
|
||||||
{opcode_type::op_feach, "feach "},
|
{opcode_type::op_feach, "feach "},
|
||||||
{opcode_type::op_callg, "callg "},
|
{opcode_type::op_callg, "callg "},
|
||||||
{opcode_type::op_calll, "calll "},
|
{opcode_type::op_calll, "calll "},
|
||||||
{opcode_type::op_upval, "upval "},
|
{opcode_type::op_upval, "upval "},
|
||||||
{opcode_type::op_callv, "callv "},
|
{opcode_type::op_callv, "callv "},
|
||||||
{opcode_type::op_callvi, "callvi"},
|
{opcode_type::op_callvi, "callvi"},
|
||||||
{opcode_type::op_callh, "callh "},
|
{opcode_type::op_callh, "callh "},
|
||||||
{opcode_type::op_callfv, "callfv"},
|
{opcode_type::op_callfv, "callfv"},
|
||||||
{opcode_type::op_callfh, "callfh"},
|
{opcode_type::op_callfh, "callfh"},
|
||||||
{opcode_type::op_callb, "callb "},
|
{opcode_type::op_callb, "callb "},
|
||||||
{opcode_type::op_slcbeg, "slcbeg"},
|
{opcode_type::op_slcbeg, "slcbeg"},
|
||||||
{opcode_type::op_slcend, "slcend"},
|
{opcode_type::op_slcend, "slcend"},
|
||||||
{opcode_type::op_slc, "slice "},
|
{opcode_type::op_slc, "slice "},
|
||||||
{opcode_type::op_slc2, "slice2"},
|
{opcode_type::op_slc2, "slice2"},
|
||||||
{opcode_type::op_mcallg, "mcallg"},
|
{opcode_type::op_mcallg, "mcallg"},
|
||||||
{opcode_type::op_mcalll, "mcalll"},
|
{opcode_type::op_mcalll, "mcalll"},
|
||||||
{opcode_type::op_mupval, "mupval"},
|
{opcode_type::op_mupval, "mupval"},
|
||||||
{opcode_type::op_mcallv, "mcallv"},
|
{opcode_type::op_mcallv, "mcallv"},
|
||||||
{opcode_type::op_mcallh, "mcallh"},
|
{opcode_type::op_mcallh, "mcallh"},
|
||||||
{opcode_type::op_ret, "ret "}
|
{opcode_type::op_ret, "ret "}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct opcode {
|
struct opcode {
|
||||||
|
|||||||
2344
src/nasal_parse.cpp
2344
src/nasal_parse.cpp
File diff suppressed because it is too large
Load Diff
@@ -1,169 +1,169 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "nasal_lexer.h"
|
#include "nasal_lexer.h"
|
||||||
#include "nasal_err.h"
|
#include "nasal_err.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
class parse {
|
class parse {
|
||||||
|
|
||||||
#define thisspan (toks[ptr].loc)
|
#define thisspan (toks[ptr].loc)
|
||||||
#define prevspan (ptr!=0? toks[ptr-1].loc:toks[ptr].loc)
|
#define prevspan (ptr!=0? toks[ptr-1].loc:toks[ptr].loc)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 ptr;
|
u64 ptr;
|
||||||
u64 in_func_depth; // count function block
|
u64 in_func_depth; // count function block
|
||||||
u64 in_loop_depth; // count loop block
|
u64 in_loop_depth; // count loop block
|
||||||
const token* toks;
|
const token* toks;
|
||||||
code_block* root;
|
code_block* root;
|
||||||
error err;
|
error err;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::unordered_map<tok, std::string> token_name_mapper = {
|
const std::unordered_map<tok, std::string> token_name_mapper = {
|
||||||
{tok::tk_true , "true" },
|
{tok::tk_true , "true" },
|
||||||
{tok::tk_false , "false" },
|
{tok::tk_false , "false" },
|
||||||
{tok::tk_use , "use" },
|
{tok::tk_use , "use" },
|
||||||
{tok::tk_for , "for" },
|
{tok::tk_for , "for" },
|
||||||
{tok::tk_forindex, "forindex"},
|
{tok::tk_forindex, "forindex"},
|
||||||
{tok::tk_foreach , "foreach" },
|
{tok::tk_foreach , "foreach" },
|
||||||
{tok::tk_while , "while" },
|
{tok::tk_while , "while" },
|
||||||
{tok::tk_var , "var" },
|
{tok::tk_var , "var" },
|
||||||
{tok::tk_func , "func" },
|
{tok::tk_func , "func" },
|
||||||
{tok::tk_brk , "break" },
|
{tok::tk_brk , "break" },
|
||||||
{tok::tk_cont , "continue"},
|
{tok::tk_cont , "continue"},
|
||||||
{tok::tk_ret , "return" },
|
{tok::tk_ret , "return" },
|
||||||
{tok::tk_if , "if" },
|
{tok::tk_if , "if" },
|
||||||
{tok::tk_elsif , "elsif" },
|
{tok::tk_elsif , "elsif" },
|
||||||
{tok::tk_else , "else" },
|
{tok::tk_else , "else" },
|
||||||
{tok::tk_nil , "nil" },
|
{tok::tk_nil , "nil" },
|
||||||
{tok::tk_lcurve , "(" },
|
{tok::tk_lcurve , "(" },
|
||||||
{tok::tk_rcurve , ")" },
|
{tok::tk_rcurve , ")" },
|
||||||
{tok::tk_lbracket, "[" },
|
{tok::tk_lbracket, "[" },
|
||||||
{tok::tk_rbracket, "]" },
|
{tok::tk_rbracket, "]" },
|
||||||
{tok::tk_lbrace , "{" },
|
{tok::tk_lbrace , "{" },
|
||||||
{tok::tk_rbrace , "}" },
|
{tok::tk_rbrace , "}" },
|
||||||
{tok::tk_semi , ";" },
|
{tok::tk_semi , ";" },
|
||||||
{tok::tk_and , "and" },
|
{tok::tk_and , "and" },
|
||||||
{tok::tk_or , "or" },
|
{tok::tk_or , "or" },
|
||||||
{tok::tk_comma , "," },
|
{tok::tk_comma , "," },
|
||||||
{tok::tk_dot , "." },
|
{tok::tk_dot , "." },
|
||||||
{tok::tk_ellipsis, "..." },
|
{tok::tk_ellipsis, "..." },
|
||||||
{tok::tk_quesmark, "?" },
|
{tok::tk_quesmark, "?" },
|
||||||
{tok::tk_quesques, "??" },
|
{tok::tk_quesques, "??" },
|
||||||
{tok::tk_quesdot , "?." },
|
{tok::tk_quesdot , "?." },
|
||||||
{tok::tk_colon , ":" },
|
{tok::tk_colon , ":" },
|
||||||
{tok::tk_add , "+" },
|
{tok::tk_add , "+" },
|
||||||
{tok::tk_sub , "-" },
|
{tok::tk_sub , "-" },
|
||||||
{tok::tk_mult , "*" },
|
{tok::tk_mult , "*" },
|
||||||
{tok::tk_div , "/" },
|
{tok::tk_div , "/" },
|
||||||
{tok::tk_floater , "~" },
|
{tok::tk_floater , "~" },
|
||||||
{tok::tk_btand , "&" },
|
{tok::tk_btand , "&" },
|
||||||
{tok::tk_btor , "|" },
|
{tok::tk_btor , "|" },
|
||||||
{tok::tk_btxor , "^" },
|
{tok::tk_btxor , "^" },
|
||||||
{tok::tk_not , "!" },
|
{tok::tk_not , "!" },
|
||||||
{tok::tk_eq , "=" },
|
{tok::tk_eq , "=" },
|
||||||
{tok::tk_addeq , "+=" },
|
{tok::tk_addeq , "+=" },
|
||||||
{tok::tk_subeq , "-=" },
|
{tok::tk_subeq , "-=" },
|
||||||
{tok::tk_multeq , "*=" },
|
{tok::tk_multeq , "*=" },
|
||||||
{tok::tk_diveq , "/=" },
|
{tok::tk_diveq , "/=" },
|
||||||
{tok::tk_lnkeq , "~=" },
|
{tok::tk_lnkeq , "~=" },
|
||||||
{tok::tk_btandeq , "&=" },
|
{tok::tk_btandeq , "&=" },
|
||||||
{tok::tk_btoreq , "|=" },
|
{tok::tk_btoreq , "|=" },
|
||||||
{tok::tk_btxoreq , "^=" },
|
{tok::tk_btxoreq , "^=" },
|
||||||
{tok::tk_cmpeq , "==" },
|
{tok::tk_cmpeq , "==" },
|
||||||
{tok::tk_neq , "!=" },
|
{tok::tk_neq , "!=" },
|
||||||
{tok::tk_less , "<" },
|
{tok::tk_less , "<" },
|
||||||
{tok::tk_leq , "<=" },
|
{tok::tk_leq , "<=" },
|
||||||
{tok::tk_grt , ">" },
|
{tok::tk_grt , ">" },
|
||||||
{tok::tk_geq , ">=" }
|
{tok::tk_geq , ">=" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void die(const span&, const std::string&);
|
void die(const span&, const std::string&);
|
||||||
void next();
|
void next();
|
||||||
void match(tok, const char* info = nullptr);
|
void match(tok, const char* info = nullptr);
|
||||||
bool lookahead(tok);
|
bool lookahead(tok);
|
||||||
bool lookahead_expression();
|
bool lookahead_expression();
|
||||||
bool is_call(tok);
|
bool is_call(tok);
|
||||||
bool check_comma(const tok*);
|
bool check_comma(const tok*);
|
||||||
bool check_tuple();
|
bool check_tuple();
|
||||||
bool check_func_end(expr*);
|
bool check_func_end(expr*);
|
||||||
bool check_in_curve_multi_definition();
|
bool check_in_curve_multi_definition();
|
||||||
bool check_special_call();
|
bool check_special_call();
|
||||||
bool need_semi_check(expr*);
|
bool need_semi_check(expr*);
|
||||||
void update_location(expr*);
|
void update_location(expr*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
use_stmt* use_stmt_gen();
|
use_stmt* use_stmt_gen();
|
||||||
null_expr* null();
|
null_expr* null();
|
||||||
nil_expr* nil();
|
nil_expr* nil();
|
||||||
number_literal* num();
|
number_literal* num();
|
||||||
string_literal* str();
|
string_literal* str();
|
||||||
identifier* id();
|
identifier* id();
|
||||||
bool_literal* bools();
|
bool_literal* bools();
|
||||||
vector_expr* vec();
|
vector_expr* vec();
|
||||||
hash_expr* hash();
|
hash_expr* hash();
|
||||||
hash_pair* pair();
|
hash_pair* pair();
|
||||||
function* func();
|
function* func();
|
||||||
void params(function*);
|
void params(function*);
|
||||||
expr* lcurve_expr();
|
expr* lcurve_expr();
|
||||||
expr* expression();
|
expr* expression();
|
||||||
code_block* expression_block();
|
code_block* expression_block();
|
||||||
expr* calc();
|
expr* calc();
|
||||||
expr* bitwise_or();
|
expr* bitwise_or();
|
||||||
expr* bitwise_xor();
|
expr* bitwise_xor();
|
||||||
expr* bitwise_and();
|
expr* bitwise_and();
|
||||||
expr* or_expr();
|
expr* or_expr();
|
||||||
expr* and_expr();
|
expr* and_expr();
|
||||||
expr* cmp_expr();
|
expr* cmp_expr();
|
||||||
expr* null_chain_expr();
|
expr* null_chain_expr();
|
||||||
expr* additive_expr();
|
expr* additive_expr();
|
||||||
expr* multive_expr();
|
expr* multive_expr();
|
||||||
unary_operator* unary();
|
unary_operator* unary();
|
||||||
expr* scalar();
|
expr* scalar();
|
||||||
call* call_scalar();
|
call* call_scalar();
|
||||||
call_hash* callh();
|
call_hash* callh();
|
||||||
null_access* null_access_call();
|
null_access* null_access_call();
|
||||||
call_vector* callv();
|
call_vector* callv();
|
||||||
call_function* callf();
|
call_function* callf();
|
||||||
slice_vector* subvec();
|
slice_vector* subvec();
|
||||||
expr* definition();
|
expr* definition();
|
||||||
multi_identifier* incurve_def();
|
multi_identifier* incurve_def();
|
||||||
multi_identifier* outcurve_def();
|
multi_identifier* outcurve_def();
|
||||||
multi_identifier* multi_id();
|
multi_identifier* multi_id();
|
||||||
tuple_expr* multi_scalar();
|
tuple_expr* multi_scalar();
|
||||||
multi_assign* multi_assignment();
|
multi_assign* multi_assignment();
|
||||||
expr* loop();
|
expr* loop();
|
||||||
while_expr* while_loop();
|
while_expr* while_loop();
|
||||||
for_expr* for_loop();
|
for_expr* for_loop();
|
||||||
forei_expr* forei_loop();
|
forei_expr* forei_loop();
|
||||||
iter_expr* iter_gen();
|
iter_expr* iter_gen();
|
||||||
condition_expr* cond();
|
condition_expr* cond();
|
||||||
continue_expr* continue_expression();
|
continue_expr* continue_expression();
|
||||||
break_expr* break_expression();
|
break_expr* break_expression();
|
||||||
return_expr* return_expression();
|
return_expr* return_expression();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
code_block* tree() {return root;}
|
code_block* tree() {return root;}
|
||||||
|
|
||||||
// swap root pointer with another pointer(maybe nullptr)
|
// swap root pointer with another pointer(maybe nullptr)
|
||||||
code_block* swap(code_block* another) {
|
code_block* swap(code_block* another) {
|
||||||
auto res = root;
|
auto res = root;
|
||||||
root = another;
|
root = another;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parse(): ptr(0), in_func_depth(0),
|
parse(): ptr(0), in_func_depth(0),
|
||||||
in_loop_depth(0), toks(nullptr),
|
in_loop_depth(0), toks(nullptr),
|
||||||
root(nullptr) {}
|
root(nullptr) {}
|
||||||
~parse() {delete root;}
|
~parse() {delete root;}
|
||||||
const error& compile(const lexer&);
|
const error& compile(const lexer&);
|
||||||
static void easter_egg();
|
static void easter_egg();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,300 +1,281 @@
|
|||||||
#include "nasal_type.h"
|
#include "nasal_type.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
|
std::ostream& operator<<(std::ostream& out, nas_vec& vec) {
|
||||||
if (!vec.elems.size() || vec.printed) {
|
if (!vec.elems.size() || vec.printed) {
|
||||||
out << (vec.elems.size()? "[..]":"[]");
|
out << (vec.elems.size()? "[..]":"[]");
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
vec.printed = true;
|
vec.printed = true;
|
||||||
usize iter = 0, size = vec.elems.size();
|
usize iter = 0, size = vec.elems.size();
|
||||||
out << "[";
|
out << "[";
|
||||||
for (auto& i:vec.elems) {
|
for (auto& i:vec.elems) {
|
||||||
out << i << ",]"[(++iter)==size];
|
out << i << ",]"[(++iter)==size];
|
||||||
}
|
}
|
||||||
vec.printed = false;
|
vec.printed = false;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nas_hash::get_value(const std::string& key) {
|
var nas_hash::get_value(const std::string& key) {
|
||||||
if (elems.count(key)) {
|
if (elems.count(key)) {
|
||||||
return elems.at(key);
|
return elems.at(key);
|
||||||
}
|
}
|
||||||
if (!elems.count("parents")) {
|
if (!elems.count("parents")) {
|
||||||
return var::none();
|
return var::none();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = var::none();
|
auto ret = var::none();
|
||||||
auto& val = elems.at("parents");
|
auto& val = elems.at("parents");
|
||||||
if (!val.is_vec()) {
|
if (!val.is_vec()) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
for (auto& i : val.vec().elems) {
|
for (auto& i : val.vec().elems) {
|
||||||
if (i.is_hash()) {
|
if (i.is_hash()) {
|
||||||
ret = i.hash().get_value(key);
|
ret = i.hash().get_value(key);
|
||||||
}
|
}
|
||||||
if (!ret.is_none()) {
|
if (!ret.is_none()) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
var* nas_hash::get_memory(const std::string& key) {
|
var* nas_hash::get_memory(const std::string& key) {
|
||||||
if (elems.count(key)) {
|
if (elems.count(key)) {
|
||||||
return &elems.at(key);
|
return &elems.at(key);
|
||||||
}
|
}
|
||||||
if (!elems.count("parents")) {
|
if (!elems.count("parents")) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
var* addr = nullptr;
|
var* addr = nullptr;
|
||||||
var& val = elems.at("parents");
|
var& val = elems.at("parents");
|
||||||
if (!val.is_vec()) {
|
if (!val.is_vec()) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
for (auto& i : val.vec().elems) {
|
for (auto& i : val.vec().elems) {
|
||||||
// recursively search key in `parents`
|
// recursively search key in `parents`
|
||||||
if (i.is_hash()) {
|
if (i.is_hash()) {
|
||||||
addr = i.hash().get_memory(key);
|
addr = i.hash().get_memory(key);
|
||||||
}
|
}
|
||||||
if (addr) {
|
if (addr) {
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, nas_hash& hash) {
|
std::ostream& operator<<(std::ostream& out, nas_hash& hash) {
|
||||||
if (!hash.elems.size() || hash.printed) {
|
if (!hash.elems.size() || hash.printed) {
|
||||||
out << (hash.elems.size()? "{..}":"{}");
|
out << (hash.elems.size()? "{..}":"{}");
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark print, to avoid infinite recursion
|
// mark print, to avoid infinite recursion
|
||||||
hash.printed = true;
|
hash.printed = true;
|
||||||
|
|
||||||
static const char* sep[] = {", ", "}"};
|
static const char* sep[] = {", ", "}"};
|
||||||
usize iter = 0, size = hash.elems.size();
|
usize iter = 0, size = hash.elems.size();
|
||||||
out << "{";
|
out << "{";
|
||||||
for (auto& i : hash.elems) {
|
for (auto& i : hash.elems) {
|
||||||
out << i.first << ": " << i.second << sep[(++iter)==size];
|
out << i.first << ": " << i.second << sep[(++iter)==size];
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore flag
|
// restore flag
|
||||||
hash.printed = false;
|
hash.printed = false;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, nas_func& func) {
|
std::ostream& operator<<(std::ostream& out, nas_func& func) {
|
||||||
out << "func(";
|
out << "func(";
|
||||||
|
|
||||||
std::vector<std::string> argument_list = {};
|
std::vector<std::string> argument_list = {};
|
||||||
argument_list.resize(func.keys.size());
|
argument_list.resize(func.keys.size());
|
||||||
for (const auto& key : func.keys) {
|
for (const auto& key : func.keys) {
|
||||||
argument_list[key.second-1] = key.first;
|
argument_list[key.second-1] = key.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& key : argument_list) {
|
for (const auto& key : argument_list) {
|
||||||
out << key;
|
out << key;
|
||||||
if (key != argument_list.back()) {
|
if (key != argument_list.back()) {
|
||||||
out << ", ";
|
out << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (func.dynamic_parameter_index>=0) {
|
if (func.dynamic_parameter_index>=0) {
|
||||||
out << (argument_list.size()? ", ":"");
|
out << (argument_list.size()? ", ":"");
|
||||||
out << func.dynamic_parameter_name << "...";
|
out << func.dynamic_parameter_name << "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
out << ") {..}";
|
out << ") {..}";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_func::clear() {
|
void nas_func::clear() {
|
||||||
dynamic_parameter_index = -1;
|
dynamic_parameter_index = -1;
|
||||||
local.clear();
|
local.clear();
|
||||||
upval.clear();
|
upval.clear();
|
||||||
keys.clear();
|
keys.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_ghost::set(const std::string& ghost_type_name,
|
void nas_ghost::set(const std::string& ghost_type_name,
|
||||||
destructor destructor_pointer,
|
destructor destructor_pointer,
|
||||||
marker gc_marker_pointer,
|
marker gc_marker_pointer,
|
||||||
void* ghost_pointer) {
|
void* ghost_pointer) {
|
||||||
type_name = ghost_type_name;
|
type_name = ghost_type_name;
|
||||||
destructor_function = destructor_pointer;
|
destructor_function = destructor_pointer;
|
||||||
gc_mark_function = gc_marker_pointer;
|
gc_mark_function = gc_marker_pointer;
|
||||||
pointer = ghost_pointer;
|
pointer = ghost_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_ghost::clear() {
|
void nas_ghost::clear() {
|
||||||
// do nothing if pointer is null
|
// do nothing if pointer is null
|
||||||
if (!pointer) {
|
if (!pointer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do clear pointer if destructor function pointer is null
|
// do clear pointer if destructor function pointer is null
|
||||||
if (!destructor_function) {
|
if (!destructor_function) {
|
||||||
type_name = "";
|
type_name = "";
|
||||||
pointer = nullptr;
|
pointer = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do destruction
|
// do destruction
|
||||||
destructor_function(pointer);
|
destructor_function(pointer);
|
||||||
type_name = "";
|
type_name = "";
|
||||||
pointer = nullptr;
|
pointer = nullptr;
|
||||||
destructor_function = nullptr;
|
destructor_function = nullptr;
|
||||||
gc_mark_function = nullptr;
|
gc_mark_function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
std::ostream& operator<<(std::ostream& out, const nas_ghost& ghost) {
|
||||||
out << "<" << ghost.get_ghost_name();
|
out << "<" << ghost.get_ghost_name();
|
||||||
out << "@0x" << std::hex << ghost.convert<u64>() << std::dec << ">";
|
out << "@0x" << std::hex << ghost.convert<u64>() << std::dec << ">";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nas_co::clear() {
|
std::ostream& operator<<(std::ostream& out, const nas_co& co) {
|
||||||
if (!ctx.stack) {
|
out << "<coroutine at 0x" << std::hex;
|
||||||
return;
|
out << reinterpret_cast<u64>(&co) << std::dec << ">";
|
||||||
}
|
return out;
|
||||||
for (u32 i = 0; i<VM_STACK_DEPTH; ++i) {
|
}
|
||||||
ctx.stack[i] = var::nil();
|
|
||||||
}
|
var nas_map::get_value(const std::string& key) {
|
||||||
|
if (mapper.count(key)) {
|
||||||
ctx.pc = 0;
|
return *mapper.at(key);
|
||||||
ctx.localr = nullptr;
|
}
|
||||||
ctx.memr = nullptr;
|
return var::none();
|
||||||
ctx.canary = ctx.stack+VM_STACK_DEPTH-1;
|
}
|
||||||
ctx.top = ctx.stack;
|
|
||||||
ctx.funcr = var::nil();
|
var* nas_map::get_memory(const std::string& key) {
|
||||||
ctx.upvalr = var::nil();
|
if (mapper.count(key)) {
|
||||||
|
return mapper.at(key);
|
||||||
status = status::suspended;
|
}
|
||||||
}
|
return nullptr;
|
||||||
|
}
|
||||||
std::ostream& operator<<(std::ostream& out, const nas_co& co) {
|
|
||||||
out << "<coroutine at 0x" << std::hex;
|
std::ostream& operator<<(std::ostream& out, nas_map& mp) {
|
||||||
out << reinterpret_cast<u64>(&co) << std::dec << ">";
|
if (!mp.mapper.size() || mp.printed) {
|
||||||
return out;
|
out << (mp.mapper.size()? "{..}":"{}");
|
||||||
}
|
return out;
|
||||||
|
}
|
||||||
var nas_map::get_value(const std::string& key) {
|
|
||||||
if (mapper.count(key)) {
|
// mark print, to avoid infinite recursion
|
||||||
return *mapper.at(key);
|
mp.printed = true;
|
||||||
}
|
|
||||||
return var::none();
|
static const char* sep[] = {", ", "}"};
|
||||||
}
|
usize iter = 0, size = mp.mapper.size();
|
||||||
|
out << "{";
|
||||||
var* nas_map::get_memory(const std::string& key) {
|
for (auto& i : mp.mapper) {
|
||||||
if (mapper.count(key)) {
|
out << i.first << ": " << *i.second << sep[(++iter)==size];
|
||||||
return mapper.at(key);
|
}
|
||||||
}
|
|
||||||
return nullptr;
|
// restore flag
|
||||||
}
|
mp.printed = false;
|
||||||
|
return out;
|
||||||
std::ostream& operator<<(std::ostream& out, nas_map& mp) {
|
}
|
||||||
if (!mp.mapper.size() || mp.printed) {
|
|
||||||
out << (mp.mapper.size()? "{..}":"{}");
|
nas_val::nas_val(vm_type val_type) {
|
||||||
return out;
|
mark = gc_status::collected;
|
||||||
}
|
type = val_type;
|
||||||
|
immutable = 0;
|
||||||
// mark print, to avoid infinite recursion
|
switch(val_type) {
|
||||||
mp.printed = true;
|
case vm_type::vm_str: ptr.str = new std::string; break;
|
||||||
|
case vm_type::vm_vec: ptr.vec = new nas_vec; break;
|
||||||
static const char* sep[] = {", ", "}"};
|
case vm_type::vm_hash: ptr.hash = new nas_hash; break;
|
||||||
usize iter = 0, size = mp.mapper.size();
|
case vm_type::vm_func: ptr.func = new nas_func; break;
|
||||||
out << "{";
|
case vm_type::vm_upval: ptr.upval = new nas_upval; break;
|
||||||
for (auto& i : mp.mapper) {
|
case vm_type::vm_ghost: ptr.obj = new nas_ghost; break;
|
||||||
out << i.first << ": " << *i.second << sep[(++iter)==size];
|
case vm_type::vm_co: ptr.co = new nas_co; break;
|
||||||
}
|
case vm_type::vm_map: ptr.map = new nas_map; break;
|
||||||
|
default: break;
|
||||||
// restore flag
|
}
|
||||||
mp.printed = false;
|
}
|
||||||
return out;
|
|
||||||
}
|
nas_val::~nas_val() {
|
||||||
|
switch(type) {
|
||||||
nas_val::nas_val(vm_type val_type) {
|
case vm_type::vm_str: delete ptr.str; break;
|
||||||
mark = gc_status::collected;
|
case vm_type::vm_vec: delete ptr.vec; break;
|
||||||
type = val_type;
|
case vm_type::vm_hash: delete ptr.hash; break;
|
||||||
immutable = 0;
|
case vm_type::vm_func: delete ptr.func; break;
|
||||||
switch(val_type) {
|
case vm_type::vm_upval: delete ptr.upval; break;
|
||||||
case vm_type::vm_str: ptr.str = new std::string; break;
|
case vm_type::vm_ghost: delete ptr.obj; break;
|
||||||
case vm_type::vm_vec: ptr.vec = new nas_vec; break;
|
case vm_type::vm_co: delete ptr.co; break;
|
||||||
case vm_type::vm_hash: ptr.hash = new nas_hash; break;
|
case vm_type::vm_map: delete ptr.map; break;
|
||||||
case vm_type::vm_func: ptr.func = new nas_func; break;
|
default: break;
|
||||||
case vm_type::vm_upval: ptr.upval = new nas_upval; break;
|
}
|
||||||
case vm_type::vm_ghost: ptr.obj = new nas_ghost; break;
|
type = vm_type::vm_nil;
|
||||||
case vm_type::vm_co: ptr.co = new nas_co; break;
|
}
|
||||||
case vm_type::vm_map: ptr.map = new nas_map; break;
|
|
||||||
default: break;
|
void nas_val::clear() {
|
||||||
}
|
switch(type) {
|
||||||
}
|
case vm_type::vm_str: ptr.str->clear(); break;
|
||||||
|
case vm_type::vm_vec: ptr.vec->elems.clear(); break;
|
||||||
nas_val::~nas_val() {
|
case vm_type::vm_hash: ptr.hash->elems.clear(); break;
|
||||||
switch(type) {
|
case vm_type::vm_func: ptr.func->clear(); break;
|
||||||
case vm_type::vm_str: delete ptr.str; break;
|
case vm_type::vm_upval: ptr.upval->clear(); break;
|
||||||
case vm_type::vm_vec: delete ptr.vec; break;
|
case vm_type::vm_ghost: ptr.obj->clear(); break;
|
||||||
case vm_type::vm_hash: delete ptr.hash; break;
|
case vm_type::vm_co: ptr.co->clear(); break;
|
||||||
case vm_type::vm_func: delete ptr.func; break;
|
case vm_type::vm_map: ptr.map->clear(); break;
|
||||||
case vm_type::vm_upval: delete ptr.upval; break;
|
default: break;
|
||||||
case vm_type::vm_ghost: delete ptr.obj; break;
|
}
|
||||||
case vm_type::vm_co: delete ptr.co; break;
|
}
|
||||||
case vm_type::vm_map: delete ptr.map; break;
|
|
||||||
default: break;
|
std::string var::to_str() {
|
||||||
}
|
if (type==vm_type::vm_str) {
|
||||||
type = vm_type::vm_nil;
|
return str();
|
||||||
}
|
} else if (type==vm_type::vm_num) {
|
||||||
|
auto tmp = std::to_string(num());
|
||||||
void nas_val::clear() {
|
tmp.erase(tmp.find_last_not_of('0') + 1, std::string::npos);
|
||||||
switch(type) {
|
tmp.erase(tmp.find_last_not_of('.') + 1, std::string::npos);
|
||||||
case vm_type::vm_str: ptr.str->clear(); break;
|
return tmp;
|
||||||
case vm_type::vm_vec: ptr.vec->elems.clear(); break;
|
}
|
||||||
case vm_type::vm_hash: ptr.hash->elems.clear(); break;
|
|
||||||
case vm_type::vm_func: ptr.func->clear(); break;
|
std::stringstream ss;
|
||||||
case vm_type::vm_upval: ptr.upval->clear(); break;
|
ss << *this;
|
||||||
case vm_type::vm_ghost: ptr.obj->clear(); break;
|
return ss.str();
|
||||||
case vm_type::vm_co: ptr.co->clear(); break;
|
}
|
||||||
case vm_type::vm_map: ptr.map->clear(); break;
|
|
||||||
default: break;
|
std::ostream& operator<<(std::ostream& out, var& ref) {
|
||||||
}
|
switch(ref.type) {
|
||||||
}
|
case vm_type::vm_none: out << "undefined"; break;
|
||||||
|
case vm_type::vm_nil: out << "nil"; break;
|
||||||
std::string var::to_str() {
|
case vm_type::vm_num: out << ref.val.num; break;
|
||||||
if (type==vm_type::vm_str) {
|
case vm_type::vm_str: out << ref.str(); break;
|
||||||
return str();
|
case vm_type::vm_vec: out << ref.vec(); break;
|
||||||
} else if (type==vm_type::vm_num) {
|
case vm_type::vm_hash: out << ref.hash(); break;
|
||||||
auto tmp = std::to_string(num());
|
case vm_type::vm_func: out << ref.func(); break;
|
||||||
tmp.erase(tmp.find_last_not_of('0') + 1, std::string::npos);
|
case vm_type::vm_ghost: out << ref.ghost(); break;
|
||||||
tmp.erase(tmp.find_last_not_of('.') + 1, std::string::npos);
|
case vm_type::vm_co: out << ref.co(); break;
|
||||||
return tmp;
|
case vm_type::vm_map: out << ref.map(); break;
|
||||||
}
|
default: break;
|
||||||
|
}
|
||||||
std::stringstream ss;
|
return out;
|
||||||
ss << *this;
|
}
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& out, var& ref) {
|
|
||||||
switch(ref.type) {
|
|
||||||
case vm_type::vm_none: out << "undefined"; break;
|
|
||||||
case vm_type::vm_nil: out << "nil"; break;
|
|
||||||
case vm_type::vm_num: out << ref.val.num; break;
|
|
||||||
case vm_type::vm_str: out << ref.str(); break;
|
|
||||||
case vm_type::vm_vec: out << ref.vec(); break;
|
|
||||||
case vm_type::vm_hash: out << ref.hash(); break;
|
|
||||||
case vm_type::vm_func: out << ref.func(); break;
|
|
||||||
case vm_type::vm_ghost: out << ref.ghost(); break;
|
|
||||||
case vm_type::vm_co: out << ref.co(); break;
|
|
||||||
case vm_type::vm_map: out << ref.map(); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
758
src/nasal_type.h
758
src/nasal_type.h
@@ -1,362 +1,398 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal.h"
|
#include "nasal.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
enum class vm_type: u8 {
|
enum class vm_type: u8 {
|
||||||
/* none-gc object */
|
/* none-gc object */
|
||||||
vm_none = 0, // error type
|
vm_none = 0, // error type
|
||||||
vm_cnt, // counter for forindex/foreach loop
|
vm_cnt, // counter for forindex/foreach loop
|
||||||
vm_addr, // var* address
|
vm_addr, // var* address
|
||||||
vm_ret, // return addres(program counter)
|
vm_ret, // return addres(program counter)
|
||||||
vm_nil, // nil
|
vm_nil, // nil
|
||||||
vm_num, // number
|
vm_num, // number
|
||||||
|
|
||||||
/* gc object */
|
/* gc object */
|
||||||
vm_str, // string
|
vm_str, // string
|
||||||
vm_vec, // vector
|
vm_vec, // vector
|
||||||
vm_hash, // hashmap(dict)
|
vm_hash, // hashmap(dict)
|
||||||
vm_func, // function(lambda)
|
vm_func, // function(lambda)
|
||||||
vm_upval, // upvalue
|
vm_upval, // upvalue
|
||||||
vm_ghost, // ghost type
|
vm_ghost, // ghost type
|
||||||
vm_co, // coroutine
|
vm_co, // coroutine
|
||||||
vm_map, // for globals and namespaces
|
vm_map, // for globals and namespaces
|
||||||
|
|
||||||
/* mark type range */
|
/* mark type range */
|
||||||
vm_type_size_max
|
vm_type_size_max
|
||||||
};
|
};
|
||||||
|
|
||||||
// size of gc object type
|
// size of gc object type
|
||||||
const u32 GC_TYPE_SIZE =
|
const u32 GC_TYPE_SIZE =
|
||||||
static_cast<u32>(vm_type::vm_type_size_max) -
|
static_cast<u32>(vm_type::vm_type_size_max) -
|
||||||
static_cast<u32>(vm_type::vm_str);
|
static_cast<u32>(vm_type::vm_str);
|
||||||
|
|
||||||
// basic types
|
// basic types
|
||||||
struct nas_vec; // vector
|
struct nas_vec; // vector
|
||||||
struct nas_hash; // hashmap(dict)
|
struct nas_hash; // hashmap(dict)
|
||||||
struct nas_func; // function(lambda)
|
struct nas_func; // function(lambda)
|
||||||
struct nas_upval; // upvalue
|
struct nas_upval; // upvalue
|
||||||
struct nas_ghost; // objects
|
struct nas_ghost; // objects
|
||||||
struct nas_co; // coroutine
|
struct nas_co; // coroutine
|
||||||
struct nas_map; // mapper
|
struct nas_map; // mapper
|
||||||
|
|
||||||
// nas_val includes gc-managed types
|
// nas_val includes gc-managed types
|
||||||
struct nas_val {
|
struct nas_val {
|
||||||
enum class gc_status: u8 {
|
enum class gc_status: u8 {
|
||||||
uncollected = 0,
|
uncollected = 0,
|
||||||
collected,
|
collected,
|
||||||
found
|
found
|
||||||
};
|
};
|
||||||
|
|
||||||
gc_status mark;
|
gc_status mark;
|
||||||
vm_type type; // value type
|
vm_type type; // value type
|
||||||
u8 immutable; // used to mark if a string is immutable
|
u8 immutable; // used to mark if a string is immutable
|
||||||
union elem {
|
union elem {
|
||||||
std::string* str;
|
std::string* str;
|
||||||
nas_vec* vec;
|
nas_vec* vec;
|
||||||
nas_hash* hash;
|
nas_hash* hash;
|
||||||
nas_func* func;
|
nas_func* func;
|
||||||
nas_upval* upval;
|
nas_upval* upval;
|
||||||
nas_ghost* obj;
|
nas_ghost* obj;
|
||||||
nas_co* co;
|
nas_co* co;
|
||||||
nas_map* map;
|
nas_map* map;
|
||||||
} ptr;
|
} ptr;
|
||||||
|
|
||||||
nas_val(vm_type);
|
nas_val(vm_type);
|
||||||
~nas_val();
|
~nas_val();
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct var {
|
struct var {
|
||||||
public:
|
public:
|
||||||
vm_type type = vm_type::vm_none;
|
vm_type type = vm_type::vm_none;
|
||||||
union {
|
union {
|
||||||
u64 ret;
|
u64 ret;
|
||||||
i64 cnt;
|
i64 cnt;
|
||||||
f64 num;
|
f64 num;
|
||||||
var* addr;
|
var* addr;
|
||||||
nas_val* gcobj;
|
nas_val* gcobj;
|
||||||
} val;
|
} val;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
var(vm_type t, u64 pc) { type = t; val.ret = pc; }
|
var(vm_type t, u64 pc) { type = t; val.ret = pc; }
|
||||||
var(vm_type t, i64 ct) { type = t; val.cnt = ct; }
|
var(vm_type t, i64 ct) { type = t; val.cnt = ct; }
|
||||||
var(vm_type t, f64 n) { type = t; val.num = n; }
|
var(vm_type t, f64 n) { type = t; val.num = n; }
|
||||||
var(vm_type t, var* p) { type = t; val.addr = p; }
|
var(vm_type t, var* p) { type = t; val.addr = p; }
|
||||||
var(vm_type t, nas_val* p) { type = t; val.gcobj = p; }
|
var(vm_type t, nas_val* p) { type = t; val.gcobj = p; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
var() = default;
|
var() = default;
|
||||||
var(const var&) = default;
|
var(const var&) = default;
|
||||||
bool operator==(const var& nr) const {
|
bool operator==(const var& nr) const {
|
||||||
return type == nr.type && val.gcobj == nr.val.gcobj;
|
return type == nr.type && val.gcobj == nr.val.gcobj;
|
||||||
}
|
}
|
||||||
bool operator!=(const var& nr) const {
|
bool operator!=(const var& nr) const {
|
||||||
return type != nr.type || val.gcobj != nr.val.gcobj;
|
return type != nr.type || val.gcobj != nr.val.gcobj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// create new var object
|
// create new var object
|
||||||
static var none() {
|
static var none() {
|
||||||
return var(vm_type::vm_none, static_cast<u64>(0));
|
return var(vm_type::vm_none, static_cast<u64>(0));
|
||||||
}
|
}
|
||||||
static var nil() {
|
static var nil() {
|
||||||
return var(vm_type::vm_nil, static_cast<u64>(0));
|
return var(vm_type::vm_nil, static_cast<u64>(0));
|
||||||
}
|
}
|
||||||
static var ret(u64 pc) {
|
static var ret(u64 pc) {
|
||||||
return var(vm_type::vm_ret, pc);
|
return var(vm_type::vm_ret, pc);
|
||||||
}
|
}
|
||||||
static var cnt(i64 n) {
|
static var cnt(i64 n) {
|
||||||
return var(vm_type::vm_cnt, n);
|
return var(vm_type::vm_cnt, n);
|
||||||
}
|
}
|
||||||
static var num(f64 n) {
|
static var num(f64 n) {
|
||||||
return var(vm_type::vm_num, n);
|
return var(vm_type::vm_num, n);
|
||||||
}
|
}
|
||||||
static var gcobj(nas_val* p) {
|
static var gcobj(nas_val* p) {
|
||||||
return var(p->type, p);
|
return var(p->type, p);
|
||||||
}
|
}
|
||||||
static var addr(var* p) {
|
static var addr(var* p) {
|
||||||
return var(vm_type::vm_addr, p);
|
return var(vm_type::vm_addr, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// get value
|
// get value
|
||||||
var* addr() const { return val.addr; }
|
var* addr() const { return val.addr; }
|
||||||
u64 ret() const { return val.ret; }
|
u64 ret() const { return val.ret; }
|
||||||
i64& cnt() { return val.cnt; }
|
i64& cnt() { return val.cnt; }
|
||||||
f64 num() const { return val.num; }
|
f64 num() const { return val.num; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// get gc object
|
// get gc object
|
||||||
std::string& str() { return *val.gcobj->ptr.str; }
|
std::string& str() { return *val.gcobj->ptr.str; }
|
||||||
nas_vec& vec() { return *val.gcobj->ptr.vec; }
|
nas_vec& vec() { return *val.gcobj->ptr.vec; }
|
||||||
nas_hash& hash() { return *val.gcobj->ptr.hash; }
|
nas_hash& hash() { return *val.gcobj->ptr.hash; }
|
||||||
nas_func& func() { return *val.gcobj->ptr.func; }
|
nas_func& func() { return *val.gcobj->ptr.func; }
|
||||||
nas_upval& upval() { return *val.gcobj->ptr.upval; }
|
nas_upval& upval() { return *val.gcobj->ptr.upval; }
|
||||||
nas_ghost& ghost() { return *val.gcobj->ptr.obj; }
|
nas_ghost& ghost() { return *val.gcobj->ptr.obj; }
|
||||||
nas_co& co() { return *val.gcobj->ptr.co; }
|
nas_co& co() { return *val.gcobj->ptr.co; }
|
||||||
nas_map& map() { return *val.gcobj->ptr.map; }
|
nas_map& map() { return *val.gcobj->ptr.map; }
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// get const gc object
|
// get const gc object
|
||||||
const std::string& str() const { return *val.gcobj->ptr.str; }
|
const std::string& str() const { return *val.gcobj->ptr.str; }
|
||||||
const nas_vec& vec() const { return *val.gcobj->ptr.vec; }
|
const nas_vec& vec() const { return *val.gcobj->ptr.vec; }
|
||||||
const nas_hash& hash() const { return *val.gcobj->ptr.hash; }
|
const nas_hash& hash() const { return *val.gcobj->ptr.hash; }
|
||||||
const nas_func& func() const { return *val.gcobj->ptr.func; }
|
const nas_func& func() const { return *val.gcobj->ptr.func; }
|
||||||
const nas_upval& upval() const { return *val.gcobj->ptr.upval; }
|
const nas_upval& upval() const { return *val.gcobj->ptr.upval; }
|
||||||
const nas_ghost& ghost() const { return *val.gcobj->ptr.obj; }
|
const nas_ghost& ghost() const { return *val.gcobj->ptr.obj; }
|
||||||
const nas_co& co() const { return *val.gcobj->ptr.co; }
|
const nas_co& co() const { return *val.gcobj->ptr.co; }
|
||||||
const nas_map& map() const { return *val.gcobj->ptr.map; }
|
const nas_map& map() const { return *val.gcobj->ptr.map; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool is_none() const { return type == vm_type::vm_none; }
|
bool is_none() const { return type == vm_type::vm_none; }
|
||||||
bool is_cnt() const { return type == vm_type::vm_cnt; }
|
bool is_cnt() const { return type == vm_type::vm_cnt; }
|
||||||
bool is_addr() const { return type == vm_type::vm_addr; }
|
bool is_addr() const { return type == vm_type::vm_addr; }
|
||||||
bool is_ret() const { return type == vm_type::vm_ret; }
|
bool is_ret() const { return type == vm_type::vm_ret; }
|
||||||
bool is_nil() const { return type == vm_type::vm_nil; }
|
bool is_nil() const { return type == vm_type::vm_nil; }
|
||||||
bool is_num() const { return type == vm_type::vm_num; }
|
bool is_num() const { return type == vm_type::vm_num; }
|
||||||
bool is_str() const { return type == vm_type::vm_str; }
|
bool is_str() const { return type == vm_type::vm_str; }
|
||||||
bool is_vec() const { return type == vm_type::vm_vec; }
|
bool is_vec() const { return type == vm_type::vm_vec; }
|
||||||
bool is_hash() const { return type == vm_type::vm_hash; }
|
bool is_hash() const { return type == vm_type::vm_hash; }
|
||||||
bool is_func() const { return type == vm_type::vm_func; }
|
bool is_func() const { return type == vm_type::vm_func; }
|
||||||
bool is_upval() const { return type == vm_type::vm_upval; }
|
bool is_upval() const { return type == vm_type::vm_upval; }
|
||||||
bool is_ghost() const { return type == vm_type::vm_ghost; }
|
bool is_ghost() const { return type == vm_type::vm_ghost; }
|
||||||
bool is_coroutine() const { return type == vm_type::vm_co; }
|
bool is_coroutine() const { return type == vm_type::vm_co; }
|
||||||
bool is_map() const { return type == vm_type::vm_map; }
|
bool is_map() const { return type == vm_type::vm_map; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// convert to number
|
// convert to number
|
||||||
f64 to_num() const {
|
f64 to_num() const {
|
||||||
return type != vm_type::vm_str
|
return type != vm_type::vm_str
|
||||||
? val.num
|
? val.num
|
||||||
: util::str_to_num(str().c_str());
|
: util::str_to_num(str().c_str());
|
||||||
}
|
}
|
||||||
// convert to string
|
// convert to string
|
||||||
std::string to_str();
|
std::string to_str();
|
||||||
inline bool object_check(const std::string&) const;
|
inline bool object_check(const std::string&) const;
|
||||||
friend std::ostream& operator<<(std::ostream&, var&);
|
friend std::ostream& operator<<(std::ostream&, var&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_vec {
|
struct nas_vec {
|
||||||
std::vector<var> elems;
|
std::vector<var> elems;
|
||||||
|
|
||||||
// mark if this is printed, avoid stack overflow
|
// mark if this is printed, avoid stack overflow
|
||||||
bool printed = false;
|
bool printed = false;
|
||||||
|
|
||||||
auto size() const { return elems.size(); }
|
auto size() const { return elems.size(); }
|
||||||
var get_value(const i32 index) {
|
var get_value(const i32 index) {
|
||||||
i32 size = elems.size();
|
i32 size = elems.size();
|
||||||
if (index < -size || index >= size) {
|
if (index < -size || index >= size) {
|
||||||
return var::none();
|
return var::none();
|
||||||
}
|
}
|
||||||
return elems[index >= 0 ? index : index + size];
|
return elems[index >= 0 ? index : index + size];
|
||||||
}
|
}
|
||||||
var* get_memory(const i32 index) {
|
var* get_memory(const i32 index) {
|
||||||
i32 size = elems.size();
|
i32 size = elems.size();
|
||||||
if (index < -size || index >= size) {
|
if (index < -size || index >= size) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &elems[index >= 0 ? index : index + size];
|
return &elems[index >= 0 ? index : index + size];
|
||||||
}
|
}
|
||||||
friend std::ostream& operator<<(std::ostream&, nas_vec&);
|
friend std::ostream& operator<<(std::ostream&, nas_vec&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_hash {
|
struct nas_hash {
|
||||||
std::unordered_map<std::string, var> elems;
|
std::unordered_map<std::string, var> elems;
|
||||||
|
|
||||||
// mark if this is printed, avoid stack overflow
|
// mark if this is printed, avoid stack overflow
|
||||||
bool printed = false;
|
bool printed = false;
|
||||||
|
|
||||||
auto size() const { return elems.size(); }
|
auto size() const { return elems.size(); }
|
||||||
var get_value(const std::string&);
|
var get_value(const std::string&);
|
||||||
var* get_memory(const std::string&);
|
var* get_memory(const std::string&);
|
||||||
friend std::ostream& operator<<(std::ostream&, nas_hash&);
|
friend std::ostream& operator<<(std::ostream&, nas_hash&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_func {
|
struct nas_func {
|
||||||
i64 dynamic_parameter_index; // dynamic parameter name index in hash.
|
i64 dynamic_parameter_index; // dynamic parameter name index in hash.
|
||||||
u64 entry; // pc will set to entry-1 to call this function
|
u64 entry; // pc will set to entry-1 to call this function
|
||||||
u32 parameter_size; // used to load default parameters to a new function
|
u32 parameter_size; // used to load default parameters to a new function
|
||||||
u64 local_size; // used to expand memory space for local values on stack
|
u64 local_size; // used to expand memory space for local values on stack
|
||||||
std::vector<var> local; // local scope with default value(var)
|
std::vector<var> local; // local scope with default value(var)
|
||||||
std::vector<var> upval; // closure
|
std::vector<var> upval; // closure
|
||||||
|
|
||||||
// parameter table, u32 begins from 1
|
// parameter table, u32 begins from 1
|
||||||
std::unordered_map<std::string, u32> keys;
|
std::unordered_map<std::string, u32> keys;
|
||||||
|
|
||||||
// dynamic parameter name
|
// dynamic parameter name
|
||||||
std::string dynamic_parameter_name;
|
std::string dynamic_parameter_name;
|
||||||
|
|
||||||
nas_func():
|
nas_func():
|
||||||
dynamic_parameter_index(-1), entry(0),
|
dynamic_parameter_index(-1), entry(0),
|
||||||
parameter_size(0), local_size(0),
|
parameter_size(0), local_size(0),
|
||||||
dynamic_parameter_name("") {}
|
dynamic_parameter_name("") {}
|
||||||
void clear();
|
void clear();
|
||||||
friend std::ostream& operator<<(std::ostream&, nas_func&);
|
friend std::ostream& operator<<(std::ostream&, nas_func&);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_upval {
|
struct nas_upval {
|
||||||
public:
|
public:
|
||||||
/* on stack, use these variables */
|
/* on stack, use these variables */
|
||||||
bool on_stack;
|
bool on_stack;
|
||||||
u64 size;
|
u64 size;
|
||||||
var* stack_frame_offset;
|
var* stack_frame_offset;
|
||||||
|
|
||||||
/* not on stack, use this */
|
/* not on stack, use this */
|
||||||
std::vector<var> elems;
|
std::vector<var> elems;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_upval(): on_stack(true), size(0), stack_frame_offset(nullptr) {}
|
nas_upval(): on_stack(true), size(0), stack_frame_offset(nullptr) {}
|
||||||
|
|
||||||
var& operator[](usize n) {
|
var& operator[](usize n) {
|
||||||
return on_stack? stack_frame_offset[n] : elems[n];
|
return on_stack? stack_frame_offset[n] : elems[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
on_stack = true;
|
on_stack = true;
|
||||||
elems.clear();
|
elems.clear();
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct nas_ghost {
|
struct nas_ghost {
|
||||||
private:
|
private:
|
||||||
using destructor = void (*)(void*);
|
using destructor = void (*)(void*);
|
||||||
using marker = void (*)(void*, std::vector<var>*);
|
using marker = void (*)(void*, std::vector<var>*);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string type_name;
|
std::string type_name;
|
||||||
destructor destructor_function;
|
destructor destructor_function;
|
||||||
marker gc_mark_function;
|
marker gc_mark_function;
|
||||||
void* pointer;
|
void* pointer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
nas_ghost():
|
nas_ghost():
|
||||||
type_name(""), destructor_function(nullptr),
|
type_name(""), destructor_function(nullptr),
|
||||||
gc_mark_function(nullptr), pointer(nullptr) {}
|
gc_mark_function(nullptr), pointer(nullptr) {}
|
||||||
~nas_ghost() { clear(); }
|
~nas_ghost() { clear(); }
|
||||||
void set(const std::string&, destructor, marker, void*);
|
void set(const std::string&, destructor, marker, void*);
|
||||||
void clear();
|
void clear();
|
||||||
friend std::ostream& operator<<(std::ostream&, const nas_ghost&);
|
friend std::ostream& operator<<(std::ostream&, const nas_ghost&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const auto& get_ghost_name() const { return type_name; }
|
const auto& get_ghost_name() const { return type_name; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* get() { return static_cast<T*>(pointer); }
|
T* get() { return static_cast<T*>(pointer); }
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T convert() const { return reinterpret_cast<T>(pointer); }
|
T convert() const { return reinterpret_cast<T>(pointer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct context {
|
struct callsite {
|
||||||
u64 pc = 0;
|
var caller;
|
||||||
var* localr = nullptr;
|
u64 file_index = 0;
|
||||||
var* memr = nullptr;
|
u64 line = 0;
|
||||||
var funcr = var::nil();
|
};
|
||||||
var upvalr = var::nil();
|
|
||||||
var* canary = nullptr;
|
struct context {
|
||||||
var* stack = nullptr;
|
u64 pc = 0;
|
||||||
var* top = nullptr;
|
var* localr = nullptr;
|
||||||
};
|
var* memr = nullptr;
|
||||||
|
var funcr = var::nil();
|
||||||
struct nas_co {
|
var upvalr = var::nil();
|
||||||
enum class status:u32 {
|
var* canary = nullptr;
|
||||||
suspended,
|
|
||||||
running,
|
var* stack = nullptr;
|
||||||
dead
|
var* top = nullptr;
|
||||||
};
|
|
||||||
|
callsite* func_stack = nullptr;
|
||||||
context ctx;
|
callsite* func_top = nullptr;
|
||||||
status status;
|
|
||||||
|
const std::string* files = nullptr;
|
||||||
nas_co() {
|
|
||||||
ctx.stack = new var[VM_STACK_DEPTH];
|
void ctor() {
|
||||||
clear();
|
stack = new var[VM_STACK_DEPTH];
|
||||||
}
|
func_stack = new callsite[VM_STACK_DEPTH];
|
||||||
~nas_co() {
|
}
|
||||||
delete[] ctx.stack;
|
void dtor() {
|
||||||
}
|
delete[] stack;
|
||||||
void clear();
|
delete[] func_stack;
|
||||||
friend std::ostream& operator<<(std::ostream&, const nas_co&);
|
}
|
||||||
};
|
void clear() {
|
||||||
|
/* set canary and program counter */
|
||||||
struct nas_map {
|
pc = 0;
|
||||||
bool printed = false;
|
localr = nullptr;
|
||||||
std::unordered_map<std::string, var*> mapper;
|
memr = nullptr;
|
||||||
|
funcr = var::nil();
|
||||||
public:
|
upvalr = var::nil();
|
||||||
void clear() {
|
|
||||||
mapper.clear();
|
/* set canary = stack[VM_STACK_DEPTH-1] */
|
||||||
}
|
canary = stack + VM_STACK_DEPTH - 1;
|
||||||
auto size() const { return mapper.size(); }
|
|
||||||
|
/* nothing is on stack */
|
||||||
var get_value(const std::string&);
|
top = stack;
|
||||||
var* get_memory(const std::string&);
|
func_top = func_stack - 1;
|
||||||
friend std::ostream& operator<<(std::ostream&, nas_map&);
|
|
||||||
};
|
/* clear main stack */
|
||||||
|
for (u32 i = 0; i < VM_STACK_DEPTH; ++i) {
|
||||||
const var zero = var::num(0);
|
stack[i] = var::nil();
|
||||||
const var one = var::num(1);
|
}
|
||||||
const var nil = var::nil();
|
}
|
||||||
|
};
|
||||||
inline bool var::object_check(const std::string& name) const {
|
|
||||||
return is_ghost() && ghost().type_name == name && ghost().pointer;
|
struct nas_co {
|
||||||
}
|
enum class status:u32 {
|
||||||
|
suspended,
|
||||||
// use to print error log and return error value
|
running,
|
||||||
static var nas_err(const std::string& func, const std::string& info) {
|
dead
|
||||||
std::cerr << "[vm] " << func << ": " << info << "\n";
|
};
|
||||||
return var::none();
|
|
||||||
}
|
context ctx;
|
||||||
|
status status;
|
||||||
|
|
||||||
|
nas_co() { ctx.ctor(); }
|
||||||
|
~nas_co() { ctx.dtor(); }
|
||||||
|
void clear() { ctx.clear(); status = status::suspended; }
|
||||||
|
friend std::ostream& operator<<(std::ostream&, const nas_co&);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nas_map {
|
||||||
|
bool printed = false;
|
||||||
|
std::unordered_map<std::string, var*> mapper;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void clear() {
|
||||||
|
mapper.clear();
|
||||||
|
}
|
||||||
|
auto size() const { return mapper.size(); }
|
||||||
|
|
||||||
|
var get_value(const std::string&);
|
||||||
|
var* get_memory(const std::string&);
|
||||||
|
friend std::ostream& operator<<(std::ostream&, nas_map&);
|
||||||
|
};
|
||||||
|
|
||||||
|
const var zero = var::num(0);
|
||||||
|
const var one = var::num(1);
|
||||||
|
const var nil = var::nil();
|
||||||
|
|
||||||
|
inline bool var::object_check(const std::string& name) const {
|
||||||
|
return is_ghost() && ghost().type_name == name && ghost().pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use to print error log and return error value
|
||||||
|
static var nas_err(const std::string& func, const std::string& info) {
|
||||||
|
std::cerr << "[vm] " << func << ": " << info << "\n";
|
||||||
|
return var::none();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
1655
src/nasal_vm.cpp
1655
src/nasal_vm.cpp
File diff suppressed because it is too large
Load Diff
@@ -287,11 +287,11 @@ public:
|
|||||||
|
|
||||||
/* constructor of vm instance */
|
/* constructor of vm instance */
|
||||||
vm() {
|
vm() {
|
||||||
ctx.stack = new var[VM_STACK_DEPTH];
|
ctx.ctor();
|
||||||
global = new var[VM_STACK_DEPTH];
|
global = new var[VM_STACK_DEPTH];
|
||||||
}
|
}
|
||||||
~vm() {
|
~vm() {
|
||||||
delete[] ctx.stack;
|
ctx.dtor();
|
||||||
delete[] global;
|
delete[] global;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -900,6 +900,11 @@ inline void vm::o_callfv() {
|
|||||||
var tmp = local[-1];
|
var tmp = local[-1];
|
||||||
local[-1] = ctx.funcr;
|
local[-1] = ctx.funcr;
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
|
(++ctx.func_top)[0] = {
|
||||||
|
tmp,
|
||||||
|
bytecode[ctx.pc].fidx,
|
||||||
|
bytecode[ctx.pc].line
|
||||||
|
};
|
||||||
|
|
||||||
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
if (ctx.top-argc+func.local_size+3>=ctx.canary) {
|
||||||
@@ -969,6 +974,11 @@ inline void vm::o_callfh() {
|
|||||||
var tmp = ctx.top[-1];
|
var tmp = ctx.top[-1];
|
||||||
ctx.top[-1] = ctx.funcr;
|
ctx.top[-1] = ctx.funcr;
|
||||||
ctx.funcr = tmp;
|
ctx.funcr = tmp;
|
||||||
|
(++ctx.func_top)[0] = {
|
||||||
|
tmp,
|
||||||
|
bytecode[ctx.pc].fidx,
|
||||||
|
bytecode[ctx.pc].line
|
||||||
|
};
|
||||||
|
|
||||||
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
// top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
if (ctx.top+func.local_size+2>= ctx.canary) {
|
if (ctx.top+func.local_size+2>= ctx.canary) {
|
||||||
@@ -1011,6 +1021,9 @@ inline void vm::o_callb() {
|
|||||||
// this code is written for coroutine
|
// this code is written for coroutine
|
||||||
(++ctx.top)[0] = nil;
|
(++ctx.top)[0] = nil;
|
||||||
|
|
||||||
|
// set file list into ctx
|
||||||
|
ctx.files = files;
|
||||||
|
|
||||||
// if running a native function about coroutine
|
// if running a native function about coroutine
|
||||||
// (top) will be set to another context.top, instead of main_context.top
|
// (top) will be set to another context.top, instead of main_context.top
|
||||||
auto function_pointer = native_function[imm[ctx.pc]].func;
|
auto function_pointer = native_function[imm[ctx.pc]].func;
|
||||||
@@ -1212,6 +1225,7 @@ inline void vm::o_ret() {
|
|||||||
ctx.top = local-1;
|
ctx.top = local-1;
|
||||||
ctx.funcr = ctx.top[0];
|
ctx.funcr = ctx.top[0];
|
||||||
ctx.top[0] = ret; // rewrite func with returned value
|
ctx.top[0] = ret; // rewrite func with returned value
|
||||||
|
ctx.func_top--;
|
||||||
|
|
||||||
// synchronize upvalue
|
// synchronize upvalue
|
||||||
if (up.is_upval()) {
|
if (up.is_upval()) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -69,6 +69,8 @@ var builtin_platform(context*, gc*);
|
|||||||
var builtin_arch(context*, gc*);
|
var builtin_arch(context*, gc*);
|
||||||
var builtin_version(context*, gc*);
|
var builtin_version(context*, gc*);
|
||||||
|
|
||||||
|
var builtin_caller(context*, gc*);
|
||||||
|
|
||||||
// md5 related functions
|
// md5 related functions
|
||||||
std::string tohex(u32);
|
std::string tohex(u32);
|
||||||
std::string md5(const std::string&);
|
std::string md5(const std::string&);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "ast_visitor.h"
|
#include "ast/ast_visitor.h"
|
||||||
|
|
||||||
namespace nasal {
|
namespace nasal {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nasal_ast.h"
|
#include "ast/ast.h"
|
||||||
#include "ast_visitor.h"
|
#include "ast/ast_visitor.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|||||||
@@ -385,7 +385,8 @@ var call = func(function, args = nil, _me = nil, locals = nil, error = nil) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var caller = func(level = 1) {
|
var caller = func(level = 1) {
|
||||||
die("this runtime does not support caller");
|
# TODO: caller should return [scope, func, call location file, call location line]
|
||||||
|
return __caller(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
var closure = func(function, level = 1) {
|
var closure = func(function, level = 1) {
|
||||||
@@ -415,4 +416,4 @@ var fgcommand = func(cmd, node=nil) {
|
|||||||
# elsif (ishash(node)) node = props.Node.new(node)._g;
|
# elsif (ishash(node)) node = props.Node.new(node)._g;
|
||||||
# _fgcommand(cmd, node);
|
# _fgcommand(cmd, node);
|
||||||
println("in progress, not supported yet.");
|
println("in progress, not supported yet.");
|
||||||
}
|
}
|
||||||
|
|||||||
24
test/caller.nas
Normal file
24
test/caller.nas
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
var a = func(x, y, z) {
|
||||||
|
for (var i = 0; i < 20; i += 1) {
|
||||||
|
var cl = caller(i);
|
||||||
|
if (cl == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print("[", i, "]\t", cl[1], "\t -> called from ", cl[2], ":", cl[3], "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var b = func(x, y) {
|
||||||
|
a(1, 2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = func(x) b(1, 2);
|
||||||
|
var d = func c(1);
|
||||||
|
var e = func d();
|
||||||
|
var f = func e();
|
||||||
|
var g = func f();
|
||||||
|
var h = func g();
|
||||||
|
var i = func h();
|
||||||
|
var j = func i();
|
||||||
|
|
||||||
|
j();
|
||||||
@@ -109,7 +109,7 @@ for (var t = 0; t < 10; t += 1) {
|
|||||||
counter += 1;
|
counter += 1;
|
||||||
for (var i = 0; i < t + 1; i += 1)
|
for (var i = 0; i < t + 1; i += 1)
|
||||||
coroutine.resume(co);
|
coroutine.resume(co);
|
||||||
if (counter - int(counter / 1000) * 1000 == 0) {
|
if (counter - int(counter / 2500) * 2500 == 0) {
|
||||||
var rate = counter / 2e5;
|
var rate = counter / 2e5;
|
||||||
print(" ", bar.bar(rate), " ",
|
print(" ", bar.bar(rate), " ",
|
||||||
padding.leftpad(str(int(rate*100)),3), "% | ",
|
padding.leftpad(str(int(rate*100)),3), "% | ",
|
||||||
@@ -120,7 +120,7 @@ for (var t = 0; t < 10; t += 1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tm.stamp();
|
tm.stamp();
|
||||||
for (var i = 0; i < 1e5; i += 1)
|
for (var i = 0; i < 2e5; i += 1)
|
||||||
consumer();
|
consumer();
|
||||||
println(" ", bar.bar(1), " 100% | ",
|
println(" ", bar.bar(1), " 100% | ",
|
||||||
str(int(1e3 * counter / tm.elapsedMSec())),
|
str(int(1e3 * counter / tm.elapsedMSec())),
|
||||||
|
|||||||
Reference in New Issue
Block a user