Merge pull request #43 from ValKmjolnir/develop
🎨 rename & file structure change & improve ast/gc dump format
This commit is contained in:
commit
0cf8e3bd23
|
@ -1,6 +1,6 @@
|
|||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(nasal VERSION 10.1)
|
||||
project(nasal VERSION 11.2)
|
||||
|
||||
message("CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||
|
||||
|
@ -16,10 +16,8 @@ set(CMAKE_BUILD_TYPE "Release")
|
|||
|
||||
# build nasal used object
|
||||
set(NASAL_OBJECT_SOURCE_FILE
|
||||
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/nasal_builtin.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/cli/cli.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/builtin.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/coroutine.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/fg_props.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/bits_lib.cpp
|
||||
|
@ -29,31 +27,37 @@ set(NASAL_OBJECT_SOURCE_FILE
|
|||
${CMAKE_SOURCE_DIR}/src/natives/dylib_lib.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/regex_lib.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/natives/unix_lib.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/repl/repl.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_dumper.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/ast_visitor.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_ast.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_codegen.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_dbg.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_err.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_import.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_lexer.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_misc.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_opcode.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_parse.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_vm.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/optimizer.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/repl.cpp)
|
||||
${CMAKE_SOURCE_DIR}/src/symbol_finder.cpp)
|
||||
add_library(nasal-object STATIC ${NASAL_OBJECT_SOURCE_FILE})
|
||||
target_include_directories(nasal-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
# build nasal
|
||||
add_executable(nasal ${CMAKE_SOURCE_DIR}/src/main.cpp)
|
||||
target_link_libraries(nasal nasal-object)
|
||||
# link ldl and lpthread
|
||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||
target_link_libraries(nasal dl)
|
||||
target_link_libraries(nasal pthread)
|
||||
endif()
|
||||
target_include_directories(nasal PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
# copy nasal from build dir to the outside dir
|
||||
if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
|
||||
add_custom_command(
|
||||
TARGET nasal POST_BUILD
|
||||
|
@ -67,10 +71,12 @@ endif()
|
|||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/module)
|
||||
|
||||
set(MODULE_USED_OBJECT_SOURCE_FILE
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_misc.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/util.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/util/fs.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_type.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/nasal_gc.cpp)
|
||||
add_library(module-used-object STATIC ${MODULE_USED_OBJECT_SOURCE_FILE})
|
||||
target_include_directories(module-used-object PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
||||
add_library(fib SHARED ${CMAKE_SOURCE_DIR}/module/fib.cpp)
|
||||
target_include_directories(fib PRIVATE ${CMAKE_SOURCE_DIR}/src)
|
||||
|
|
64
README.md
64
README.md
|
@ -26,11 +26,9 @@
|
|||
|
||||
__Contact us if having great ideas to share!__
|
||||
|
||||
* __E-mail__:
|
||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||
|
||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||
|
||||
* __sidi.liang@gmail.com__ (Sidi)
|
||||
* __sidi.liang@gmail.com__ (Sidi)
|
||||
|
||||
## __Introduction__
|
||||
|
||||
|
@ -117,6 +115,14 @@ if (os.platform()=="windows") {
|
|||
}
|
||||
```
|
||||
|
||||
Or use `std.runtime.windows.set_utf8_output()`:
|
||||
|
||||
```javascript
|
||||
use std.runtime;
|
||||
|
||||
runtime.windows.set_utf8_output();
|
||||
```
|
||||
|
||||
## __Difference Between Andy's and This Interpreter__
|
||||
|
||||

|
||||
|
@ -337,9 +343,8 @@ and the debugger will print this:
|
|||
|
||||
```javascript
|
||||
source code:
|
||||
--> var fib=func(x)
|
||||
{
|
||||
if(x<2) return x;
|
||||
--> var fib = func(x) {
|
||||
if (x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
for(var i=0;i<31;i+=1)
|
||||
|
@ -347,16 +352,16 @@ source code:
|
|||
|
||||
|
||||
next bytecode:
|
||||
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
||||
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
||||
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
||||
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
||||
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
||||
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
||||
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
||||
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
||||
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||
--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||
0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||
|
||||
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
||||
vm stack (0x7fca7e9f1010, limit 16, total 0)
|
||||
>>
|
||||
```
|
||||
|
||||
|
@ -371,9 +376,8 @@ This will help you debugging or learning how the vm works:
|
|||
|
||||
```javascript
|
||||
source code:
|
||||
var fib=func(x)
|
||||
{
|
||||
--> if(x<2) return x;
|
||||
var fib = func(x) {
|
||||
--> if (x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
for(var i=0;i<31;i+=1)
|
||||
|
@ -381,24 +385,24 @@ source code:
|
|||
|
||||
|
||||
next bytecode:
|
||||
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
||||
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
||||
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
||||
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
||||
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
||||
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
||||
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||
0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||
--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||
|
||||
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
||||
0x000007 | pc | 0x869
|
||||
vm stack (0x7fca7e9f1010, limit 16, total 8)
|
||||
0x000007 | pc | 0x3c7
|
||||
0x000006 | addr | 0x0
|
||||
0x000005 | nil |
|
||||
0x000004 | nil |
|
||||
0x000003 | num | 0
|
||||
0x000002 | nil |
|
||||
0x000001 | nil |
|
||||
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
||||
0x000000 | func | <0x5573f66ef5f0> func(elems...) {..}
|
||||
>>
|
||||
```
|
||||
|
||||
|
|
|
@ -26,11 +26,9 @@
|
|||
|
||||
__如果有好的意见或建议,欢迎联系我们!__
|
||||
|
||||
* __E-mail__:
|
||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||
|
||||
* __lhk101lhk101@qq.com__ (ValKmjolnir)
|
||||
|
||||
* __1467329765@qq.com__(Sidi762)
|
||||
* __sidi.liang@gmail.com__ (Sidi)
|
||||
|
||||
## __简介__
|
||||
|
||||
|
@ -103,7 +101,7 @@ Windows 平台的预览版解释器现在还没配置相关流水线,
|
|||
|
||||

|
||||
|
||||
如果你是 `Windows` 用户且想正常输出unicode,在nasal代码里写这个来开启unicode代码页:
|
||||
如果你是 `Windows` 用户且想正常输出 unicode,可以这样开启 unicode 代码页:
|
||||
|
||||
```javascript
|
||||
if (os.platform()=="windows") {
|
||||
|
@ -111,6 +109,14 @@ if (os.platform()=="windows") {
|
|||
}
|
||||
```
|
||||
|
||||
或者使用 `std.runtime.windows.set_utf8_output()`:
|
||||
|
||||
```javascript
|
||||
use std.runtime;
|
||||
|
||||
runtime.windows.set_utf8_output();
|
||||
```
|
||||
|
||||
## __与andy解释器的不同之处__
|
||||
|
||||

|
||||
|
@ -322,9 +328,8 @@ local (0x55dcb5b43190 <+7>)
|
|||
|
||||
```javascript
|
||||
source code:
|
||||
--> var fib=func(x)
|
||||
{
|
||||
if(x<2) return x;
|
||||
--> var fib = func(x) {
|
||||
if (x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
for(var i=0;i<31;i+=1)
|
||||
|
@ -332,16 +337,16 @@ source code:
|
|||
|
||||
|
||||
next bytecode:
|
||||
0x000848 4a 00 00 01 callfv 0x1(std/lib.nas:427)
|
||||
0x000849 3d 00 00 00 pop 0x0(std/lib.nas:427)
|
||||
0x00084a 07 00 00 00 pnil 0x0(std/lib.nas:423)
|
||||
0x00084b 56 00 00 00 ret 0x0(std/lib.nas:423)
|
||||
0x00084c 03 00 00 5e loadg 0x5e(std/lib.nas:423)
|
||||
--> 0x00084d 0b 00 08 51 newf 0x851(test/fib.nas:1)
|
||||
0x00084e 02 00 00 03 intl 0x3(test/fib.nas:1)
|
||||
0x00084f 0d 00 00 08 para 0x8 (x)(test/fib.nas:1)
|
||||
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||
--> 0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||
0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||
|
||||
stack (0x55ccd0a1b9d0, limit 10, total 0)
|
||||
vm stack (0x7fca7e9f1010, limit 16, total 0)
|
||||
>>
|
||||
```
|
||||
|
||||
|
@ -356,9 +361,8 @@ stack (0x55ccd0a1b9d0, limit 10, total 0)
|
|||
|
||||
```javascript
|
||||
source code:
|
||||
var fib=func(x)
|
||||
{
|
||||
--> if(x<2) return x;
|
||||
var fib = func(x) {
|
||||
--> if (x<2) return x;
|
||||
return fib(x-1)+fib(x-2);
|
||||
}
|
||||
for(var i=0;i<31;i+=1)
|
||||
|
@ -366,24 +370,24 @@ source code:
|
|||
|
||||
|
||||
next bytecode:
|
||||
0x000850 3e 00 08 60 jmp 0x860(test/fib.nas:1)
|
||||
--> 0x000851 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||
0x000852 39 00 00 07 lessc 0x7 (2)(test/fib.nas:3)
|
||||
0x000853 40 00 08 56 jf 0x856(test/fib.nas:3)
|
||||
0x000854 45 00 00 01 calll 0x1(test/fib.nas:3)
|
||||
0x000855 56 00 00 00 ret 0x0(test/fib.nas:3)
|
||||
0x000856 44 00 00 5f callg 0x5f(test/fib.nas:4)
|
||||
0x000857 45 00 00 01 calll 0x1(test/fib.nas:4)
|
||||
0x0003a8 07:00 00 00 00 00 00 00 00 pnil 0x0 (std/lib.nas:413)
|
||||
0x0003a9 56:00 00 00 00 00 00 00 00 ret 0x0 (std/lib.nas:413)
|
||||
0x0003aa 03:00 00 00 00 00 00 00 56 loadg 0x56 (std/lib.nas:413)
|
||||
0x0003ab 0b:00 00 00 00 00 00 03 af newf 0x3af (test/fib.nas:1)
|
||||
0x0003ac 02:00 00 00 00 00 00 00 03 intl 0x3 (test/fib.nas:1)
|
||||
0x0003ad 0d:00 00 00 00 00 00 00 22 para 0x22 (x) (test/fib.nas:1)
|
||||
0x0003ae 3e:00 00 00 00 00 00 03 be jmp 0x3be (test/fib.nas:1)
|
||||
--> 0x0003af 45:00 00 00 00 00 00 00 01 calll 0x1 (test/fib.nas:2)
|
||||
|
||||
stack (0x55ccd0a1b9d0, limit 10, total 8)
|
||||
0x000007 | pc | 0x869
|
||||
vm stack (0x7fca7e9f1010, limit 16, total 8)
|
||||
0x000007 | pc | 0x3c7
|
||||
0x000006 | addr | 0x0
|
||||
0x000005 | nil |
|
||||
0x000004 | nil |
|
||||
0x000003 | num | 0
|
||||
0x000002 | nil |
|
||||
0x000001 | nil |
|
||||
0x000000 | func | <0x55ccd0a58fa0> entry:0x487
|
||||
0x000000 | func | <0x5573f66ef5f0> func(elems...) {..}
|
||||
>>
|
||||
```
|
||||
|
||||
|
|
61
makefile
61
makefile
|
@ -13,7 +13,7 @@ NASAL_HEADER = \
|
|||
src/ast_dumper.h\
|
||||
src/ast_visitor.h\
|
||||
src/nasal_ast.h\
|
||||
src/natives/nasal_builtin.h\
|
||||
src/natives/builtin.h\
|
||||
src/nasal_codegen.h\
|
||||
src/nasal_dbg.h\
|
||||
src/nasal_err.h\
|
||||
|
@ -27,6 +27,7 @@ NASAL_HEADER = \
|
|||
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\
|
||||
|
@ -35,8 +36,10 @@ NASAL_HEADER = \
|
|||
src/natives/json_lib.h\
|
||||
src/natives/unix_lib.h\
|
||||
src/natives/coroutine.h\
|
||||
src/repl.h\
|
||||
src/natives/regex_lib.h
|
||||
src/natives/regex_lib.h\
|
||||
src/repl/repl.h\
|
||||
src/util/fs.h\
|
||||
src/util/util.h
|
||||
|
||||
NASAL_OBJECT = \
|
||||
build/nasal_err.o\
|
||||
|
@ -51,9 +54,8 @@ NASAL_OBJECT = \
|
|||
build/nasal_opcode.o\
|
||||
build/symbol_finder.o\
|
||||
build/nasal_codegen.o\
|
||||
build/nasal_misc.o\
|
||||
build/nasal_gc.o\
|
||||
build/nasal_builtin.o\
|
||||
build/builtin.o\
|
||||
build/fg_props.o\
|
||||
build/io_lib.o\
|
||||
build/math_lib.o\
|
||||
|
@ -64,8 +66,11 @@ NASAL_OBJECT = \
|
|||
build/nasal_type.o\
|
||||
build/nasal_vm.o\
|
||||
build/nasal_dbg.o\
|
||||
build/repl.o\
|
||||
build/regex_lib.o\
|
||||
build/repl.o\
|
||||
build/cli.o\
|
||||
build/fs.o\
|
||||
build/util.o\
|
||||
build/main.o
|
||||
|
||||
|
||||
|
@ -86,16 +91,25 @@ build:
|
|||
build/main.o: $(NASAL_HEADER) src/main.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/main.cpp -o build/main.o
|
||||
|
||||
build/nasal_misc.o: src/nasal.h src/nasal_misc.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/nasal_misc.cpp -o build/nasal_misc.o
|
||||
build/cli.o: src/cli/cli.h src/cli/cli.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/cli/cli.cpp -o build/cli.o
|
||||
|
||||
build/repl.o: $(NASAL_HEADER) src/repl.h src/repl.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/repl.cpp -o build/repl.o
|
||||
build/util.o: src/util/util.h src/util/util.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/util/util.cpp -o build/util.o
|
||||
|
||||
build/nasal_err.o: src/nasal.h src/repl.h src/nasal_err.h src/nasal_err.cpp | build
|
||||
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/nasal_type.h src/nasal_type.cpp | build
|
||||
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/nasal_type.h src/nasal_gc.h src/nasal_gc.cpp | build
|
||||
|
@ -106,12 +120,16 @@ build/nasal_import.o: \
|
|||
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.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
|
||||
|
@ -122,12 +140,14 @@ build/nasal_ast.o: \
|
|||
src/nasal_ast.h src/nasal_ast.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/nasal_ast.cpp -o build/nasal_ast.o
|
||||
|
||||
build/nasal_builtin.o: \
|
||||
build/builtin.o: \
|
||||
src/nasal.h\
|
||||
src/nasal_type.h\
|
||||
src/nasal_gc.h\
|
||||
src/natives/nasal_builtin.h src/natives/nasal_builtin.cpp | build
|
||||
$(CXX) $(CXXFLAGS) src/natives/nasal_builtin.cpp -o build/nasal_builtin.o
|
||||
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\
|
||||
|
@ -143,7 +163,6 @@ build/bits_lib.o: \
|
|||
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\
|
||||
|
@ -155,6 +174,7 @@ 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
|
||||
|
||||
|
@ -169,6 +189,7 @@ 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
|
||||
|
||||
|
@ -198,7 +219,8 @@ build/nasal_codegen.o: $(NASAL_HEADER) src/nasal_codegen.h src/nasal_codegen.cpp
|
|||
|
||||
build/nasal_opcode.o: \
|
||||
src/nasal.h\
|
||||
src/natives/nasal_builtin.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
|
||||
|
||||
|
@ -207,6 +229,7 @@ build/nasal_parse.o: \
|
|||
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
|
||||
|
||||
|
@ -238,6 +261,7 @@ build/ast_dumper.o: \
|
|||
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
|
||||
|
||||
|
@ -294,5 +318,6 @@ test:nasal
|
|||
@ ./nasal -e test/trait.nas
|
||||
@ ./nasal -t -d test/turingmachine.nas
|
||||
@ ./nasal -d test/wavecollapse.nas
|
||||
@ ./nasal -d test/wavecity.nas
|
||||
@ ./nasal test/word_collector.nas test/md5compare.nas
|
||||
@ ./nasal -t -d test/ycombinator.nas
|
||||
|
|
|
@ -34,7 +34,8 @@ public:
|
|||
tcgetattr(0, &init_termios);
|
||||
new_termios = init_termios;
|
||||
new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE);
|
||||
// vmin=0 is nonblock input, but in wsl there is a bug that will block input
|
||||
// vmin = 0 is nonblock input,
|
||||
// but in wsl1 there is a bug that will block input
|
||||
// so we use fcntl to write the nonblock input
|
||||
new_termios.c_cc[VMIN] = 1;
|
||||
new_termios.c_cc[VTIME] = 0;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
dynamic_libs_so = libfib.so libkey.so libnasock.so libmat.so
|
||||
dynamic_libs_dll = libfib.dll libkey.dll libnasock.dll libmat.dll
|
||||
|
||||
used_header = ../src/nasal.h ../src/nasal_type.h ../src/nasal_gc.h
|
||||
used_object = ../build/nasal_misc.o ../build/nasal_type.o ../build/nasal_gc.o
|
||||
used_header = ../src/nasal.h ../src/util/util.h ../src/nasal_type.h ../src/nasal_gc.h
|
||||
used_object = ../build/util.o ../build/nasal_type.o ../build/nasal_gc.o
|
||||
|
||||
STD = c++17
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "ast_dumper.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -6,7 +7,7 @@ namespace nasal {
|
|||
|
||||
bool ast_dumper::visit_use_stmt(use_stmt* node) {
|
||||
dump_indent();
|
||||
std::cout << "use" << format_location(node->get_location());
|
||||
std::cout << "use" << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_path()) {
|
||||
if (i==node->get_path().back()) {
|
||||
|
@ -20,48 +21,48 @@ bool ast_dumper::visit_use_stmt(use_stmt* node) {
|
|||
|
||||
bool ast_dumper::visit_null_expr(null_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "null" << format_location(node->get_location());
|
||||
std::cout << "null" << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_nil_expr(nil_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "nil" << format_location(node->get_location());
|
||||
std::cout << "nil" << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_number_literal(number_literal* node) {
|
||||
dump_indent();
|
||||
std::cout << "number " << node->get_number();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_string_literal(string_literal* node) {
|
||||
dump_indent();
|
||||
std::cout << "string \"" << rawstr(node->get_content()) << "\"";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << "string \"" << util::rawstr(node->get_content()) << "\"";
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_identifier(identifier* node) {
|
||||
dump_indent();
|
||||
std::cout << "identifier " << node->get_name();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_bool_literal(bool_literal* node) {
|
||||
dump_indent();
|
||||
std::cout << "bool " << node->get_flag();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_vector_expr(vector_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "vector";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_elements()) {
|
||||
if (i==node->get_elements().back()) {
|
||||
|
@ -76,7 +77,7 @@ bool ast_dumper::visit_vector_expr(vector_expr* node) {
|
|||
bool ast_dumper::visit_hash_expr(hash_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "hash";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_members()) {
|
||||
if (i==node->get_members().back()) {
|
||||
|
@ -91,7 +92,7 @@ bool ast_dumper::visit_hash_expr(hash_expr* node) {
|
|||
bool ast_dumper::visit_hash_pair(hash_pair* node) {
|
||||
dump_indent();
|
||||
std::cout << "pair " << node->get_name();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
if (node->get_value()) {
|
||||
push_indent();
|
||||
set_last();
|
||||
|
@ -104,7 +105,7 @@ bool ast_dumper::visit_hash_pair(hash_pair* node) {
|
|||
bool ast_dumper::visit_function(function* node) {
|
||||
dump_indent();
|
||||
std::cout << "function";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_parameter_list()) {
|
||||
i->accept(this);
|
||||
|
@ -118,7 +119,7 @@ bool ast_dumper::visit_function(function* node) {
|
|||
bool ast_dumper::visit_code_block(code_block* node) {
|
||||
dump_indent();
|
||||
std::cout << "block";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_expressions()) {
|
||||
if (i==node->get_expressions().back()) {
|
||||
|
@ -133,7 +134,7 @@ bool ast_dumper::visit_code_block(code_block* node) {
|
|||
bool ast_dumper::visit_parameter(parameter* node) {
|
||||
dump_indent();
|
||||
std::cout << "parameter " << node->get_parameter_name();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
if (node->get_default_value()) {
|
||||
push_indent();
|
||||
set_last();
|
||||
|
@ -146,7 +147,7 @@ bool ast_dumper::visit_parameter(parameter* node) {
|
|||
bool ast_dumper::visit_ternary_operator(ternary_operator* node) {
|
||||
dump_indent();
|
||||
std::cout << "ternary_operator";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_condition()->accept(this);
|
||||
node->get_left()->accept(this);
|
||||
|
@ -166,7 +167,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) {
|
|||
return true;
|
||||
}
|
||||
dump_indent();
|
||||
std::cout << "binary_operator ";
|
||||
std::cout << "binary_operator \"";
|
||||
switch(node->get_operator_type()) {
|
||||
case binary_operator::binary_type::add: std::cout << "+"; break;
|
||||
case binary_operator::binary_type::sub: std::cout << "-"; break;
|
||||
|
@ -185,7 +186,7 @@ bool ast_dumper::visit_binary_operator(binary_operator* node) {
|
|||
case binary_operator::binary_type::condition_and: std::cout << "and"; break;
|
||||
case binary_operator::binary_type::condition_or: std::cout << "or"; break;
|
||||
}
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << "\"" << format_location(node);
|
||||
push_indent();
|
||||
node->get_left()->accept(this);
|
||||
set_last();
|
||||
|
@ -200,13 +201,13 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) {
|
|||
return true;
|
||||
}
|
||||
dump_indent();
|
||||
std::cout << "unary_operator ";
|
||||
std::cout << "unary_operator \"";
|
||||
switch(node->get_operator_type()) {
|
||||
case unary_operator::unary_type::negative: std::cout << "-"; break;
|
||||
case unary_operator::unary_type::logical_not: std::cout << "!"; break;
|
||||
case unary_operator::unary_type::bitwise_not: std::cout << "~"; break;
|
||||
}
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << "\"" << format_location(node);
|
||||
push_indent();
|
||||
set_last();
|
||||
node->get_value()->accept(this);
|
||||
|
@ -217,7 +218,7 @@ bool ast_dumper::visit_unary_operator(unary_operator* node) {
|
|||
bool ast_dumper::visit_call_expr(call_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "call_expr";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
if (!node->get_calls().size()) {
|
||||
set_last();
|
||||
|
@ -236,14 +237,14 @@ bool ast_dumper::visit_call_expr(call_expr* node) {
|
|||
bool ast_dumper::visit_call_hash(call_hash* node) {
|
||||
dump_indent();
|
||||
std::cout << "call_hash " << node->get_field();
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_call_vector(call_vector* node) {
|
||||
dump_indent();
|
||||
std::cout << "call_vector";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_slices()) {
|
||||
if (i==node->get_slices().back()) {
|
||||
|
@ -258,7 +259,7 @@ bool ast_dumper::visit_call_vector(call_vector* node) {
|
|||
bool ast_dumper::visit_call_function(call_function* node) {
|
||||
dump_indent();
|
||||
std::cout << "call_function";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_argument()) {
|
||||
if (i==node->get_argument().back()) {
|
||||
|
@ -273,7 +274,7 @@ bool ast_dumper::visit_call_function(call_function* node) {
|
|||
bool ast_dumper::visit_slice_vector(slice_vector* node) {
|
||||
dump_indent();
|
||||
std::cout << "slice";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
if (!node->get_end()) {
|
||||
set_last();
|
||||
|
@ -290,7 +291,7 @@ bool ast_dumper::visit_slice_vector(slice_vector* node) {
|
|||
bool ast_dumper::visit_definition_expr(definition_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "definition";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
if (node->get_variable_name()) {
|
||||
node->get_variable_name()->accept(this);
|
||||
|
@ -321,7 +322,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
|
|||
case assignment_expr::assign_type::bitwise_or_equal: std::cout << "|="; break;
|
||||
case assignment_expr::assign_type::bitwise_xor_equal: std::cout << "^="; break;
|
||||
}
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_left()->accept(this);
|
||||
set_last();
|
||||
|
@ -333,7 +334,7 @@ bool ast_dumper::visit_assignment_expr(assignment_expr* node) {
|
|||
bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
|
||||
dump_indent();
|
||||
std::cout << "multiple_identifier";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_variables()) {
|
||||
if (i==node->get_variables().back()) {
|
||||
|
@ -348,7 +349,7 @@ bool ast_dumper::visit_multi_identifier(multi_identifier* node) {
|
|||
bool ast_dumper::visit_tuple_expr(tuple_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "tuple";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
for(auto i : node->get_elements()) {
|
||||
if (i==node->get_elements().back()) {
|
||||
|
@ -363,7 +364,7 @@ bool ast_dumper::visit_tuple_expr(tuple_expr* node) {
|
|||
bool ast_dumper::visit_multi_assign(multi_assign* node) {
|
||||
dump_indent();
|
||||
std::cout << "multiple_assignment";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_tuple()->accept(this);
|
||||
set_last();
|
||||
|
@ -375,7 +376,7 @@ bool ast_dumper::visit_multi_assign(multi_assign* node) {
|
|||
bool ast_dumper::visit_while_expr(while_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "while";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_condition()->accept(this);
|
||||
set_last();
|
||||
|
@ -387,7 +388,7 @@ bool ast_dumper::visit_while_expr(while_expr* node) {
|
|||
bool ast_dumper::visit_for_expr(for_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "for";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_initial()->accept(this);
|
||||
node->get_condition()->accept(this);
|
||||
|
@ -405,7 +406,7 @@ bool ast_dumper::visit_iter_expr(iter_expr* node) {
|
|||
} else {
|
||||
std::cout << "iterator";
|
||||
}
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
set_last();
|
||||
if (node->get_name()) {
|
||||
|
@ -424,7 +425,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) {
|
|||
} else {
|
||||
std::cout << "forindex";
|
||||
}
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
node->get_iterator()->accept(this);
|
||||
node->get_value()->accept(this);
|
||||
|
@ -437,7 +438,7 @@ bool ast_dumper::visit_forei_expr(forei_expr* node) {
|
|||
bool ast_dumper::visit_condition_expr(condition_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "condition";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
if (!node->get_elsif_stataments().size() &&
|
||||
!node->get_else_statement()) {
|
||||
|
@ -462,7 +463,7 @@ bool ast_dumper::visit_condition_expr(condition_expr* node) {
|
|||
bool ast_dumper::visit_if_expr(if_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "if";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
push_indent();
|
||||
if (node->get_condition()) {
|
||||
node->get_condition()->accept(this);
|
||||
|
@ -476,21 +477,21 @@ bool ast_dumper::visit_if_expr(if_expr* node) {
|
|||
bool ast_dumper::visit_continue_expr(continue_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "continue";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_break_expr(break_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "break";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ast_dumper::visit_return_expr(return_expr* node) {
|
||||
dump_indent();
|
||||
std::cout << "return";
|
||||
std::cout << format_location(node->get_location());
|
||||
std::cout << format_location(node);
|
||||
if (node->get_value()) {
|
||||
push_indent();
|
||||
set_last();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "ast_visitor.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
@ -16,29 +17,37 @@ private:
|
|||
private:
|
||||
void push_indent() {
|
||||
if (indent.size()) {
|
||||
if (indent.back()=="|--") {
|
||||
indent.back() = "| ";
|
||||
} else if (indent.back()=="+--") {
|
||||
if (indent.back()=="├──") {
|
||||
indent.back() = "│ ";
|
||||
} else if (indent.back()=="╰──") {
|
||||
indent.back() = " ";
|
||||
}
|
||||
}
|
||||
indent.push_back("|--");
|
||||
indent.push_back("├──");
|
||||
}
|
||||
void pop_indent() {indent.pop_back();}
|
||||
void set_last() {indent.back() = "+--";}
|
||||
|
||||
void pop_indent() {
|
||||
indent.pop_back();
|
||||
}
|
||||
|
||||
void set_last() {
|
||||
indent.back() = "╰──";
|
||||
}
|
||||
|
||||
void dump_indent() {
|
||||
if (indent.size() && indent.back()=="| ") {
|
||||
indent.back() = "|--";
|
||||
if (indent.size() && indent.back()=="│ ") {
|
||||
indent.back() = "├──";
|
||||
}
|
||||
for(const auto& i : indent) {
|
||||
std::cout << i;
|
||||
}
|
||||
}
|
||||
std::string format_location(const span& location) {
|
||||
|
||||
std::string format_location(expr* node) {
|
||||
std::stringstream ss;
|
||||
ss << " -> ";
|
||||
location.dump_begin(ss);
|
||||
ss << "\n";
|
||||
ss << " → [";
|
||||
node->get_location().dump_begin(ss);
|
||||
ss << "]\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
@ -81,7 +90,10 @@ public:
|
|||
|
||||
public:
|
||||
void dump(code_block* root) {
|
||||
util::windows_code_page_manager wcpm;
|
||||
wcpm.set_utf8_output();
|
||||
root->accept(this);
|
||||
wcpm.restore_code_page();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#include "cli/cli.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace nasal::cli {
|
||||
|
||||
cli_config parse(const std::vector<std::string>& args) {
|
||||
cli_config result;
|
||||
|
||||
for(const auto& arg : args) {
|
||||
if (cli_options.count(arg)) {
|
||||
result.options.insert(cli_options.at(arg));
|
||||
} else if (!result.input_file_path.length()) {
|
||||
result.input_file_path = arg;
|
||||
} else {
|
||||
result.nasal_vm_args.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.input_file_path.length() && result.options.empty()) {
|
||||
result.options.insert(option::cli_execute);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace nasal::cli {
|
||||
|
||||
enum class option {
|
||||
cli_help,
|
||||
cli_version,
|
||||
cli_repl_mode,
|
||||
cli_view_ast,
|
||||
cli_view_raw_ast,
|
||||
cli_view_code,
|
||||
cli_show_symbol,
|
||||
cli_execute,
|
||||
cli_show_execute_time,
|
||||
cli_detail_info,
|
||||
cli_show_referenced_file,
|
||||
cli_debug_mode,
|
||||
cli_profile,
|
||||
cli_profile_all,
|
||||
cli_limit_mode
|
||||
};
|
||||
|
||||
struct cli_config {
|
||||
std::string input_file_path = "";
|
||||
std::unordered_set<option> options = {};
|
||||
std::vector<std::string> nasal_vm_args = {};
|
||||
|
||||
bool has(option opt) const {
|
||||
return options.count(opt);
|
||||
}
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, option> cli_options = {
|
||||
{"-h", option::cli_help},
|
||||
{"--help", option::cli_help},
|
||||
{"-v", option::cli_version},
|
||||
{"--version", option::cli_version},
|
||||
{"-r", option::cli_repl_mode},
|
||||
{"--repl", option::cli_repl_mode},
|
||||
{"-a", option::cli_view_ast},
|
||||
{"--ast", option::cli_view_ast},
|
||||
{"--raw-ast", option::cli_view_raw_ast},
|
||||
{"-c", option::cli_view_code},
|
||||
{"--code", option::cli_view_code},
|
||||
{"-s", option::cli_show_symbol},
|
||||
{"--symbol", option::cli_show_symbol},
|
||||
{"-e", option::cli_execute},
|
||||
{"--exec", option::cli_execute},
|
||||
{"-t", option::cli_show_execute_time},
|
||||
{"--time", option::cli_show_execute_time},
|
||||
{"-d", option::cli_detail_info},
|
||||
{"--detail", option::cli_detail_info},
|
||||
{"-f", option::cli_show_referenced_file},
|
||||
{"--ref-file", option::cli_show_referenced_file},
|
||||
{"-dbg", option::cli_debug_mode},
|
||||
{"--debug", option::cli_debug_mode},
|
||||
{"--prof", option::cli_profile},
|
||||
{"--prof-all", option::cli_profile_all},
|
||||
{"--limit", option::cli_limit_mode}
|
||||
};
|
||||
|
||||
cli_config parse(const std::vector<std::string>&);
|
||||
|
||||
}
|
140
src/main.cpp
140
src/main.cpp
|
@ -13,39 +13,26 @@
|
|||
#include "nasal_codegen.h"
|
||||
#include "nasal_vm.h"
|
||||
#include "nasal_dbg.h"
|
||||
#include "repl.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "repl/repl.h"
|
||||
#include "cli/cli.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <cstdlib>
|
||||
|
||||
const u32 VM_RAW_AST = 1;
|
||||
const u32 VM_AST = 1<<1;
|
||||
const u32 VM_CODE = 1<<2;
|
||||
const u32 VM_TIME = 1<<3;
|
||||
const u32 VM_EXEC = 1<<4;
|
||||
const u32 VM_DETAIL = 1<<5;
|
||||
const u32 VM_DEBUG = 1<<6;
|
||||
const u32 VM_SYMINFO = 1<<7;
|
||||
const u32 VM_PROFILE = 1<<8;
|
||||
const u32 VM_PROF_ALL = 1<<9;
|
||||
const u32 VM_REF_FILE = 1<<10;
|
||||
const u32 VM_LIMIT = 1<<11;
|
||||
|
||||
std::ostream& help(std::ostream& out) {
|
||||
out
|
||||
<< "\n"
|
||||
<< " ,--#-,\n"
|
||||
<< "<3 / \\____\\ <3\n"
|
||||
<< " |_|__A_|\n"
|
||||
#ifdef _WIN32
|
||||
<< "use command <chcp 65001> to use unicode.\n"
|
||||
#endif
|
||||
<< "\nnasal <option>\n"
|
||||
<< "option:\n"
|
||||
<< " -h, --help | get help.\n"
|
||||
<< " -v, --version | get version.\n"
|
||||
<< " -r, --repl | use repl interpreter(experimental).\n"
|
||||
<< " -r, --repl | use repl interpreter.\n"
|
||||
<< "\nnasal [option] <file> [argv]\n"
|
||||
<< "option:\n"
|
||||
<< " -a, --ast | view ast after link/optimize process.\n"
|
||||
|
@ -80,7 +67,7 @@ std::ostream& logo(std::ostream& out) {
|
|||
<< " \\_\\ \\/ \\__,_|___/\\__,_|_|\n"
|
||||
<< "\n"
|
||||
<< "ver : " << __nasver__
|
||||
<< " " << nasal::get_platform() << " " << nasal::get_arch()
|
||||
<< " " << nasal::util::get_platform() << " " << nasal::util::get_arch()
|
||||
<< " (" << __DATE__ << " " << __TIME__ << ")\n"
|
||||
<< "std : c++ " << __cplusplus << "\n"
|
||||
<< "core : " << std::thread::hardware_concurrency() << " core(s)\n"
|
||||
|
@ -88,7 +75,9 @@ std::ostream& logo(std::ostream& out) {
|
|||
<< "repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n"
|
||||
<< "wiki : https://wiki.flightgear.org/Nasal_scripting_language\n"
|
||||
<< "\n"
|
||||
<< "presented by fgprc members - http://fgprc.org.cn\n"
|
||||
<< "presented by fgprc members\n"
|
||||
<< " - http://fgprc.org\n"
|
||||
<< " - http://fgprc.org.cn\n"
|
||||
<< "\n"
|
||||
<< "input <nasal -h> to get help .\n\n";
|
||||
return out;
|
||||
|
@ -101,28 +90,25 @@ std::ostream& version(std::ostream& out) {
|
|||
for(u32 i = 0; i<5; ++i) {
|
||||
num = (num+rand())*(1.0/(RAND_MAX+1.0));
|
||||
}
|
||||
if (num<0.01) {
|
||||
// give you 5% to see this easter egg
|
||||
if (num<0.05) {
|
||||
nasal::parse::easter_egg();
|
||||
}
|
||||
|
||||
out << "nasal interpreter version " << __nasver__;
|
||||
out << " " << nasal::get_platform() << " " << nasal::get_arch();
|
||||
out << "nasal version " << __nasver__;
|
||||
out << " " << nasal::util::get_platform() << " " << nasal::util::get_arch();
|
||||
out << " (" << __DATE__ << " " << __TIME__ << ")\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void err() {
|
||||
std::cerr
|
||||
<< "invalid argument(s).\n"
|
||||
<< "use <nasal -h> to get help.\n";
|
||||
std::cerr << "invalid argument(s), use <nasal -h> to get help.\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
void execute(const std::string& file,
|
||||
const std::vector<std::string>& argv,
|
||||
const u32 cmd) {
|
||||
|
||||
void execute(const nasal::cli::cli_config& config) {
|
||||
using option = nasal::cli::option;
|
||||
using clk = std::chrono::high_resolution_clock;
|
||||
const auto den = clk::duration::period::den;
|
||||
|
||||
|
@ -132,17 +118,17 @@ void execute(const std::string& file,
|
|||
nasal::codegen gen;
|
||||
|
||||
// lexer scans file to get tokens
|
||||
lex.scan(file).chkerr();
|
||||
lex.scan(config.input_file_path).chkerr();
|
||||
|
||||
// parser gets lexer's token list to compile
|
||||
parse.compile(lex).chkerr();
|
||||
if (cmd&VM_RAW_AST) {
|
||||
if (config.has(option::cli_view_raw_ast)) {
|
||||
nasal::ast_dumper().dump(parse.tree());
|
||||
}
|
||||
|
||||
// linker gets parser's ast and load import files to this ast
|
||||
ld.link(parse, cmd&VM_DETAIL).chkerr();
|
||||
if (cmd&VM_REF_FILE) {
|
||||
ld.link(parse, config.has(option::cli_detail_info)).chkerr();
|
||||
if (config.has(option::cli_show_referenced_file)) {
|
||||
if (ld.get_file_list().size()) {
|
||||
std::cout << "referenced file(s):\n";
|
||||
}
|
||||
|
@ -154,34 +140,43 @@ void execute(const std::string& file,
|
|||
// optimizer does simple optimization on ast
|
||||
auto opt = std::make_unique<nasal::optimizer>();
|
||||
opt->do_optimization(parse.tree());
|
||||
if (cmd&VM_AST) {
|
||||
if (config.has(option::cli_view_ast)) {
|
||||
nasal::ast_dumper().dump(parse.tree());
|
||||
}
|
||||
|
||||
// code generator gets parser's ast and import file list to generate code
|
||||
gen.compile(parse, ld, false, cmd&VM_LIMIT).chkerr();
|
||||
if (cmd&VM_CODE) {
|
||||
gen.compile(parse, ld, false, config.has(option::cli_limit_mode)).chkerr();
|
||||
if (config.has(option::cli_view_code)) {
|
||||
gen.print(std::cout);
|
||||
}
|
||||
if (cmd&VM_SYMINFO) {
|
||||
if (config.has(option::cli_show_symbol)) {
|
||||
gen.symbol_dump(std::cout);
|
||||
}
|
||||
|
||||
// run
|
||||
const auto start = clk::now();
|
||||
if (cmd&VM_DEBUG) {
|
||||
if (config.has(option::cli_debug_mode)) {
|
||||
auto debugger = std::make_unique<nasal::dbg>();
|
||||
debugger->run(gen, ld, argv, cmd&VM_PROFILE, cmd&VM_PROF_ALL);
|
||||
} else if (cmd&VM_TIME || cmd&VM_EXEC) {
|
||||
debugger->run(
|
||||
gen,
|
||||
ld,
|
||||
config.nasal_vm_args,
|
||||
config.has(option::cli_profile),
|
||||
config.has(option::cli_profile_all)
|
||||
);
|
||||
} else if (config.has(option::cli_show_execute_time) ||
|
||||
config.has(option::cli_detail_info) ||
|
||||
config.has(option::cli_limit_mode) ||
|
||||
config.has(option::cli_execute)) {
|
||||
auto runtime = std::make_unique<nasal::vm>();
|
||||
runtime->set_detail_report_info(cmd&VM_DETAIL);
|
||||
runtime->set_limit_mode_flag(cmd&VM_LIMIT);
|
||||
runtime->run(gen, ld, argv);
|
||||
runtime->set_detail_report_info(config.has(option::cli_detail_info));
|
||||
runtime->set_limit_mode_flag(config.has(option::cli_limit_mode));
|
||||
runtime->run(gen, ld, config.nasal_vm_args);
|
||||
}
|
||||
|
||||
// get running time
|
||||
const auto end = clk::now();
|
||||
if (cmd&VM_TIME) {
|
||||
if (config.has(option::cli_show_execute_time)) {
|
||||
std::clog << "process exited after ";
|
||||
std::clog << static_cast<f64>((end-start).count())/den << "s.\n\n";
|
||||
}
|
||||
|
@ -194,18 +189,20 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// the first argument is the executable itself, ignore it
|
||||
const auto config = nasal::cli::parse({argv+1, argv+argc});
|
||||
|
||||
// run directly or show help
|
||||
if (argc==2) {
|
||||
std::string s(argv[1]);
|
||||
if (s=="-h" || s=="--help") {
|
||||
if (config.has(nasal::cli::option::cli_help)) {
|
||||
std::clog << help;
|
||||
} else if (s=="-v" || s=="--version") {
|
||||
} else if (config.has(nasal::cli::option::cli_version)) {
|
||||
std::clog << version;
|
||||
} else if (s=="-r" || s=="--repl") {
|
||||
} else if (config.has(nasal::cli::option::cli_repl_mode)) {
|
||||
auto repl = std::make_unique<nasal::repl::repl>();
|
||||
repl->execute();
|
||||
} else if (s[0]!='-') {
|
||||
execute(s, {}, VM_EXEC);
|
||||
} else if (config.input_file_path.size()) {
|
||||
execute(config);
|
||||
} else {
|
||||
err();
|
||||
}
|
||||
|
@ -213,45 +210,6 @@ i32 main(i32 argc, const char* argv[]) {
|
|||
}
|
||||
|
||||
// execute with arguments
|
||||
const std::unordered_map<std::string, u32> command_list = {
|
||||
{"--raw-ast", VM_RAW_AST},
|
||||
{"--ast", VM_AST},
|
||||
{"-a", VM_AST},
|
||||
{"--code", VM_CODE},
|
||||
{"-c", VM_CODE},
|
||||
{"--symbol", VM_SYMINFO},
|
||||
{"-s", VM_SYMINFO},
|
||||
{"--exec", VM_EXEC},
|
||||
{"-e", VM_EXEC},
|
||||
{"--time", VM_TIME|VM_EXEC},
|
||||
{"-t", VM_TIME|VM_EXEC},
|
||||
{"--detail", VM_DETAIL|VM_EXEC},
|
||||
{"-d", VM_DETAIL|VM_EXEC},
|
||||
{"--debug", VM_DEBUG},
|
||||
{"-dbg", VM_DEBUG},
|
||||
{"--prof", VM_PROFILE},
|
||||
{"--prof-all", VM_PROF_ALL},
|
||||
{"-f", VM_REF_FILE},
|
||||
{"--ref-file", VM_REF_FILE},
|
||||
{"--limit", VM_LIMIT|VM_EXEC}
|
||||
};
|
||||
|
||||
u32 commands = 0;
|
||||
std::string filename = "";
|
||||
std::vector<std::string> vm_argv;
|
||||
for(i32 i = 1; i<argc; ++i) {
|
||||
if (command_list.count(argv[i])) {
|
||||
commands |= command_list.at(argv[i]);
|
||||
} else if (!filename.length()) {
|
||||
filename = argv[i];
|
||||
} else {
|
||||
vm_argv.push_back(argv[i]);
|
||||
}
|
||||
}
|
||||
if (!filename.length()) {
|
||||
err();
|
||||
}
|
||||
|
||||
execute(filename, vm_argv, commands? commands:VM_EXEC);
|
||||
execute(config);
|
||||
return 0;
|
||||
}
|
62
src/nasal.h
62
src/nasal.h
|
@ -4,12 +4,8 @@
|
|||
#define __nasver__ "11.2"
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
// abbreviation of some useful basic type
|
||||
using i32 = std::int32_t;
|
||||
|
@ -21,61 +17,5 @@ using u64 = std::uint64_t;
|
|||
using usize = std::size_t;
|
||||
using f64 = double;
|
||||
|
||||
namespace nasal {
|
||||
|
||||
bool is_windows();
|
||||
bool is_linux();
|
||||
bool is_macos();
|
||||
bool is_x86();
|
||||
bool is_amd64();
|
||||
bool is_x86_64();
|
||||
bool is_arm();
|
||||
bool is_aarch64();
|
||||
bool is_ia64();
|
||||
bool is_powerpc();
|
||||
bool is_superh();
|
||||
const char* get_platform();
|
||||
const char* get_arch();
|
||||
|
||||
// virtual machine stack depth, both global depth and value stack depth
|
||||
const u32 VM_STACK_DEPTH = UINT16_MAX;
|
||||
|
||||
f64 hex_to_f64(const char*);
|
||||
f64 oct_to_f64(const char*);
|
||||
// we have the same reason not using atof here
|
||||
// just as andy's interpreter does.
|
||||
// it is not platform independent, and may have strange output.
|
||||
// so we write a new function here to convert str to number manually.
|
||||
// but this also makes 0.1+0.2==0.3,
|
||||
// not another result that you may get in other languages.
|
||||
f64 dec_to_f64(const char*);
|
||||
|
||||
f64 str_to_num(const char*);
|
||||
i32 utf8_hdchk(const char);
|
||||
std::string char_to_hex(const char);
|
||||
std::string rawstr(const std::string&, const usize maxlen = 0);
|
||||
|
||||
namespace fs {
|
||||
|
||||
class path {
|
||||
private:
|
||||
std::string file_system_path;
|
||||
|
||||
public:
|
||||
path(const path&) = default;
|
||||
path(const std::string& file_path): file_system_path(file_path) {}
|
||||
path& operator/(const path&);
|
||||
const char* c_str() const {
|
||||
return file_system_path.c_str();
|
||||
}
|
||||
const std::string& str() const {
|
||||
return file_system_path;
|
||||
}
|
||||
};
|
||||
|
||||
bool exists(const path&);
|
||||
bool is_regular(const path&);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include "nasal_codegen.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
@ -239,9 +240,9 @@ void codegen::func_gen(function* node) {
|
|||
}
|
||||
}
|
||||
|
||||
usize newf=code.size();
|
||||
const auto newf = code.size();
|
||||
emit(op_newf, 0, node->get_location());
|
||||
usize lsize=code.size();
|
||||
const auto lsize = code.size();
|
||||
emit(op_intl, 0, node->get_location());
|
||||
|
||||
// add special keyword 'me' into symbol table
|
||||
|
@ -1390,7 +1391,7 @@ void codegen::print(std::ostream& out) {
|
|||
|
||||
// print const strings
|
||||
for(const auto& str : const_string_table) {
|
||||
out << " .symbol \"" << rawstr(str) << "\"\n";
|
||||
out << " .symbol \"" << util::rawstr(str) << "\"\n";
|
||||
}
|
||||
|
||||
// print blank line
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "nasal_parse.h"
|
||||
#include "nasal_import.h"
|
||||
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
#include "natives/coroutine.h"
|
||||
#include "natives/bits_lib.h"
|
||||
#include "natives/math_lib.h"
|
||||
|
|
|
@ -13,7 +13,7 @@ void operand_line_counter::load_file_line_counter(
|
|||
file_name_list = file_list;
|
||||
file_line_counter = {};
|
||||
file_contents = {};
|
||||
flstream fs;
|
||||
filestream fs;
|
||||
for(usize i =0; i<file_list.size(); ++i) {
|
||||
fs.load(file_list[i]);
|
||||
file_contents.push_back(fs.file_content());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "nasal_err.h"
|
||||
#include "repl.h"
|
||||
#include "repl/repl.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
@ -71,7 +71,7 @@ std::ostream& reset(std::ostream& s) {
|
|||
return s;
|
||||
}
|
||||
|
||||
void flstream::load(const std::string& f) {
|
||||
void filestream::load(const std::string& f) {
|
||||
if (file==f) { // don't need to load a loaded file
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,13 @@ std::ostream& orange(std::ostream&);
|
|||
std::ostream& white(std::ostream&);
|
||||
std::ostream& reset(std::ostream&);
|
||||
|
||||
class flstream {
|
||||
class filestream {
|
||||
protected:
|
||||
std::string file;
|
||||
std::vector<std::string> res;
|
||||
|
||||
public:
|
||||
flstream(): file("") {}
|
||||
filestream(): file("") {}
|
||||
void load(const std::string&);
|
||||
const std::string& operator[](usize n) const {return res[n];}
|
||||
const auto& name() const {return file;}
|
||||
|
@ -43,7 +43,7 @@ public:
|
|||
usize size() const {return res.size();}
|
||||
};
|
||||
|
||||
class error: public flstream {
|
||||
class error: public filestream {
|
||||
private:
|
||||
u32 cnt; // counter for errors
|
||||
|
||||
|
|
|
@ -301,17 +301,17 @@ void gc::info() const {
|
|||
for(usize i = 0; i<indent; ++i) {
|
||||
indent_string += "-";
|
||||
}
|
||||
auto last_line = indent_string + "+" +
|
||||
indent_string + "-" + indent_string + "-" + indent_string;
|
||||
const auto last_line = "+" + indent_string + "+" +
|
||||
indent_string + "-" + indent_string + "-" + indent_string + "+";
|
||||
indent_string = indent_string + "+" +
|
||||
indent_string + "+" + indent_string + "+" + indent_string;
|
||||
|
||||
std::clog << "\n" << indent_string << "\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "object type";
|
||||
std::clog << "\n+" << indent_string << "+\n";
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "object type";
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "gc count";
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "alloc count";
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "memory size";
|
||||
std::clog << "\n" << indent_string << "\n";
|
||||
std::clog << " |\n+" << indent_string << "+\n";
|
||||
|
||||
double total = 0;
|
||||
for(u8 i = 0; i<gc_type_size; ++i) {
|
||||
|
@ -319,33 +319,45 @@ void gc::info() const {
|
|||
continue;
|
||||
}
|
||||
total += static_cast<f64>(gcnt[i]);
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << name[i];
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << name[i];
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << gcnt[i];
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << acnt[i];
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << size[i];
|
||||
std::clog << "\n";
|
||||
std::clog << " |\n";
|
||||
}
|
||||
std::clog << indent_string << "\n";
|
||||
std::clog << "+" << indent_string << "+\n";
|
||||
|
||||
auto den = std::chrono::high_resolution_clock::duration::period::den;
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "detail";
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "detail";
|
||||
std::clog << " | " << left << setw(indent) << setfill(' ') << "time spend";
|
||||
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
||||
std::clog << " | " << left << setw(indent) << setfill('x') << "x";
|
||||
std::clog << "\n" << indent_string << "\n";
|
||||
std::clog << " |\n+" << indent_string << "+\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "gc time";
|
||||
std::clog << " | " << setw(indent-3) << std::setprecision(4) << worktime*1.0/den*1000 << " ms";
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "avg time";
|
||||
std::clog << " | " << setw(indent-3) << std::setprecision(4) << worktime*1.0/den*1000/total << " ms";
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "max gc";
|
||||
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_time*1.0/den*1000 << " ms";
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "max mark";
|
||||
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_mark_time*1.0/den*1000 << " ms";
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "max sweep";
|
||||
std::clog << " | " << setw(indent-3) << std::setprecision(4) << max_sweep_time*1.0/den*1000 << " ms";
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << "| " << left << setw(indent) << setfill(' ') << "concurrent";
|
||||
std::clog << " | " << setw(indent) << (flag_concurrent_mark_triggered? "true":"false");
|
||||
std::clog << setw(indent*2+7) << " " << "|\n";
|
||||
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "gc time";
|
||||
std::clog << " | " << worktime*1.0/den*1000 << " ms\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "avg time";
|
||||
std::clog << " | " << worktime*1.0/den*1000/total << " ms\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max gc";
|
||||
std::clog << " | " << max_time*1.0/den*1000 << " ms\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max mark";
|
||||
std::clog << " | " << max_mark_time*1.0/den*1000 << " ms\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "max sweep";
|
||||
std::clog << " | " << max_sweep_time*1.0/den*1000 << " ms\n";
|
||||
std::clog << " " << left << setw(indent) << setfill(' ') << "concurrent";
|
||||
std::clog << " | " << (flag_concurrent_mark_triggered? "true\n":"false\n");
|
||||
std::clog << last_line << "\n";
|
||||
}
|
||||
|
||||
|
@ -380,7 +392,7 @@ void gc::context_change(nas_co* co) {
|
|||
}
|
||||
|
||||
void gc::context_reserve() {
|
||||
// pc=0 means this coroutine is finished
|
||||
// pc = 0 means this coroutine is finished
|
||||
cort->status = running_context->pc?
|
||||
nas_co::status::suspended:
|
||||
nas_co::status::dead;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <thread>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "nasal.h"
|
||||
#include "nasal_type.h"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "nasal_import.h"
|
||||
#include "symbol_finder.h"
|
||||
#include "util/util.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
|
@ -7,7 +9,7 @@
|
|||
namespace nasal {
|
||||
|
||||
linker::linker(): show_path_flag(false), this_file("") {
|
||||
const auto seperator = is_windows()? ';':':';
|
||||
const auto seperator = util::is_windows()? ';':':';
|
||||
const auto PATH = std::string(getenv("PATH"));
|
||||
usize last = 0, position = PATH.find(seperator, 0);
|
||||
while(position!=std::string::npos) {
|
||||
|
@ -30,7 +32,7 @@ std::string linker::get_path(expr* node) {
|
|||
for(auto i : path) {
|
||||
file_relative_path += i->get_name();
|
||||
if (i!=path.back()) {
|
||||
file_relative_path += (is_windows()? "\\":"/");
|
||||
file_relative_path += (util::is_windows()? "\\":"/");
|
||||
}
|
||||
}
|
||||
return file_relative_path + ".nas";
|
||||
|
@ -60,7 +62,7 @@ std::string linker::find_real_file_path(const std::string& filename,
|
|||
|
||||
// we will find lib.nas in nasal std directory
|
||||
if (filename=="lib.nas") {
|
||||
return is_windows()?
|
||||
return util::is_windows()?
|
||||
find_real_file_path("std\\lib.nas", location):
|
||||
find_real_file_path("std/lib.nas", location);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "nasal_lexer.h"
|
||||
#include "nasal_parse.h"
|
||||
#include "symbol_finder.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#endif
|
||||
|
||||
#include "nasal_lexer.h"
|
||||
#include "repl.h"
|
||||
#include "repl/repl.h"
|
||||
#include "util/util.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
@ -61,7 +63,7 @@ void lexer::err_char() {
|
|||
char c = res[ptr++];
|
||||
err.err("lexer",
|
||||
{line, column-1, line, column, filename},
|
||||
"invalid character 0x" + char_to_hex(c)
|
||||
"invalid character 0x" + util::char_to_hex(c)
|
||||
);
|
||||
++invalid_char;
|
||||
}
|
||||
|
@ -75,6 +77,11 @@ void lexer::open(const std::string& file) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (file.empty()) {
|
||||
err.err("lexer", "empty input file");
|
||||
err.chkerr();
|
||||
}
|
||||
|
||||
// check file exsits and it is a regular file
|
||||
if (!fs::is_regular(file)) {
|
||||
err.err("lexer", "<"+file+"> is not a regular file");
|
||||
|
@ -96,14 +103,14 @@ void lexer::open(const std::string& file) {
|
|||
}
|
||||
|
||||
tok lexer::get_type(const std::string& str) {
|
||||
return token_mapper.count(str)? token_mapper.at(str):tok::null;
|
||||
return token_mapper.count(str)? token_mapper.at(str):tok::tk_null;
|
||||
}
|
||||
|
||||
std::string lexer::utf8_gen() {
|
||||
std::string str = "";
|
||||
while(ptr<res.size() && res[ptr]<0) {
|
||||
std::string tmp = "";
|
||||
u32 nbytes = utf8_hdchk(res[ptr]);
|
||||
u32 nbytes = util::utf8_hdchk(res[ptr]);
|
||||
if (!nbytes) {
|
||||
++ptr;
|
||||
++column;
|
||||
|
@ -120,9 +127,9 @@ std::string lexer::utf8_gen() {
|
|||
// utf8 character's total length is 1+nbytes
|
||||
if (tmp.length()!=1+nbytes) {
|
||||
++column;
|
||||
std::string utf_info = "0x" + char_to_hex(tmp[0]);
|
||||
std::string utf_info = "0x" + util::char_to_hex(tmp[0]);
|
||||
for(u32 i = 1; i<tmp.size(); ++i) {
|
||||
utf_info += " 0x" + char_to_hex(tmp[i]);
|
||||
utf_info += " 0x" + util::char_to_hex(tmp[i]);
|
||||
}
|
||||
err.err("lexer",
|
||||
{line, column-1, line, column, filename},
|
||||
|
@ -152,7 +159,8 @@ token lexer::id_gen() {
|
|||
tok type = get_type(str);
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
(type!=tok::null)? type:tok::id, str
|
||||
(type!=tok::tk_null)? type:tok::tk_id,
|
||||
str
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -174,7 +182,11 @@ token lexer::num_gen() {
|
|||
"invalid number `"+str+"`"
|
||||
);
|
||||
}
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_num,
|
||||
str
|
||||
};
|
||||
} else if (ptr+1<res.size() && res[ptr]=='0' && res[ptr+1]=='o') { // generate oct number
|
||||
std::string str = "0o";
|
||||
ptr += 2;
|
||||
|
@ -193,7 +205,11 @@ token lexer::num_gen() {
|
|||
"invalid number `"+str+"`"
|
||||
);
|
||||
}
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_num,
|
||||
str
|
||||
};
|
||||
}
|
||||
// generate dec number
|
||||
// dec number -> [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
|
||||
|
@ -213,7 +229,11 @@ token lexer::num_gen() {
|
|||
{begin_line, begin_column, line, column, filename},
|
||||
"invalid number `"+str+"`"
|
||||
);
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_num,
|
||||
"0"
|
||||
};
|
||||
}
|
||||
}
|
||||
if (ptr<res.size() && (res[ptr]=='e' || res[ptr]=='E')) {
|
||||
|
@ -231,11 +251,19 @@ token lexer::num_gen() {
|
|||
{begin_line, begin_column, line, column, filename},
|
||||
"invalid number `"+str+"`"
|
||||
);
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::num, "0"};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_num,
|
||||
"0"
|
||||
};
|
||||
}
|
||||
}
|
||||
column += str.length();
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::num, str};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_num,
|
||||
str
|
||||
};
|
||||
}
|
||||
|
||||
token lexer::str_gen() {
|
||||
|
@ -283,18 +311,26 @@ token lexer::str_gen() {
|
|||
{begin_line, begin_column, line, column, filename},
|
||||
"get EOF when generating string"
|
||||
);
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_str,
|
||||
str
|
||||
};
|
||||
}
|
||||
++column;
|
||||
|
||||
// if is not utf8, 1+utf8_hdchk should be 1
|
||||
if (begin=='`' && str.length()!=1+utf8_hdchk(str[0])) {
|
||||
if (begin=='`' && str.length()!=1+util::utf8_hdchk(str[0])) {
|
||||
err.err("lexer",
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
"\'`\' is used for string including one character"
|
||||
);
|
||||
}
|
||||
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
|
||||
return {
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
tok::tk_str,
|
||||
str
|
||||
};
|
||||
}
|
||||
|
||||
token lexer::single_opr() {
|
||||
|
@ -303,7 +339,7 @@ token lexer::single_opr() {
|
|||
std::string str(1, res[ptr]);
|
||||
++column;
|
||||
tok type = get_type(str);
|
||||
if (type==tok::null) {
|
||||
if (type==tok::tk_null) {
|
||||
err.err("lexer",
|
||||
{begin_line, begin_column, line, column, filename},
|
||||
"invalid operator `"+str+"`"
|
||||
|
@ -380,10 +416,14 @@ const error& lexer::scan(const std::string& file) {
|
|||
}
|
||||
if (toks.size()) {
|
||||
// eof token's location is the last token's location
|
||||
toks.push_back({toks.back().loc, tok::eof, "<eof>"});
|
||||
toks.push_back({toks.back().loc, tok::tk_eof, "<eof>"});
|
||||
} else {
|
||||
// if token sequence is empty, generate a default location
|
||||
toks.push_back({{line, column, line, column, filename}, tok::eof, "<eof>"});
|
||||
toks.push_back({
|
||||
{line, column, line, column, filename},
|
||||
tok::tk_eof,
|
||||
"<eof>"
|
||||
});
|
||||
}
|
||||
res = "";
|
||||
return err;
|
||||
|
|
|
@ -16,66 +16,66 @@
|
|||
|
||||
namespace nasal {
|
||||
|
||||
enum class tok:u32 {
|
||||
null=0, // null token (default token type)
|
||||
num, // number literal
|
||||
str, // string literal
|
||||
id, // identifier
|
||||
tktrue, // keyword true
|
||||
tkfalse, // keyword false
|
||||
use, // keyword use
|
||||
rfor, // loop keyword for
|
||||
forindex, // loop keyword forindex
|
||||
foreach, // loop keyword foreach
|
||||
rwhile, // loop keyword while
|
||||
var, // keyword for definition
|
||||
func, // keyword for definition of function
|
||||
brk, // loop keyword break
|
||||
cont, // loop keyword continue
|
||||
ret, // function keyword return
|
||||
rif, // condition expression keyword if
|
||||
elsif, // condition expression keyword elsif
|
||||
relse, // condition expression keyword else
|
||||
nil, // nil literal
|
||||
lcurve, // (
|
||||
rcurve, // )
|
||||
lbracket, // [
|
||||
rbracket, // ]
|
||||
lbrace, // {
|
||||
rbrace, // }
|
||||
semi, // ;
|
||||
opand, // operator and
|
||||
opor, // operator or
|
||||
comma, // ,
|
||||
dot, // .
|
||||
ellipsis, // ...
|
||||
quesmark, // ?
|
||||
colon, // :
|
||||
add, // operator +
|
||||
sub, // operator -
|
||||
mult, // operator *
|
||||
div, // operator /
|
||||
floater, // operator ~ and binary operator ~
|
||||
btand, // bitwise operator &
|
||||
btor, // bitwise operator |
|
||||
btxor, // bitwise operator ^
|
||||
opnot, // operator !
|
||||
eq, // operator =
|
||||
addeq, // operator +=
|
||||
subeq, // operator -=
|
||||
multeq, // operator *=
|
||||
diveq, // operator /=
|
||||
lnkeq, // operator ~=
|
||||
btandeq, // operator &=
|
||||
btoreq, // operator |=
|
||||
btxoreq, // operator ^=
|
||||
cmpeq, // operator ==
|
||||
neq, // operator !=
|
||||
less, // operator <
|
||||
leq, // operator <=
|
||||
grt, // operator >
|
||||
geq, // operator >=
|
||||
eof // <eof> end of token list
|
||||
enum class tok {
|
||||
tk_null = 0, // null token (default token type)
|
||||
tk_num, // number literal
|
||||
tk_str, // string literal
|
||||
tk_id, // identifier
|
||||
tk_true, // keyword true
|
||||
tk_false, // keyword false
|
||||
tk_use, // keyword use
|
||||
tk_for, // loop keyword for
|
||||
tk_forindex, // loop keyword forindex
|
||||
tk_foreach, // loop keyword foreach
|
||||
tk_while, // loop keyword while
|
||||
tk_var, // keyword for definition
|
||||
tk_func, // keyword for definition of function
|
||||
tk_brk, // loop keyword break
|
||||
tk_cont, // loop keyword continue
|
||||
tk_ret, // function keyword return
|
||||
tk_if, // condition expression keyword if
|
||||
tk_elsif, // condition expression keyword elsif
|
||||
tk_else, // condition expression keyword else
|
||||
tk_nil, // nil literal
|
||||
tk_lcurve, // (
|
||||
tk_rcurve, // )
|
||||
tk_lbracket, // [
|
||||
tk_rbracket, // ]
|
||||
tk_lbrace, // {
|
||||
tk_rbrace, // }
|
||||
tk_semi, // ;
|
||||
tk_and, // operator and
|
||||
tk_or, // operator or
|
||||
tk_comma, // ,
|
||||
tk_dot, // .
|
||||
tk_ellipsis, // ...
|
||||
tk_quesmark, // ?
|
||||
tk_colon, // :
|
||||
tk_add, // operator +
|
||||
tk_sub, // operator -
|
||||
tk_mult, // operator *
|
||||
tk_div, // operator /
|
||||
tk_floater, // operator ~ and binary operator ~
|
||||
tk_btand, // bitwise operator &
|
||||
tk_btor, // bitwise operator |
|
||||
tk_btxor, // bitwise operator ^
|
||||
tk_not, // operator !
|
||||
tk_eq, // operator =
|
||||
tk_addeq, // operator +=
|
||||
tk_subeq, // operator -=
|
||||
tk_multeq, // operator *=
|
||||
tk_diveq, // operator /=
|
||||
tk_lnkeq, // operator ~=
|
||||
tk_btandeq, // operator &=
|
||||
tk_btoreq, // operator |=
|
||||
tk_btxoreq, // operator ^=
|
||||
tk_cmpeq, // operator ==
|
||||
tk_neq, // operator !=
|
||||
tk_less, // operator <
|
||||
tk_leq, // operator <=
|
||||
tk_grt, // operator >
|
||||
tk_geq, // operator >=
|
||||
tk_eof // <eof> end of token list
|
||||
};
|
||||
|
||||
struct token {
|
||||
|
@ -99,60 +99,60 @@ private:
|
|||
std::vector<token> toks;
|
||||
|
||||
const std::unordered_map<std::string, tok> token_mapper = {
|
||||
{"use" ,tok::use },
|
||||
{"true" ,tok::tktrue },
|
||||
{"false" ,tok::tkfalse },
|
||||
{"for" ,tok::rfor },
|
||||
{"forindex",tok::forindex},
|
||||
{"foreach" ,tok::foreach },
|
||||
{"while" ,tok::rwhile },
|
||||
{"var" ,tok::var },
|
||||
{"func" ,tok::func },
|
||||
{"break" ,tok::brk },
|
||||
{"continue",tok::cont },
|
||||
{"return" ,tok::ret },
|
||||
{"if" ,tok::rif },
|
||||
{"elsif" ,tok::elsif },
|
||||
{"else" ,tok::relse },
|
||||
{"nil" ,tok::nil },
|
||||
{"(" ,tok::lcurve },
|
||||
{")" ,tok::rcurve },
|
||||
{"[" ,tok::lbracket},
|
||||
{"]" ,tok::rbracket},
|
||||
{"{" ,tok::lbrace },
|
||||
{"}" ,tok::rbrace },
|
||||
{";" ,tok::semi },
|
||||
{"and" ,tok::opand },
|
||||
{"or" ,tok::opor },
|
||||
{"," ,tok::comma },
|
||||
{"." ,tok::dot },
|
||||
{"..." ,tok::ellipsis},
|
||||
{"?" ,tok::quesmark},
|
||||
{":" ,tok::colon },
|
||||
{"+" ,tok::add },
|
||||
{"-" ,tok::sub },
|
||||
{"*" ,tok::mult },
|
||||
{"/" ,tok::div },
|
||||
{"~" ,tok::floater },
|
||||
{"&" ,tok::btand },
|
||||
{"|" ,tok::btor },
|
||||
{"^" ,tok::btxor },
|
||||
{"!" ,tok::opnot },
|
||||
{"=" ,tok::eq },
|
||||
{"+=" ,tok::addeq },
|
||||
{"-=" ,tok::subeq },
|
||||
{"*=" ,tok::multeq },
|
||||
{"/=" ,tok::diveq },
|
||||
{"~=" ,tok::lnkeq },
|
||||
{"&=" ,tok::btandeq },
|
||||
{"|=" ,tok::btoreq },
|
||||
{"^=" ,tok::btxoreq },
|
||||
{"==" ,tok::cmpeq },
|
||||
{"!=" ,tok::neq },
|
||||
{"<" ,tok::less },
|
||||
{"<=" ,tok::leq },
|
||||
{">" ,tok::grt },
|
||||
{">=" ,tok::geq }
|
||||
{"use" , tok::tk_use },
|
||||
{"true" , tok::tk_true },
|
||||
{"false" , tok::tk_false },
|
||||
{"for" , tok::tk_for },
|
||||
{"forindex", tok::tk_forindex},
|
||||
{"foreach" , tok::tk_foreach },
|
||||
{"while" , tok::tk_while },
|
||||
{"var" , tok::tk_var },
|
||||
{"func" , tok::tk_func },
|
||||
{"break" , tok::tk_brk },
|
||||
{"continue", tok::tk_cont },
|
||||
{"return" , tok::tk_ret },
|
||||
{"if" , tok::tk_if },
|
||||
{"elsif" , tok::tk_elsif },
|
||||
{"else" , tok::tk_else },
|
||||
{"nil" , tok::tk_nil },
|
||||
{"(" , tok::tk_lcurve },
|
||||
{")" , tok::tk_rcurve },
|
||||
{"[" , tok::tk_lbracket},
|
||||
{"]" , tok::tk_rbracket},
|
||||
{"{" , tok::tk_lbrace },
|
||||
{"}" , tok::tk_rbrace },
|
||||
{";" , tok::tk_semi },
|
||||
{"and" , tok::tk_and },
|
||||
{"or" , tok::tk_or },
|
||||
{"," , tok::tk_comma },
|
||||
{"." , tok::tk_dot },
|
||||
{"..." , tok::tk_ellipsis},
|
||||
{"?" , tok::tk_quesmark},
|
||||
{":" , tok::tk_colon },
|
||||
{"+" , tok::tk_add },
|
||||
{"-" , tok::tk_sub },
|
||||
{"*" , tok::tk_mult },
|
||||
{"/" , tok::tk_div },
|
||||
{"~" , tok::tk_floater },
|
||||
{"&" , tok::tk_btand },
|
||||
{"|" , tok::tk_btor },
|
||||
{"^" , tok::tk_btxor },
|
||||
{"!" , tok::tk_not },
|
||||
{"=" , tok::tk_eq },
|
||||
{"+=" , tok::tk_addeq },
|
||||
{"-=" , tok::tk_subeq },
|
||||
{"*=" , tok::tk_multeq },
|
||||
{"/=" , tok::tk_diveq },
|
||||
{"~=" , tok::tk_lnkeq },
|
||||
{"&=" , tok::tk_btandeq },
|
||||
{"|=" , tok::tk_btoreq },
|
||||
{"^=" , tok::tk_btxoreq },
|
||||
{"==" , tok::tk_cmpeq },
|
||||
{"!=" , tok::tk_neq },
|
||||
{"<" , tok::tk_less },
|
||||
{"<=" , tok::tk_leq },
|
||||
{">" , tok::tk_grt },
|
||||
{">=" , tok::tk_geq }
|
||||
};
|
||||
|
||||
tok get_type(const std::string&);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "nasal_opcode.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
@ -48,7 +49,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
|
||||
// dump operand index and bytecode(hex format)
|
||||
out << hex << "0x"
|
||||
<< setw(6) << setfill('0') << index << " "
|
||||
<< setw(8) << setfill('0') << index << " "
|
||||
<< setw(2) << setfill('0') << static_cast<u32>(op) << ":" << dec;
|
||||
|
||||
// dump immediate number(hex format)
|
||||
|
@ -80,7 +81,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
break;
|
||||
case op_lnkeqc:
|
||||
out << hex << "0x" << num << dec;
|
||||
out << " (" << rawstr(const_string[num], 16) << ")";
|
||||
out << " (" << util::rawstr(const_string[num], 16) << ")";
|
||||
break;
|
||||
case op_addecp:
|
||||
case op_subecp:
|
||||
|
@ -91,7 +92,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
break;
|
||||
case op_lnkecp:
|
||||
out << hex << "0x" << num << dec;
|
||||
out << " (" << rawstr(const_string[num], 16) << ") sp-1";
|
||||
out << " (" << util::rawstr(const_string[num], 16) << ") sp-1";
|
||||
break;
|
||||
case op_addc:
|
||||
case op_subc:
|
||||
|
@ -141,7 +142,7 @@ void codestream::dump(std::ostream& out) const {
|
|||
case op_deft:
|
||||
case op_dyn:
|
||||
out << hex << "0x" << num << dec;
|
||||
out << " (" << rawstr(const_string[num], 16) << ")";
|
||||
out << " (" << util::rawstr(const_string[num], 16) << ")";
|
||||
break;
|
||||
default:
|
||||
if (files) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "nasal.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,66 +16,68 @@ class parse {
|
|||
|
||||
private:
|
||||
u64 ptr;
|
||||
u64 in_func; // count function block
|
||||
u64 in_loop; // count loop block
|
||||
u64 in_func_depth; // count function block
|
||||
u64 in_loop_depth; // count loop block
|
||||
const token* toks;
|
||||
code_block* root;
|
||||
error err;
|
||||
|
||||
private:
|
||||
const std::unordered_map<tok, std::string> tokname {
|
||||
{tok::use ,"use" },
|
||||
{tok::rfor ,"for" },
|
||||
{tok::forindex,"forindex"},
|
||||
{tok::foreach ,"foreach" },
|
||||
{tok::rwhile ,"while" },
|
||||
{tok::var ,"var" },
|
||||
{tok::func ,"func" },
|
||||
{tok::brk ,"break" },
|
||||
{tok::cont ,"continue"},
|
||||
{tok::ret ,"return" },
|
||||
{tok::rif ,"if" },
|
||||
{tok::elsif ,"elsif" },
|
||||
{tok::relse ,"else" },
|
||||
{tok::nil ,"nil" },
|
||||
{tok::lcurve ,"(" },
|
||||
{tok::rcurve ,")" },
|
||||
{tok::lbracket,"[" },
|
||||
{tok::rbracket,"]" },
|
||||
{tok::lbrace ,"{" },
|
||||
{tok::rbrace ,"}" },
|
||||
{tok::semi ,";" },
|
||||
{tok::opand ,"and" },
|
||||
{tok::opor ,"or" },
|
||||
{tok::comma ,"," },
|
||||
{tok::dot ,"." },
|
||||
{tok::ellipsis,"..." },
|
||||
{tok::quesmark,"?" },
|
||||
{tok::colon ,":" },
|
||||
{tok::add ,"+" },
|
||||
{tok::sub ,"-" },
|
||||
{tok::mult ,"*" },
|
||||
{tok::div ,"/" },
|
||||
{tok::floater ,"~" },
|
||||
{tok::btand ,"&" },
|
||||
{tok::btor ,"|" },
|
||||
{tok::btxor ,"^" },
|
||||
{tok::opnot ,"!" },
|
||||
{tok::eq ,"=" },
|
||||
{tok::addeq ,"+=" },
|
||||
{tok::subeq ,"-=" },
|
||||
{tok::multeq ,"*=" },
|
||||
{tok::diveq ,"/=" },
|
||||
{tok::lnkeq ,"~=" },
|
||||
{tok::btandeq ,"&=" },
|
||||
{tok::btoreq ,"|=" },
|
||||
{tok::btxoreq ,"^=" },
|
||||
{tok::cmpeq ,"==" },
|
||||
{tok::neq ,"!=" },
|
||||
{tok::less ,"<" },
|
||||
{tok::leq ,"<=" },
|
||||
{tok::grt ,">" },
|
||||
{tok::geq ,">=" }
|
||||
const std::unordered_map<tok, std::string> tokname = {
|
||||
{tok::tk_true , "true" },
|
||||
{tok::tk_false , "false" },
|
||||
{tok::tk_use , "use" },
|
||||
{tok::tk_for , "for" },
|
||||
{tok::tk_forindex, "forindex"},
|
||||
{tok::tk_foreach , "foreach" },
|
||||
{tok::tk_while , "while" },
|
||||
{tok::tk_var , "var" },
|
||||
{tok::tk_func , "func" },
|
||||
{tok::tk_brk , "break" },
|
||||
{tok::tk_cont , "continue"},
|
||||
{tok::tk_ret , "return" },
|
||||
{tok::tk_if , "if" },
|
||||
{tok::tk_elsif , "elsif" },
|
||||
{tok::tk_else , "else" },
|
||||
{tok::tk_nil , "nil" },
|
||||
{tok::tk_lcurve , "(" },
|
||||
{tok::tk_rcurve , ")" },
|
||||
{tok::tk_lbracket, "[" },
|
||||
{tok::tk_rbracket, "]" },
|
||||
{tok::tk_lbrace , "{" },
|
||||
{tok::tk_rbrace , "}" },
|
||||
{tok::tk_semi , ";" },
|
||||
{tok::tk_and , "and" },
|
||||
{tok::tk_or , "or" },
|
||||
{tok::tk_comma , "," },
|
||||
{tok::tk_dot , "." },
|
||||
{tok::tk_ellipsis, "..." },
|
||||
{tok::tk_quesmark, "?" },
|
||||
{tok::tk_colon , ":" },
|
||||
{tok::tk_add , "+" },
|
||||
{tok::tk_sub , "-" },
|
||||
{tok::tk_mult , "*" },
|
||||
{tok::tk_div , "/" },
|
||||
{tok::tk_floater , "~" },
|
||||
{tok::tk_btand , "&" },
|
||||
{tok::tk_btor , "|" },
|
||||
{tok::tk_btxor , "^" },
|
||||
{tok::tk_not , "!" },
|
||||
{tok::tk_eq , "=" },
|
||||
{tok::tk_addeq , "+=" },
|
||||
{tok::tk_subeq , "-=" },
|
||||
{tok::tk_multeq , "*=" },
|
||||
{tok::tk_diveq , "/=" },
|
||||
{tok::tk_lnkeq , "~=" },
|
||||
{tok::tk_btandeq , "&=" },
|
||||
{tok::tk_btoreq , "|=" },
|
||||
{tok::tk_btxoreq , "^=" },
|
||||
{tok::tk_cmpeq , "==" },
|
||||
{tok::tk_neq , "!=" },
|
||||
{tok::tk_less , "<" },
|
||||
{tok::tk_leq , "<=" },
|
||||
{tok::tk_grt , ">" },
|
||||
{tok::tk_geq , ">=" }
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -151,7 +153,8 @@ public:
|
|||
}
|
||||
|
||||
public:
|
||||
parse(): ptr(0), in_func(0), in_loop(0), toks(nullptr), root(nullptr) {}
|
||||
parse(): ptr(0), in_func_depth(0), in_loop_depth(0),
|
||||
toks(nullptr), root(nullptr) {}
|
||||
~parse() {delete root;}
|
||||
const error& compile(const lexer&);
|
||||
static void easter_egg();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "nasal_type.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
@ -268,7 +269,7 @@ void nas_val::clear() {
|
|||
}
|
||||
|
||||
f64 var::to_num() {
|
||||
return type!=vm_type::vm_str? val.num:str_to_num(str().c_str());
|
||||
return type!=vm_type::vm_str? val.num:util::str_to_num(str().c_str());
|
||||
}
|
||||
|
||||
std::string var::to_str() {
|
||||
|
@ -384,7 +385,7 @@ nas_map& var::map() {
|
|||
}
|
||||
|
||||
var nas_err(const std::string& error_function_name, const std::string& info) {
|
||||
std::cerr << "\n[vm] " << error_function_name << ": " << info << "\n";
|
||||
std::cerr << "[vm] " << error_function_name << ": " << info << "\n";
|
||||
return var::none();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
#include "nasal.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "nasal_vm.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
@ -75,8 +76,8 @@ void vm::value_info(var& val) {
|
|||
case vm_type::vm_nil: std::clog << "| nil |"; break;
|
||||
case vm_type::vm_num: std::clog << "| num | " << val.num(); break;
|
||||
case vm_type::vm_str: std::clog << "| str | <0x" << std::hex << p
|
||||
<< "> " << rawstr(val.str(), 16)
|
||||
<< std::dec; break;
|
||||
<< "> \"" << util::rawstr(val.str(), 16)
|
||||
<< "\"" << std::dec; break;
|
||||
case vm_type::vm_func: std::clog << "| func | <0x" << std::hex << p
|
||||
<< std::dec << "> " << val.func();
|
||||
break;
|
||||
|
@ -191,7 +192,7 @@ void vm::trace_back() {
|
|||
}
|
||||
if (same) {
|
||||
std::clog << " 0x" << std::hex
|
||||
<< std::setw(6) << std::setfill('0')
|
||||
<< std::setw(8) << std::setfill('0')
|
||||
<< prev << std::dec << " "
|
||||
<< same << " same call(s)\n";
|
||||
same = 0;
|
||||
|
@ -212,7 +213,7 @@ void vm::stack_info(const u64 limit = 16) {
|
|||
|
||||
for(u32 i = 0; i<limit && top>=bottom; ++i, --top) {
|
||||
std::clog << " 0x" << std::hex
|
||||
<< std::setw(6) << std::setfill('0')
|
||||
<< std::setw(8) << std::setfill('0')
|
||||
<< static_cast<u64>(top-bottom) << std::dec
|
||||
<< " ";
|
||||
value_info(top[0]);
|
||||
|
@ -220,22 +221,22 @@ void vm::stack_info(const u64 limit = 16) {
|
|||
}
|
||||
|
||||
void vm::register_info() {
|
||||
std::clog << "\nregisters (" << (ngc.cort? "coroutine":"main")
|
||||
<< ")\n" << std::hex
|
||||
<< " [pc ] | pc | 0x" << ctx.pc << "\n"
|
||||
<< " [global] | addr | 0x"
|
||||
std::clog << "\nregisters (" << (ngc.cort? "coroutine":"main") << ")\n";
|
||||
std::clog << std::hex
|
||||
<< " [ pc ] | pc | 0x" << ctx.pc << "\n"
|
||||
<< " [ global ] | addr | 0x"
|
||||
<< reinterpret_cast<u64>(global) << "\n"
|
||||
<< " [local ] | addr | 0x"
|
||||
<< " [ local ] | addr | 0x"
|
||||
<< reinterpret_cast<u64>(ctx.localr) << "\n"
|
||||
<< " [memr ] | addr | 0x"
|
||||
<< " [ memr ] | addr | 0x"
|
||||
<< reinterpret_cast<u64>(ctx.memr) << "\n"
|
||||
<< " [canary] | addr | 0x"
|
||||
<< " [ canary ] | addr | 0x"
|
||||
<< reinterpret_cast<u64>(ctx.canary) << "\n"
|
||||
<< " [top ] | addr | 0x"
|
||||
<< " [ top ] | addr | 0x"
|
||||
<< reinterpret_cast<u64>(ctx.top) << "\n"
|
||||
<< std::dec;
|
||||
std::clog << " [funcr ] "; value_info(ctx.funcr);
|
||||
std::clog << " [upval ] "; value_info(ctx.upvalr);
|
||||
std::clog << " [ funcr ] "; value_info(ctx.funcr);
|
||||
std::clog << " [ upval ] "; value_info(ctx.upvalr);
|
||||
}
|
||||
|
||||
void vm::global_state() {
|
||||
|
@ -245,7 +246,7 @@ void vm::global_state() {
|
|||
std::clog << "\nglobal (0x" << std::hex
|
||||
<< reinterpret_cast<u64>(global) << ")\n" << std::dec;
|
||||
for(usize i = 0; i<global_size; ++i) {
|
||||
std::clog << " 0x" << std::hex << std::setw(6)
|
||||
std::clog << " 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << i << std::dec
|
||||
<< " ";
|
||||
value_info(global[i]);
|
||||
|
@ -261,7 +262,7 @@ void vm::local_state() {
|
|||
<< " <+" << static_cast<u64>(ctx.localr-ctx.stack)
|
||||
<< ">)\n" << std::dec;
|
||||
for(u32 i = 0; i<lsize; ++i) {
|
||||
std::clog << " 0x" << std::hex << std::setw(6)
|
||||
std::clog << " 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << i << std::dec
|
||||
<< " ";
|
||||
value_info(ctx.localr[i]);
|
||||
|
@ -278,7 +279,7 @@ void vm::upvalue_state() {
|
|||
std::clog << " -> upval[" << i << "]:\n";
|
||||
auto& uv = upval[i].upval();
|
||||
for(u32 j = 0; j<uv.size; ++j) {
|
||||
std::clog << " 0x" << std::hex << std::setw(6)
|
||||
std::clog << " 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << j << std::dec
|
||||
<< " ";
|
||||
value_info(uv[j]);
|
||||
|
@ -391,7 +392,7 @@ std::string vm::type_name_string(const var& value) const {
|
|||
}
|
||||
|
||||
void vm::die(const std::string& str) {
|
||||
std::cerr << "\n[vm] error: " << str << "\n";
|
||||
std::cerr << "[vm] error: " << str << "\n";
|
||||
function_call_trace();
|
||||
trace_back();
|
||||
stack_info();
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "nasal_import.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "nasal_codegen.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4244)
|
||||
|
@ -50,6 +51,7 @@ protected:
|
|||
/* limited mode, will not load unsafe system api if switched on */
|
||||
bool flag_limited_mode = false;
|
||||
|
||||
protected:
|
||||
/* vm initializing function */
|
||||
void vm_init_enrty(const std::vector<std::string>&,
|
||||
const std::vector<f64>&,
|
||||
|
@ -60,6 +62,7 @@ protected:
|
|||
const std::vector<std::string>&);
|
||||
void context_and_global_init();
|
||||
|
||||
protected:
|
||||
/* debug functions */
|
||||
bool verbose = false;
|
||||
void value_info(var&);
|
||||
|
@ -190,20 +193,31 @@ public:
|
|||
const std::vector<std::string>&); // get command line arguments
|
||||
|
||||
/* set detail report info flag */
|
||||
void set_detail_report_info(bool flag) {verbose = flag;}
|
||||
void set_detail_report_info(bool flag) {
|
||||
verbose = flag;
|
||||
}
|
||||
|
||||
/* set repl mode flag */
|
||||
void set_repl_mode_flag(bool flag) {is_repl_mode = flag;}
|
||||
void set_repl_mode_flag(bool flag) {
|
||||
is_repl_mode = flag;
|
||||
}
|
||||
|
||||
/* set repl output flag */
|
||||
void set_allow_repl_output_flag(bool flag) {allow_repl_output = flag;}
|
||||
void set_allow_repl_output_flag(bool flag) {
|
||||
allow_repl_output = flag;
|
||||
}
|
||||
|
||||
/* set limit mode flag */
|
||||
void set_limit_mode_flag(bool flag) {flag_limited_mode = flag;}
|
||||
void set_limit_mode_flag(bool flag) {
|
||||
flag_limited_mode = flag;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool vm::cond(var& val) {
|
||||
if (val.is_num()) {
|
||||
return val.num();
|
||||
} else if (val.is_str()) {
|
||||
const f64 num = str_to_num(val.str().c_str());
|
||||
const f64 num = util::str_to_num(val.str().c_str());
|
||||
return std::isnan(num)? !val.str().empty():num;
|
||||
}
|
||||
return false;
|
||||
|
@ -320,7 +334,7 @@ inline void vm::o_lnot() {
|
|||
case vm_type::vm_nil: ctx.top[0] = one; break;
|
||||
case vm_type::vm_num: ctx.top[0] = val.num()? zero:one; break;
|
||||
case vm_type::vm_str: {
|
||||
const f64 num = str_to_num(val.str().c_str());
|
||||
const f64 num = util::str_to_num(val.str().c_str());
|
||||
if (std::isnan(num)) {
|
||||
ctx.top[0] = var::num(static_cast<f64>(val.str().empty()));
|
||||
} else {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace nasal {
|
||||
|
||||
var builtin_unsafe(context* ctx, gc* ngc) {
|
||||
|
@ -41,7 +47,7 @@ var builtin_append(context* ctx, gc* ngc) {
|
|||
var vec = local[1];
|
||||
var elem = local[2];
|
||||
if (!vec.is_vec()) {
|
||||
return nas_err("append", "\"vec\" must be vector");
|
||||
return nas_err("native::append", "\"vec\" must be vector");
|
||||
}
|
||||
auto& v = vec.vec().elems;
|
||||
for(auto& i : elem.vec().elems) {
|
||||
|
@ -55,7 +61,7 @@ var builtin_setsize(context* ctx, gc* ngc) {
|
|||
var vec = local[1];
|
||||
var size = local[2];
|
||||
if (!vec.is_vec()) {
|
||||
return nas_err("setsize", "\"vec\" must be vector");
|
||||
return nas_err("native::setsize", "\"vec\" must be vector");
|
||||
}
|
||||
if (!size.is_num() || size.num()<0) {
|
||||
return nil;
|
||||
|
@ -89,10 +95,10 @@ var builtin_split(context* ctx, gc* ngc) {
|
|||
var delimeter = local[1];
|
||||
var str = local[2];
|
||||
if (!delimeter.is_str()) {
|
||||
return nas_err("split", "\"separator\" must be string");
|
||||
return nas_err("native::split", "\"separator\" must be string");
|
||||
}
|
||||
if (!str.is_str()) {
|
||||
return nas_err("split", "\"str\" must be string");
|
||||
return nas_err("native::split", "\"str\" must be string");
|
||||
}
|
||||
const auto& deli = delimeter.str();
|
||||
const auto& s = str.str();
|
||||
|
@ -127,7 +133,7 @@ var builtin_split(context* ctx, gc* ngc) {
|
|||
var builtin_rand(context* ctx, gc* ngc) {
|
||||
auto val = ctx->localr[1];
|
||||
if (!val.is_num() && !val.is_nil()) {
|
||||
return nas_err("rand", "\"seed\" must be nil or number");
|
||||
return nas_err("native::rand", "\"seed\" must be nil or number");
|
||||
}
|
||||
if (val.is_num()) {
|
||||
srand(static_cast<u32>(val.num()));
|
||||
|
@ -187,7 +193,7 @@ var builtin_num(context* ctx, gc* ngc) {
|
|||
var builtin_pop(context* ctx, gc* ngc) {
|
||||
auto val = ctx->localr[1];
|
||||
if (!val.is_vec()) {
|
||||
return nas_err("pop", "\"vec\" must be vector");
|
||||
return nas_err("native::pop", "\"vec\" must be vector");
|
||||
}
|
||||
auto& vec = val.vec().elems;
|
||||
if (vec.size()) {
|
||||
|
@ -220,7 +226,7 @@ var builtin_size(context* ctx, gc* ngc) {
|
|||
var builtin_time(context* ctx, gc* ngc) {
|
||||
auto val = ctx->localr[1];
|
||||
if (!val.is_num()) {
|
||||
return nas_err("time", "\"begin\" must be number");
|
||||
return nas_err("native::time", "\"begin\" must be number");
|
||||
}
|
||||
auto begin = static_cast<time_t>(val.num());
|
||||
return var::num(static_cast<f64>(time(&begin)));
|
||||
|
@ -241,7 +247,7 @@ var builtin_delete(context* ctx, gc* ngc) {
|
|||
var hash = local[1];
|
||||
var key = local[2];
|
||||
if (!hash.is_hash()) {
|
||||
return nas_err("delete", "\"hash\" must be hash");
|
||||
return nas_err("native::delete", "\"hash\" must be hash");
|
||||
}
|
||||
if (!key.is_str()) {
|
||||
return nil;
|
||||
|
@ -255,7 +261,7 @@ var builtin_delete(context* ctx, gc* ngc) {
|
|||
var builtin_keys(context* ctx, gc* ngc) {
|
||||
auto hash = ctx->localr[1];
|
||||
if (!hash.is_hash() && !hash.is_map()) {
|
||||
return nas_err("keys", "\"hash\" must be hash");
|
||||
return nas_err("native::keys", "\"hash\" must be hash");
|
||||
}
|
||||
// avoid being sweeped
|
||||
auto res = ngc->temp = ngc->alloc(vm_type::vm_vec);
|
||||
|
@ -274,7 +280,7 @@ var builtin_keys(context* ctx, gc* ngc) {
|
|||
}
|
||||
|
||||
var builtin_die(context* ctx, gc* ngc) {
|
||||
return nas_err("error", ctx->localr[1].to_str());
|
||||
return nas_err("native::error", ctx->localr[1].to_str());
|
||||
}
|
||||
|
||||
var builtin_find(context* ctx, gc* ngc) {
|
||||
|
@ -311,18 +317,18 @@ var builtin_substr(context* ctx, gc* ngc) {
|
|||
var beg = local[2];
|
||||
var len = local[3];
|
||||
if (!str.is_str()) {
|
||||
return nas_err("substr", "\"str\" must be string");
|
||||
return nas_err("native::substr", "\"str\" must be string");
|
||||
}
|
||||
if (!beg.is_num() || beg.num()<0) {
|
||||
return nas_err("substr", "\"begin\" should be number >= 0");
|
||||
return nas_err("native::substr", "\"begin\" should be number >= 0");
|
||||
}
|
||||
if (!len.is_num() || len.num()<0) {
|
||||
return nas_err("substr", "\"length\" should be number >= 0");
|
||||
return nas_err("native::substr", "\"length\" should be number >= 0");
|
||||
}
|
||||
auto begin = static_cast<usize>(beg.num());
|
||||
auto length = static_cast<usize>(len.num());
|
||||
if (begin>=str.str().length()) {
|
||||
return nas_err("susbtr", "begin index out of range: "+std::to_string(begin));
|
||||
return nas_err("native::susbtr", "begin index out of range: "+std::to_string(begin));
|
||||
}
|
||||
return ngc->newstr(str.str().substr(begin, length));
|
||||
}
|
||||
|
@ -342,10 +348,10 @@ var builtin_left(context* ctx, gc* ngc) {
|
|||
var len = local[2];
|
||||
|
||||
if (!str.is_str()) {
|
||||
return nas_err("left", "\"string\" must be string");
|
||||
return nas_err("native::left", "\"string\" must be string");
|
||||
}
|
||||
if (!len.is_num()) {
|
||||
return nas_err("left", "\"length\" must be number");
|
||||
return nas_err("native::left", "\"length\" must be number");
|
||||
}
|
||||
if (len.num()<0) {
|
||||
return ngc->newstr("");
|
||||
|
@ -359,10 +365,10 @@ var builtin_right(context* ctx, gc* ngc) {
|
|||
var len = local[2];
|
||||
|
||||
if (!str.is_str()) {
|
||||
return nas_err("right", "\"string\" must be string");
|
||||
return nas_err("native::right", "\"string\" must be string");
|
||||
}
|
||||
if (!len.is_num()) {
|
||||
return nas_err("right", "\"length\" must be number");
|
||||
return nas_err("native::right", "\"length\" must be number");
|
||||
}
|
||||
|
||||
i32 length = static_cast<i32>(len.num());
|
||||
|
@ -382,7 +388,7 @@ var builtin_cmp(context* ctx, gc* ngc) {
|
|||
var a = local[1];
|
||||
var b = local[2];
|
||||
if (!a.is_str() || !b.is_str()) {
|
||||
return nas_err("cmp", "\"a\" and \"b\" must be string");
|
||||
return nas_err("native::cmp", "\"a\" and \"b\" must be string");
|
||||
}
|
||||
return var::num(static_cast<f64>(strcmp(
|
||||
a.str().c_str(),
|
||||
|
@ -425,7 +431,7 @@ var builtin_char(context* ctx, gc* ngc) {
|
|||
var builtin_values(context* ctx, gc* ngc) {
|
||||
auto hash = ctx->localr[1];
|
||||
if (!hash.is_hash() && !hash.is_map()) {
|
||||
return nas_err("values", "\"hash\" must be hash or namespace");
|
||||
return nas_err("native::values", "\"hash\" must be hash or namespace");
|
||||
}
|
||||
auto vec = ngc->alloc(vm_type::vm_vec);
|
||||
auto& v = vec.vec().elems;
|
||||
|
@ -459,11 +465,11 @@ var builtin_sleep(context* ctx, gc* ngc) {
|
|||
}
|
||||
|
||||
var builtin_platform(context* ctx, gc* ngc) {
|
||||
return ngc->newstr(get_platform());
|
||||
return ngc->newstr(util::get_platform());
|
||||
}
|
||||
|
||||
var builtin_arch(context* ctx, gc* ngc) {
|
||||
return ngc->newstr(get_arch());
|
||||
return ngc->newstr(util::get_arch());
|
||||
}
|
||||
|
||||
// md5 related functions
|
||||
|
@ -560,7 +566,7 @@ std::string md5(const std::string& src) {
|
|||
var builtin_md5(context* ctx, gc* ngc) {
|
||||
auto str = ctx->localr[1];
|
||||
if (!str.is_str()) {
|
||||
return nas_err("md5", "\"str\" must be string");
|
||||
return nas_err("native::md5", "\"str\" must be string");
|
||||
}
|
||||
return ngc->newstr(md5(str.str()));
|
||||
}
|
||||
|
@ -700,7 +706,7 @@ var builtin_logtime(context* ctx, gc* ngc) {
|
|||
var builtin_ghosttype(context* ctx, gc* ngc) {
|
||||
auto arg = ctx->localr[1];
|
||||
if (!arg.is_ghost()) {
|
||||
return nas_err("ghosttype", "this is not a ghost object.");
|
||||
return nas_err("native::ghosttype", "this is not a ghost object.");
|
||||
}
|
||||
|
||||
const auto& name = arg.ghost().get_ghost_name();
|
||||
|
@ -717,6 +723,15 @@ var builtin_ghosttype(context* ctx, gc* ngc) {
|
|||
return ngc->newstr(name);
|
||||
}
|
||||
|
||||
var builtin_set_utf8_output(context* ctx, gc* ngc) {
|
||||
#ifdef _WIN32
|
||||
// allow 65001 code page
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
// do nothing on other platforms
|
||||
return nil;
|
||||
}
|
||||
|
||||
nasal_builtin_table builtin[] = {
|
||||
{"__print", builtin_print},
|
||||
{"__println", builtin_println},
|
||||
|
@ -763,6 +778,7 @@ nasal_builtin_table builtin[] = {
|
|||
{"__gcinfo", builtin_gcinfo},
|
||||
{"__logtime", builtin_logtime},
|
||||
{"__ghosttype", builtin_ghosttype},
|
||||
{"__set_utf8_output", builtin_set_utf8_output},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
|
@ -81,6 +81,9 @@ var builtin_gcinfo(context*, gc*);
|
|||
var builtin_logtime(context*, gc*);
|
||||
var builtin_ghosttype(context*, gc*);
|
||||
|
||||
// only useful on windows platform
|
||||
var builtin_set_utf8_output(context*, gc*);
|
||||
|
||||
// register builtin function's name and it's address here in this table below
|
||||
// this table must end with {nullptr, nullptr}
|
||||
struct nasal_builtin_table {
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "natives/io_lib.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace nasal {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "natives/json_lib.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
@ -170,7 +171,7 @@ void json::next() {
|
|||
} else if (text[ptr]!=' ' && text[ptr]!='\t' && text[ptr]!='\r') {
|
||||
error_info() += "json::parse: line " + std::to_string(line);
|
||||
error_info() += ": invalid character `0x";
|
||||
error_info() += char_to_hex(text[ptr]);
|
||||
error_info() += util::char_to_hex(text[ptr]);
|
||||
error_info() += "`\n";
|
||||
}
|
||||
++ptr;
|
||||
|
@ -253,7 +254,7 @@ void json::vector_member(nas_vec& vec, gc* ngc) {
|
|||
vec.elems.push_back(ngc->newstr(this_token.content));
|
||||
next();
|
||||
} else if (this_token.type==json_token_type::tok_num) {
|
||||
vec.elems.push_back(var::num(str_to_num(this_token.content.c_str())));
|
||||
vec.elems.push_back(var::num(util::str_to_num(this_token.content.c_str())));
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +293,7 @@ void json::hash_member(nas_hash& hash, gc* ngc) {
|
|||
hash.elems.insert({name, ngc->newstr(this_token.content)});
|
||||
next();
|
||||
} else if (this_token.type==json_token_type::tok_num) {
|
||||
hash.elems.insert({name, var::num(str_to_num(this_token.content.c_str()))});
|
||||
hash.elems.insert({name, var::num(util::str_to_num(this_token.content.c_str()))});
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
namespace nasal {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "nasal.h"
|
||||
#include "nasal_gc.h"
|
||||
#include "natives/nasal_builtin.h"
|
||||
#include "natives/builtin.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
|
|
|
@ -47,12 +47,12 @@ bool repl::check_need_more_input() {
|
|||
i64 in_brace = 0;
|
||||
for(const auto& t : nasal_lexer->result()) {
|
||||
switch(t.type) {
|
||||
case tok::lcurve: ++in_curve; break;
|
||||
case tok::rcurve: --in_curve; break;
|
||||
case tok::lbracket: ++in_bracket; break;
|
||||
case tok::rbracket: --in_bracket; break;
|
||||
case tok::lbrace: ++in_brace; break;
|
||||
case tok::rbrace: --in_brace; break;
|
||||
case tok::tk_lcurve: ++in_curve; break;
|
||||
case tok::tk_rcurve: --in_curve; break;
|
||||
case tok::tk_lbracket: ++in_bracket; break;
|
||||
case tok::tk_rbracket: --in_bracket; break;
|
||||
case tok::tk_lbrace: ++in_brace; break;
|
||||
case tok::tk_rbrace: --in_brace; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4996)
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/fs.h"
|
||||
#include "nasal.h"
|
||||
|
||||
namespace nasal::fs {
|
||||
|
||||
path& path::operator/(const path& another) {
|
||||
this->file_system_path += util::is_windows()? "\\":"/";
|
||||
this->file_system_path += another.file_system_path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool exists(const path& file_path) {
|
||||
#ifdef _MSC_VER
|
||||
#define F_OK 0 // fuck msc
|
||||
#endif
|
||||
return access(file_path.c_str(), F_OK)==0;
|
||||
}
|
||||
|
||||
bool is_regular(const path& file_path) {
|
||||
#ifdef _MSC_VER
|
||||
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
||||
#endif
|
||||
struct stat buffer;
|
||||
if (stat(file_path.c_str(), &buffer)!=0) {
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(buffer.st_mode);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace nasal::fs {
|
||||
|
||||
class path {
|
||||
private:
|
||||
std::string file_system_path;
|
||||
|
||||
public:
|
||||
path(const path&) = default;
|
||||
path(const std::string& file_path): file_system_path(file_path) {}
|
||||
path& operator/(const path&);
|
||||
const char* c_str() const {
|
||||
return file_system_path.c_str();
|
||||
}
|
||||
const std::string& str() const {
|
||||
return file_system_path;
|
||||
}
|
||||
};
|
||||
|
||||
bool exists(const path&);
|
||||
bool is_regular(const path&);
|
||||
|
||||
}
|
|
@ -1,17 +1,8 @@
|
|||
#include "nasal.h"
|
||||
#include "util/util.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <cmath>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4996)
|
||||
#endif
|
||||
|
||||
namespace nasal {
|
||||
namespace nasal::util {
|
||||
|
||||
bool is_windows() {
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
@ -105,7 +96,7 @@ const char* get_platform() {
|
|||
} else if (is_macos()) {
|
||||
return "macOS";
|
||||
}
|
||||
return "unknown platform";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* get_arch() {
|
||||
|
@ -126,7 +117,57 @@ const char* get_arch() {
|
|||
} else if (is_superh()) {
|
||||
return "superh";
|
||||
}
|
||||
return "unknown arch";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
u32 utf8_hdchk(const char head) {
|
||||
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||
const auto c = static_cast<u8>(head);
|
||||
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||
return 1;
|
||||
}
|
||||
if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2
|
||||
return 2;
|
||||
}
|
||||
if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string char_to_hex(const char c) {
|
||||
const char hextbl[] = "0123456789abcdef";
|
||||
return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]};
|
||||
}
|
||||
|
||||
std::string rawstr(const std::string& str, const usize maxlen) {
|
||||
std::string ret("");
|
||||
for(auto i : str) {
|
||||
// windows doesn't output unicode normally, so we output the hex
|
||||
if (util::is_windows() && i<=0) {
|
||||
ret += "\\x" + char_to_hex(i);
|
||||
continue;
|
||||
}
|
||||
switch(i) {
|
||||
case '\0': ret += "\\0"; break;
|
||||
case '\a': ret += "\\a"; break;
|
||||
case '\b': ret += "\\b"; break;
|
||||
case '\t': ret += "\\t"; break;
|
||||
case '\n': ret += "\\n"; break;
|
||||
case '\v': ret += "\\v"; break;
|
||||
case '\f': ret += "\\f"; break;
|
||||
case '\r': ret += "\\r"; break;
|
||||
case '\033':ret += "\\e"; break;
|
||||
case '\"': ret += "\\\""; break;
|
||||
case '\'': ret += "\\\'"; break;
|
||||
case '\\': ret += "\\\\"; break;
|
||||
default: ret += i; break;
|
||||
}
|
||||
}
|
||||
if (maxlen && ret.length()>maxlen) {
|
||||
ret = ret.substr(0, maxlen)+"...";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
f64 hex_to_f64(const char* str) {
|
||||
|
@ -227,82 +268,4 @@ f64 str_to_num(const char* str) {
|
|||
return negative? -res:res;
|
||||
}
|
||||
|
||||
i32 utf8_hdchk(const char head) {
|
||||
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
|
||||
const auto c = static_cast<u8>(head);
|
||||
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
|
||||
return 1;
|
||||
}
|
||||
if ((c>>4)==0x0e) { // 1110 xxxx (10xx xxxx)^2
|
||||
return 2;
|
||||
}
|
||||
if ((c>>3)==0x1e) { // 1111 0xxx (10xx xxxx)^3
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string char_to_hex(const char c) {
|
||||
const char hextbl[] = "0123456789abcdef";
|
||||
return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]};
|
||||
}
|
||||
|
||||
std::string rawstr(const std::string& str, const usize maxlen) {
|
||||
std::string ret("");
|
||||
for(auto i : str) {
|
||||
// windows doesn't output unicode normally, so we output the hex
|
||||
if (is_windows() && i<=0) {
|
||||
ret += "\\x" + char_to_hex(i);
|
||||
continue;
|
||||
}
|
||||
switch(i) {
|
||||
case '\0': ret += "\\0"; break;
|
||||
case '\a': ret += "\\a"; break;
|
||||
case '\b': ret += "\\b"; break;
|
||||
case '\t': ret += "\\t"; break;
|
||||
case '\n': ret += "\\n"; break;
|
||||
case '\v': ret += "\\v"; break;
|
||||
case '\f': ret += "\\f"; break;
|
||||
case '\r': ret += "\\r"; break;
|
||||
case '\033':ret += "\\e"; break;
|
||||
case '\"': ret += "\\\""; break;
|
||||
case '\'': ret += "\\\'"; break;
|
||||
case '\\': ret += "\\\\"; break;
|
||||
default: ret += i; break;
|
||||
}
|
||||
}
|
||||
if (maxlen && ret.length()>maxlen) {
|
||||
ret = ret.substr(0, maxlen)+"...";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace fs {
|
||||
|
||||
path& path::operator/(const path& another) {
|
||||
this->file_system_path += is_windows()? "\\":"/";
|
||||
this->file_system_path += another.file_system_path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool exists(const path& file_path) {
|
||||
#ifdef _MSC_VER
|
||||
#define F_OK 0 // fuck msc
|
||||
#endif
|
||||
return access(file_path.c_str(), F_OK)==0;
|
||||
}
|
||||
|
||||
bool is_regular(const path& file_path) {
|
||||
#ifdef _MSC_VER
|
||||
#define S_ISREG(m) (((m)&0xF000)==0x8000)
|
||||
#endif
|
||||
struct stat buffer;
|
||||
if (stat(file_path.c_str(), &buffer)!=0) {
|
||||
return false;
|
||||
}
|
||||
return S_ISREG(buffer.st_mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
|
||||
#include "nasal.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
namespace nasal::util {
|
||||
|
||||
bool is_windows();
|
||||
bool is_linux();
|
||||
bool is_macos();
|
||||
bool is_x86();
|
||||
bool is_amd64();
|
||||
bool is_x86_64();
|
||||
bool is_arm();
|
||||
bool is_aarch64();
|
||||
bool is_ia64();
|
||||
bool is_powerpc();
|
||||
bool is_superh();
|
||||
const char* get_platform();
|
||||
const char* get_arch();
|
||||
|
||||
u32 utf8_hdchk(const char);
|
||||
|
||||
std::string char_to_hex(const char);
|
||||
std::string rawstr(const std::string&, const usize maxlen = 0);
|
||||
|
||||
f64 hex_to_f64(const char*);
|
||||
f64 oct_to_f64(const char*);
|
||||
// we have the same reason not using atof here
|
||||
// just as andy's interpreter does.
|
||||
// it is not platform independent, and may have strange output.
|
||||
// so we write a new function here to convert str to number manually.
|
||||
// but this also makes 0.1+0.2==0.3,
|
||||
// not another result that you may get in other languages.
|
||||
f64 dec_to_f64(const char*);
|
||||
|
||||
f64 str_to_num(const char*);
|
||||
|
||||
class windows_code_page_manager {
|
||||
private:
|
||||
u32 code_page;
|
||||
|
||||
public:
|
||||
windows_code_page_manager() {
|
||||
#ifdef _WIN32
|
||||
code_page = GetConsoleOutputCP();
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_utf8_output() {
|
||||
#ifdef _WIN32
|
||||
// store previous code page
|
||||
code_page = GetConsoleOutputCP();
|
||||
// allow 65001 code page
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
#endif
|
||||
}
|
||||
|
||||
void restore_code_page() {
|
||||
#ifdef _WIN32
|
||||
// restore previous code page
|
||||
SetConsoleOutputCP(code_page);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -7,7 +7,29 @@ var argv = func() {
|
|||
return globals.arg;
|
||||
}
|
||||
|
||||
var _gc_extend = func(type) {
|
||||
return __gcextd;
|
||||
}
|
||||
|
||||
var gc = {
|
||||
extend: func(type) {return __gcextd;},
|
||||
extend: func(type, times = 1) {
|
||||
if (times<=0) {
|
||||
return nil;
|
||||
}
|
||||
if (times>16) {
|
||||
times = 16;
|
||||
}
|
||||
|
||||
for(var i = 0; i<times; i+=1) {
|
||||
_gc_extend(type);
|
||||
}
|
||||
return nil;
|
||||
},
|
||||
info: func() {return __gcinfo;}
|
||||
};
|
||||
|
||||
var windows = {
|
||||
set_utf8_output: func() {
|
||||
return __set_utf8_output;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,7 +1,24 @@
|
|||
use std.padding;
|
||||
use std.process_bar;
|
||||
use std.os;
|
||||
use std.unix;
|
||||
use std.runtime;
|
||||
|
||||
var table_character_set = [
|
||||
"─", "━", "│", "┃", "╌", "╍", "╎", "╏", "┄", "┅",
|
||||
"┆", "┇", "┈", "┉", "┊", "┋", "┌", "┍", "┎", "┏",
|
||||
"┐", "┑", "┒", "┓", "└", "┕", "┖", "┗", "┘", "┙",
|
||||
"┚", "┛", "├", "┝", "┞", "┟", "┠", "┡", "┢", "┣",
|
||||
"┤", "┥", "┦", "┧", "┨", "┩", "┪", "┫", "┬", "┭",
|
||||
"┮", "┯", "┰", "┱", "┲", "┳", "┴", "┵", "┶", "┷",
|
||||
"┸", "┹", "┺", "┻", "┼", "┽", "┾", "┿", "╀", "╁",
|
||||
"╂", "╃", "╄", "╅", "╆", "╇", "╈", "╉", "╊", "╋",
|
||||
"╪", "╫", "╬", "═", "║", "╒", "╓", "╔", "╕", "╖",
|
||||
"╗", "╘", "╙", "╚", "╛", "╜", "╝", "╞", "╟", "╠",
|
||||
"╡", "╢", "╣", "╤", "╥", "╦", "╧", "╨", "╬", "╩",
|
||||
"┷", "┳", "⊥", "﹃", "﹄", "╮", "╭", "╯", "╰", "╳"
|
||||
];
|
||||
|
||||
var selection_box = ["○", "◉", "☐", "▣"];
|
||||
|
||||
var char_ttf=[
|
||||
[" "," "," "," "," "," "],
|
||||
|
@ -196,9 +213,7 @@ var ansi_escape_sequence = func() {
|
|||
}
|
||||
|
||||
# enable unicode
|
||||
if (os.platform()=="windows") {
|
||||
system("chcp 65001");
|
||||
}
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
trans_ttf("just for test");
|
||||
trans_ttf(" ValKmjolnir ");
|
||||
|
|
|
@ -27,10 +27,8 @@ use std.math;
|
|||
|
||||
func() {
|
||||
# allocate more spaces
|
||||
for(var i = 0; i<10; i+=1) {
|
||||
runtime.gc.extend("str");
|
||||
runtime.gc.extend("vec");
|
||||
}
|
||||
runtime.gc.extend("str", 8);
|
||||
runtime.gc.extend("vec", 8);
|
||||
}();
|
||||
|
||||
var (max,min,sqrt,sin,cos,abs)=(
|
||||
|
|
|
@ -4,9 +4,10 @@ use std.coroutine;
|
|||
use std.process_bar;
|
||||
use std.padding;
|
||||
use std.os;
|
||||
use std.runtime;
|
||||
|
||||
if (os.platform()=="windows") {
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
system("color");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std.os;
|
||||
use std.runtime;
|
||||
use std.io;
|
||||
use std.unix;
|
||||
|
||||
|
@ -35,7 +35,7 @@ var prt = func(s,path) {
|
|||
}
|
||||
|
||||
# enable unicode
|
||||
if (os.platform()=="windows")
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
println("\e[33m[",unix.getcwd(),"]\e[36m>\e[0m");
|
||||
prt([""],".");
|
|
@ -1,7 +1,7 @@
|
|||
use test.md5_self;
|
||||
use std.process_bar;
|
||||
use std.file;
|
||||
use std.os;
|
||||
use std.runtime;
|
||||
use std.io;
|
||||
use std.math;
|
||||
|
||||
|
@ -47,6 +47,12 @@ var compare = func() {
|
|||
};
|
||||
}();
|
||||
|
||||
var add_all_cpp_files = func(vec, path) {
|
||||
foreach(var p; file.find_all_files_with_extension(path,"cpp","h")) {
|
||||
append(vec, path~"/"~p);
|
||||
}
|
||||
}
|
||||
|
||||
var filechecksum = func() {
|
||||
var files = [];
|
||||
foreach(var p; file.find_all_files_with_extension("./test","nas")) {
|
||||
|
@ -61,9 +67,11 @@ var filechecksum = func() {
|
|||
foreach(var p; file.find_all_files_with_extension(".","md")) {
|
||||
append(files, "./"~p);
|
||||
}
|
||||
foreach(var p; file.find_all_files_with_extension("./src","cpp","h")) {
|
||||
append(files, "./src/"~p);
|
||||
}
|
||||
add_all_cpp_files(files, "./src");
|
||||
add_all_cpp_files(files, "./src/cli");
|
||||
add_all_cpp_files(files, "./src/natives");
|
||||
add_all_cpp_files(files, "./src/repl");
|
||||
add_all_cpp_files(files, "./src/util");
|
||||
foreach(var p; file.find_all_files_with_extension("./doc","md")) {
|
||||
append(files, "./doc/"~p);
|
||||
}
|
||||
|
@ -101,8 +109,6 @@ var randomchecksum = func() {
|
|||
}
|
||||
}
|
||||
|
||||
if (os.platform()=="windows") {
|
||||
system("chcp 65001");
|
||||
}
|
||||
runtime.windows.set_utf8_output();
|
||||
filechecksum();
|
||||
randomchecksum();
|
|
@ -11,7 +11,7 @@ var is_windows_platform=os.platform()=="windows";
|
|||
var is_macos_platform=os.platform()=="macOS";
|
||||
|
||||
if (is_windows_platform) {
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
}
|
||||
|
||||
var cpu_stat = func() {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std.os;
|
||||
use std.runtime;
|
||||
|
||||
var code=[
|
||||
[1,1,1,1,1,1,1,0,1,0,0,1,1,0,1,0,1,0,1,1,0,0,1,1,1,1,1,1,1],
|
||||
[1,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,1,1,0,1,0,0,0,0,0,1],
|
||||
|
@ -32,8 +33,7 @@ var code=[
|
|||
];
|
||||
|
||||
# enable unicode
|
||||
if (os.platform()=="windows")
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
var texture=[" ","██"];
|
||||
for(var i=0;i<size(code);i+=1) {
|
||||
for(var j=0;j<size(code[i]);j+=1)
|
||||
|
|
|
@ -2,7 +2,6 @@ use module.libkey;
|
|||
use std.list;
|
||||
use std.runtime;
|
||||
use std.coroutine;
|
||||
use std.os;
|
||||
use std.unix;
|
||||
|
||||
var game = func(x,y) {
|
||||
|
@ -130,8 +129,7 @@ var co=coroutine.create(func() {
|
|||
var main = func(argv) {
|
||||
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
||||
# enable unicode
|
||||
if (os.platform()=="windows")
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
print("\ec");
|
||||
|
||||
var g=game(15,10);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use module.libkey;
|
||||
use std.runtime;
|
||||
use std.os;
|
||||
use std.unix;
|
||||
|
||||
var color=[
|
||||
|
@ -277,9 +276,9 @@ var mapgen = func(mapx,mapy) {
|
|||
var main = func(argv) {
|
||||
var should_skip=(size(argv)!=0 and argv[0]=="--skip");
|
||||
var init_counter=should_skip?5:30;
|
||||
# windows use chcp 65001 to output unicode
|
||||
if (os.platform()=="windows")
|
||||
system("chcp 65001");
|
||||
|
||||
# windows use 65001 to output unicode
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
print(
|
||||
"\ec\e[1:1H",
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
use std.runtime;
|
||||
|
||||
# do nothing if platform is not windows
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
var unicode测试 = func() {
|
||||
var 输出=print;
|
||||
var 测试成功=[
|
||||
"unicode: utf-8支持测试成功",
|
||||
"目前仅支持utf-8以及ascii格式文件",
|
||||
"注意: windows系统请开启chcp 65001代码页"
|
||||
"unicode: utf-8 支持测试成功",
|
||||
"目前仅支持 utf-8 以及 ascii 格式文件",
|
||||
"注意: windows 系统请开启 chcp 65001 代码页"
|
||||
];
|
||||
foreach(var 内容;测试成功)
|
||||
foreach(var 内容; 测试成功)
|
||||
输出(内容~"\n");
|
||||
}
|
||||
|
||||
|
@ -41,10 +46,10 @@ var emoji测试 = func() {
|
|||
🍾:🍾,
|
||||
🐘:🐘
|
||||
};
|
||||
foreach(var 📄;📁)
|
||||
💻(📄,🎤);
|
||||
foreach(var 📄;keys(🗄️))
|
||||
💻(📄,🗄️[📄],🎤);
|
||||
foreach(var 📄; 📁)
|
||||
💻(📄, 🎤);
|
||||
foreach(var 📄; keys(🗄️))
|
||||
💻(📄, 🗄️[📄], 🎤);
|
||||
}
|
||||
|
||||
var dotsgen = func() {
|
||||
|
|
|
@ -4,16 +4,16 @@ use std.io;
|
|||
use std.unix;
|
||||
|
||||
var os_time = func() {
|
||||
return "[\e[33;1m"~os.time()~"\e[0m] ";
|
||||
return "\e[33;1m["~os.time()~"]\e[0m ";
|
||||
}
|
||||
var err_hd = func() {
|
||||
return "[\e[91;1merror\e[0m] ";
|
||||
return "\e[91;1m[error]\e[0m ";
|
||||
}
|
||||
var info_hd = func() {
|
||||
return "[\e[96;1minfo\e[0m] ";
|
||||
return "\e[96;1m[info]\e[0m ";
|
||||
}
|
||||
var modified_hd = func() {
|
||||
return "[\e[92;1mmodified\e[0m] ";
|
||||
return "\e[92;1m[modified]\e[0m ";
|
||||
}
|
||||
var usage = func() {
|
||||
println(os_time(),info_hd(),"\e[1musage: nasal watchdog.nas <filename> [\"argv\"]\e[0m");
|
||||
|
@ -41,7 +41,7 @@ if (size(argv)==2) {
|
|||
var modified_time = io.fstat(filename).st_mtime;
|
||||
println(os_time(),info_hd(),"\e[1mwatching ",filename," ..\e[0m");
|
||||
while(1) {
|
||||
unix.sleep(1);
|
||||
unix.sleep(5);
|
||||
if (!io.exists(filename)) {
|
||||
println(os_time(),err_hd(),"\e[1mfile <",filename,"> does not exist\e[0m");
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
use std.runtime;
|
||||
|
||||
runtime.windows.set_utf8_output();
|
||||
|
||||
var road_enum = {
|
||||
null: 0,
|
||||
narrow: 1,
|
||||
wide: 2
|
||||
};
|
||||
|
||||
var block = {
|
||||
"┌": [road_enum.null, road_enum.narrow, road_enum.narrow, road_enum.null],
|
||||
"└": [road_enum.narrow, road_enum.narrow, road_enum.null, road_enum.null],
|
||||
"┐": [road_enum.null, road_enum.null, road_enum.narrow, road_enum.narrow],
|
||||
"┘": [road_enum.narrow, road_enum.null, road_enum.null, road_enum.narrow],
|
||||
"╪": [road_enum.narrow, road_enum.wide, road_enum.narrow, road_enum.wide],
|
||||
"│": [road_enum.narrow, road_enum.null, road_enum.narrow, road_enum.null],
|
||||
"─": [road_enum.null, road_enum.narrow, road_enum.null, road_enum.narrow],
|
||||
"┼": [road_enum.narrow, road_enum.narrow, road_enum.narrow, road_enum.narrow],
|
||||
"╫": [road_enum.wide, road_enum.narrow, road_enum.wide, road_enum.narrow],
|
||||
"╬": [road_enum.wide, road_enum.wide, road_enum.wide, road_enum.wide],
|
||||
"═": [road_enum.null, road_enum.wide, road_enum.null, road_enum.wide],
|
||||
"║": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.null],
|
||||
# "╒": [road_enum.null, road_enum.wide, road_enum.narrow, road_enum.null],
|
||||
# "╓": [road_enum.null, road_enum.narrow, road_enum.wide, road_enum.null],
|
||||
"╔": [road_enum.null, road_enum.wide, road_enum.wide, road_enum.null],
|
||||
# "╕": [road_enum.null, road_enum.null, road_enum.narrow, road_enum.wide],
|
||||
# "╖": [road_enum.null, road_enum.null, road_enum.wide, road_enum.narrow],
|
||||
"╗": [road_enum.null, road_enum.null, road_enum.wide, road_enum.wide],
|
||||
# "╘": [road_enum.narrow, road_enum.wide, road_enum.null, road_enum.null],
|
||||
# "╙": [road_enum.wide, road_enum.narrow, road_enum.null, road_enum.null],
|
||||
"╚": [road_enum.wide, road_enum.wide, road_enum.null, road_enum.null],
|
||||
# "╛": [road_enum.narrow, road_enum.null, road_enum.null, road_enum.wide],
|
||||
# "╜": [road_enum.wide, road_enum.null, road_enum.null, road_enum.narrow],
|
||||
"╝": [road_enum.wide, road_enum.null, road_enum.null, road_enum.wide],
|
||||
"╞": [road_enum.narrow, road_enum.wide, road_enum.narrow, road_enum.null],
|
||||
"╟": [road_enum.wide, road_enum.narrow, road_enum.wide, road_enum.null],
|
||||
"╠": [road_enum.wide, road_enum.wide, road_enum.wide, road_enum.null],
|
||||
"╡": [road_enum.narrow, road_enum.null, road_enum.narrow, road_enum.wide],
|
||||
"╢": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.narrow],
|
||||
"╣": [road_enum.wide, road_enum.null, road_enum.wide, road_enum.wide],
|
||||
"╤": [road_enum.null, road_enum.wide, road_enum.narrow, road_enum.wide],
|
||||
"╥": [road_enum.null, road_enum.narrow, road_enum.wide, road_enum.narrow],
|
||||
"╦": [road_enum.null, road_enum.wide, road_enum.wide, road_enum.wide],
|
||||
"╧": [road_enum.narrow, road_enum.wide, road_enum.null, road_enum.wide],
|
||||
"╨": [road_enum.wide, road_enum.narrow, road_enum.null, road_enum.narrow],
|
||||
"╩": [road_enum.wide, road_enum.wide, road_enum.null, road_enum.wide],
|
||||
" ": [road_enum.null, road_enum.null, road_enum.null, road_enum.null]
|
||||
};
|
||||
|
||||
var choice = func(above_block_char,
|
||||
left_block_char,
|
||||
flag_no_road_at_right,
|
||||
flag_no_road_at_bottom) {
|
||||
var above_block = block[above_block_char];
|
||||
var left_block = block[left_block_char];
|
||||
var block_char_set = keys(block);
|
||||
|
||||
var possible = [];
|
||||
foreach(var bcs; block_char_set) {
|
||||
var this_block = block[bcs];
|
||||
if (this_block[0] == above_block[2] and
|
||||
this_block[3] == left_block[1]) {
|
||||
if (flag_no_road_at_right and this_block[1]!=road_enum.null) {
|
||||
continue;
|
||||
}
|
||||
if (flag_no_road_at_bottom and this_block[2]!=road_enum.null) {
|
||||
continue;
|
||||
}
|
||||
append(possible, bcs);
|
||||
}
|
||||
}
|
||||
if (!size(possible)) {
|
||||
return " ";
|
||||
}
|
||||
|
||||
func() {
|
||||
if (vecindex(possible, " ")!=nil) {
|
||||
for(var i = 0; i < 64; i+= 1) {
|
||||
append(possible, " ");
|
||||
}
|
||||
}
|
||||
}();
|
||||
return possible[rand()*size(possible)];
|
||||
}
|
||||
|
||||
var print_whole_line = func(this_line) {
|
||||
var res = "";
|
||||
foreach(var i; this_line) {
|
||||
res ~= i;
|
||||
}
|
||||
println(res);
|
||||
}
|
||||
|
||||
srand();
|
||||
var last_line = [];
|
||||
for(var i = 0; i<100; i+=1) {
|
||||
append(last_line, " ");
|
||||
}
|
||||
|
||||
for(var iteration_times = 0; iteration_times < 25; iteration_times += 1) {
|
||||
var this_line = [];
|
||||
var left_block = " ";
|
||||
for(var i = 0; i < 100; i += 1) {
|
||||
var this_block = choice(
|
||||
last_line[i],
|
||||
left_block,
|
||||
i==99,
|
||||
iteration_times==24
|
||||
);
|
||||
left_block = this_block;
|
||||
append(this_line, this_block);
|
||||
}
|
||||
print_whole_line(this_line);
|
||||
last_line = this_line;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# wave collapse function 2022/4/10
|
||||
# by ValKmjolnir
|
||||
use std.os;
|
||||
use std.runtime;
|
||||
|
||||
srand();
|
||||
var table=[
|
||||
|
@ -96,8 +96,7 @@ var map = func() {
|
|||
}();
|
||||
|
||||
# enable unicode
|
||||
if (os.platform()=="windows")
|
||||
system("chcp 65001");
|
||||
runtime.windows.set_utf8_output();
|
||||
map.new(90);
|
||||
|
||||
for(var iter=0;iter<40;iter+=1) {
|
||||
|
|
Loading…
Reference in New Issue