├── .clang-format
├── .gitattributes
├── .github
└── workflows
│ ├── build-release.yml
│ ├── build.yml
│ ├── build_with_asan.yml
│ ├── build_with_cov.yml
│ └── cppcheck.yml
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── benchmark
├── CMakeLists.txt
├── benchmark_common.cpp
├── benchmark_cpp.cpp
├── benchmark_fakelua.cpp
├── benchmark_lua.cpp
├── lua
│ └── bench_algo
│ │ └── fibonacci.lua
└── main.cpp
├── cmake
└── CPM.cmake
├── cmd
├── CMakeLists.txt
└── main.cpp
├── include
└── fakelua.h
├── src
├── CMakeLists.txt
├── README.md
├── compile
│ ├── README.md
│ ├── bison
│ │ ├── build.sh
│ │ ├── location.hh
│ │ ├── parser.cpp
│ │ ├── parser.h
│ │ └── parser.y
│ ├── compile_common.h
│ ├── compiler.cpp
│ ├── compiler.h
│ ├── flex
│ │ ├── build.sh
│ │ ├── scanner.cpp
│ │ └── scanner.l
│ ├── myflexer.cpp
│ ├── myflexer.h
│ ├── syntax_tree.cpp
│ └── syntax_tree.h
├── fakelua
│ └── fakelua.cpp
├── jit
│ ├── gcc_jit.cpp
│ ├── gcc_jit.h
│ ├── gcc_jit_handle.cpp
│ ├── gcc_jit_handle.h
│ ├── preprocessor.cpp
│ ├── preprocessor.h
│ ├── vm.cpp
│ ├── vm.h
│ └── vm_function.h
├── platform
│ └── FlexLexer.h
├── state
│ ├── state.cpp
│ ├── state.h
│ ├── var_pool.cpp
│ ├── var_pool.h
│ ├── var_string_heap.cpp
│ ├── var_string_heap.h
│ ├── var_table_heap.cpp
│ └── var_table_heap.h
├── util
│ ├── call_helper.h
│ ├── common.h
│ ├── const_define.h
│ ├── debug.cpp
│ ├── debug.h
│ ├── exception.cpp
│ ├── exception.h
│ ├── file_util.cpp
│ ├── file_util.h
│ ├── hash_func.h
│ ├── logging.cpp
│ ├── logging.h
│ ├── macro.h
│ ├── string_util.cpp
│ └── string_util.h
└── var
│ ├── var.cpp
│ ├── var.h
│ ├── var_string.cpp
│ ├── var_string.h
│ ├── var_table.cpp
│ ├── var_table.h
│ └── var_type.h
└── test
├── CMakeLists.txt
├── lua
├── algo
│ └── fibonacci.lua
├── exception
│ ├── test_binop_plus_error.lua
│ ├── test_break_error.lua
│ ├── test_col_func_not_find_error.lua
│ ├── test_col_func_param_error.lua
│ ├── test_col_func_table_error.lua
│ ├── test_col_func_type_error.lua
│ ├── test_compile_fail.lua
│ ├── test_const_binop_bitand_error.lua
│ ├── test_const_binop_bitor_error.lua
│ ├── test_const_binop_double_slash_error.lua
│ ├── test_const_binop_left_shift_error.lua
│ ├── test_const_binop_less_equal_error.lua
│ ├── test_const_binop_less_error.lua
│ ├── test_const_binop_minus_error.lua
│ ├── test_const_binop_mod_error.lua
│ ├── test_const_binop_more_equal_error.lua
│ ├── test_const_binop_more_error.lua
│ ├── test_const_binop_plus_error.lua
│ ├── test_const_binop_pow_error.lua
│ ├── test_const_binop_right_shift_error.lua
│ ├── test_const_binop_slash_error.lua
│ ├── test_const_binop_star_error.lua
│ ├── test_const_binop_xor_error.lua
│ ├── test_const_define_duplicate.lua
│ ├── test_const_define_func_param_duplicate.lua
│ ├── test_const_define_no_match.lua
│ ├── test_const_define_no_value.lua
│ ├── test_const_define_variadic.lua
│ ├── test_const_func_call_error.lua
│ ├── test_const_unop_bitnot_error.lua
│ ├── test_const_unop_len_error.lua
│ ├── test_for_in_exp_error.lua
│ ├── test_for_in_explist_error.lua
│ ├── test_for_in_func_args_error.lua
│ ├── test_for_in_func_error.lua
│ ├── test_for_in_namelist_error.lua
│ ├── test_for_in_pairs_error.lua
│ ├── test_for_in_prefix_error.lua
│ ├── test_for_in_prefix_func_error.lua
│ ├── test_function_call_exception.lua
│ ├── test_function_param_duplicate.lua
│ ├── test_function_param_local_duplicate.lua
│ ├── test_global_duplicate_lvalue_error.lua
│ ├── test_label_exception.lua
│ ├── test_local_define_duplicate.lua
│ ├── test_no_define_lvalue_error.lua
│ ├── test_return_type_error.lua
│ ├── test_stmt_support_error.lua
│ ├── test_table_get_error.lua
│ ├── test_table_loop_error.lua
│ ├── test_table_set_error.lua
│ ├── test_unop_minus_error.lua
│ └── test_variadic_function_call_exception.lua
├── jit
│ ├── test_assign.lua
│ ├── test_assign_not_match.lua
│ ├── test_assign_simple_var.lua
│ ├── test_assign_table_var.lua
│ ├── test_assign_variadic.lua
│ ├── test_assign_variadic_no_match.lua
│ ├── test_binop_and.lua
│ ├── test_binop_and_bool.lua
│ ├── test_binop_and_or.lua
│ ├── test_binop_bitand.lua
│ ├── test_binop_bitor.lua
│ ├── test_binop_concat.lua
│ ├── test_binop_double_slash.lua
│ ├── test_binop_equal.lua
│ ├── test_binop_left_shift.lua
│ ├── test_binop_less.lua
│ ├── test_binop_less_equal.lua
│ ├── test_binop_minus.lua
│ ├── test_binop_mod.lua
│ ├── test_binop_more.lua
│ ├── test_binop_more_equal.lua
│ ├── test_binop_not_equal.lua
│ ├── test_binop_or.lua
│ ├── test_binop_plus.lua
│ ├── test_binop_pow.lua
│ ├── test_binop_right_shift.lua
│ ├── test_binop_slash.lua
│ ├── test_binop_star.lua
│ ├── test_binop_xor.lua
│ ├── test_const_binop_and.lua
│ ├── test_const_binop_bitand.lua
│ ├── test_const_binop_bitor.lua
│ ├── test_const_binop_concat.lua
│ ├── test_const_binop_double_slash.lua
│ ├── test_const_binop_equal.lua
│ ├── test_const_binop_left_shift.lua
│ ├── test_const_binop_less.lua
│ ├── test_const_binop_less_equal.lua
│ ├── test_const_binop_minus.lua
│ ├── test_const_binop_mod.lua
│ ├── test_const_binop_more.lua
│ ├── test_const_binop_more_equal.lua
│ ├── test_const_binop_not_equal.lua
│ ├── test_const_binop_or.lua
│ ├── test_const_binop_plus.lua
│ ├── test_const_binop_pow.lua
│ ├── test_const_binop_right_shift.lua
│ ├── test_const_binop_slash.lua
│ ├── test_const_binop_star.lua
│ ├── test_const_binop_xor.lua
│ ├── test_const_define.lua
│ ├── test_const_define_simple_var.lua
│ ├── test_const_nested_table.lua
│ ├── test_const_table.lua
│ ├── test_const_table_define.lua
│ ├── test_const_unop_bitnot.lua
│ ├── test_const_unop_len.lua
│ ├── test_const_unop_minus.lua
│ ├── test_const_unop_not.lua
│ ├── test_do_block.lua
│ ├── test_empty_file.lua
│ ├── test_empty_func.lua
│ ├── test_empty_func_call.lua
│ ├── test_empty_func_no_return.lua
│ ├── test_empty_func_with_params.lua
│ ├── test_empty_local_func.lua
│ ├── test_empty_return.lua
│ ├── test_for_in.lua
│ ├── test_for_in_break.lua
│ ├── test_for_in_double.lua
│ ├── test_for_in_if_return.lua
│ ├── test_for_in_just_break.lua
│ ├── test_for_in_return.lua
│ ├── test_for_in_return_fallback.lua
│ ├── test_for_loop.lua
│ ├── test_for_loop_break.lua
│ ├── test_for_loop_default.lua
│ ├── test_for_loop_double.lua
│ ├── test_for_loop_if_return.lua
│ ├── test_for_loop_just_break.lua
│ ├── test_for_loop_return.lua
│ ├── test_global_func_call.lua
│ ├── test_if.lua
│ ├── test_if_else.lua
│ ├── test_if_elseif.lua
│ ├── test_if_elseif_normal.lua
│ ├── test_if_elseif_return.lua
│ ├── test_if_simple.lua
│ ├── test_local_define.lua
│ ├── test_local_define_with_value.lua
│ ├── test_local_func_call.lua
│ ├── test_local_func_call_string.lua
│ ├── test_local_func_call_table_construct.lua
│ ├── test_local_nested_table.lua
│ ├── test_local_table.lua
│ ├── test_local_table_with_variadic.lua
│ ├── test_local_table_with_variadic_no_end.lua
│ ├── test_local_table_with_variadic_no_end_replace.lua
│ ├── test_multi_col_name_func.lua
│ ├── test_multi_const_define.lua
│ ├── test_multi_name_func.lua
│ ├── test_multi_return.lua
│ ├── test_multi_return_call.lua
│ ├── test_multi_return_call_ex.lua
│ ├── test_multi_return_multi.lua
│ ├── test_multi_return_multi_ex.lua
│ ├── test_multi_return_sub.lua
│ ├── test_repeat.lua
│ ├── test_repeat_break.lua
│ ├── test_repeat_double.lua
│ ├── test_repeat_if_return.lua
│ ├── test_repeat_just_break.lua
│ ├── test_repeat_return.lua
│ ├── test_table_get_set.lua
│ ├── test_table_var_func_call.lua
│ ├── test_unop_bitnot.lua
│ ├── test_unop_len.lua
│ ├── test_unop_minus.lua
│ ├── test_unop_not.lua
│ ├── test_var_func_call.lua
│ ├── test_variadic_func.lua
│ ├── test_variadic_func_with_params.lua
│ ├── test_while.lua
│ ├── test_while_break.lua
│ ├── test_while_double.lua
│ ├── test_while_if_return.lua
│ ├── test_while_just_break.lua
│ └── test_while_return.lua
└── syntax
│ ├── test_assign.lua
│ ├── test_assign_simple.lua
│ ├── test_binop.lua
│ ├── test_binop_order1.lua
│ ├── test_binop_order2.lua
│ ├── test_binop_order3.lua
│ ├── test_binop_order4.lua
│ ├── test_binop_order5.lua
│ ├── test_binop_order6.lua
│ ├── test_break.lua
│ ├── test_constructor.lua
│ ├── test_continue.lua
│ ├── test_do_end.lua
│ ├── test_empty.lua
│ ├── test_for_in.lua
│ ├── test_for_num.lua
│ ├── test_function.lua
│ ├── test_function_call.lua
│ ├── test_function_call_args.lua
│ ├── test_function_exp.lua
│ ├── test_if.lua
│ ├── test_label.lua
│ ├── test_number.lua
│ ├── test_repeat.lua
│ ├── test_string.lua
│ ├── test_var.lua
│ ├── test_var_attr.lua
│ └── test_while.lua
├── main.cpp
├── test_algo.cpp
├── test_common.cpp
├── test_exception.cpp
├── test_ini.cpp
├── test_jitter.cpp
├── test_syntax_tree.cpp
└── test_var.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | # Generated from CLion C/C++ Code Style settings
2 | BasedOnStyle: LLVM
3 | AccessModifierOffset: -4
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: None
6 | AlignOperands: Align
7 | AllowAllArgumentsOnNextLine: false
8 | AllowAllConstructorInitializersOnNextLine: false
9 | AllowAllParametersOfDeclarationOnNextLine: false
10 | AllowShortBlocksOnASingleLine: false
11 | AllowShortCaseLabelsOnASingleLine: false
12 | AllowShortFunctionsOnASingleLine: false
13 | AllowShortIfStatementsOnASingleLine: Always
14 | AllowShortLambdasOnASingleLine: All
15 | AllowShortLoopsOnASingleLine: true
16 | AlwaysBreakAfterReturnType: None
17 | AlwaysBreakTemplateDeclarations: Yes
18 | BreakBeforeBraces: Custom
19 | BraceWrapping:
20 | AfterCaseLabel: false
21 | AfterClass: false
22 | AfterControlStatement: Never
23 | AfterEnum: false
24 | AfterFunction: false
25 | AfterNamespace: false
26 | AfterUnion: false
27 | BeforeCatch: false
28 | BeforeElse: false
29 | IndentBraces: false
30 | SplitEmptyFunction: false
31 | SplitEmptyRecord: true
32 | BreakBeforeBinaryOperators: None
33 | BreakBeforeTernaryOperators: true
34 | BreakConstructorInitializers: BeforeColon
35 | BreakInheritanceList: BeforeColon
36 | ColumnLimit: 140
37 | CompactNamespaces: false
38 | ContinuationIndentWidth: 8
39 | IndentCaseLabels: true
40 | IndentPPDirectives: None
41 | IndentWidth: 4
42 | KeepEmptyLinesAtTheStartOfBlocks: true
43 | MaxEmptyLinesToKeep: 2
44 | NamespaceIndentation: None
45 | ObjCSpaceAfterProperty: false
46 | ObjCSpaceBeforeProtocolList: true
47 | PointerAlignment: Right
48 | ReflowComments: false
49 | SpaceAfterCStyleCast: true
50 | SpaceAfterLogicalNot: false
51 | SpaceAfterTemplateKeyword: false
52 | SpaceBeforeAssignmentOperators: true
53 | SpaceBeforeCpp11BracedList: false
54 | SpaceBeforeCtorInitializerColon: true
55 | SpaceBeforeInheritanceColon: true
56 | SpaceBeforeParens: ControlStatements
57 | SpaceBeforeRangeBasedForLoopColon: false
58 | SpaceInEmptyParentheses: false
59 | SpacesBeforeTrailingComments: 0
60 | SpacesInAngles: false
61 | SpacesInCStyleCastParentheses: false
62 | SpacesInContainerLiterals: false
63 | SpacesInParentheses: false
64 | SpacesInSquareBrackets: false
65 | TabWidth: 4
66 | UseTab: Never
67 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
--------------------------------------------------------------------------------
/.github/workflows/build-release.yml:
--------------------------------------------------------------------------------
1 | name: BuildRelease
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-24.04
12 |
13 | steps:
14 | - uses: actions/checkout@v1
15 |
16 | - name: Setup GCC
17 | uses: pkgxdev/setup@v1
18 | with:
19 | +: gcc@13
20 |
21 | - name: Setup Lua
22 | run: |
23 | wget https://www.lua.org/ftp/lua-5.4.7.tar.gz
24 | tar -xf lua-5.4.7.tar.gz
25 | cd lua-5.4.7
26 | make linux
27 | sudo make install
28 | cd ..
29 |
30 | - name: Prepare
31 | run: |
32 | sudo apt-get -y install libgccjit-13-dev
33 | dpkg -L libgccjit-13-dev
34 | sudo mv /usr/lib/gcc/x86_64-linux-gnu/13/include/libgccjit* /usr/include/
35 | sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/13/libgccjit.so /usr/lib/libgccjit.so
36 |
37 | - name: Build
38 | run: |
39 | set -x
40 | rm build -rf
41 | mkdir build
42 | cd build
43 | cmake -DCMAKE_BUILD_TYPE=Release ..
44 | make -j8
45 | ctest -V
46 | ./bin/bench_mark
47 | ./bin/flua
48 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-24.04
12 |
13 | steps:
14 | - uses: actions/checkout@v1
15 |
16 | - name: Setup GCC
17 | uses: pkgxdev/setup@v1
18 | with:
19 | +: gcc@13
20 |
21 | - name: Setup Lua
22 | run: |
23 | wget https://www.lua.org/ftp/lua-5.4.7.tar.gz
24 | tar -xf lua-5.4.7.tar.gz
25 | cd lua-5.4.7
26 | make linux
27 | sudo make install
28 | cd ..
29 |
30 | - name: Prepare
31 | run: |
32 | sudo apt-get -y install libgccjit-13-dev
33 | dpkg -L libgccjit-13-dev
34 | sudo mv /usr/lib/gcc/x86_64-linux-gnu/13/include/libgccjit* /usr/include/
35 | sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/13/libgccjit.so /usr/lib/libgccjit.so
36 |
37 | - name: Build
38 | run: |
39 | set -x
40 | rm build -rf
41 | mkdir build
42 | cd build
43 | cmake ..
44 | make -j8
45 | ctest -V
46 | ./bin/bench_mark
47 | ./bin/flua
48 |
--------------------------------------------------------------------------------
/.github/workflows/build_with_asan.yml:
--------------------------------------------------------------------------------
1 | name: BuildWithASAN
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-24.04
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 |
17 | - name: Setup GCC
18 | uses: pkgxdev/setup@v1
19 | with:
20 | +: gcc@13
21 |
22 | - name: Setup Lua
23 | run: |
24 | wget https://www.lua.org/ftp/lua-5.4.7.tar.gz
25 | tar -xf lua-5.4.7.tar.gz
26 | cd lua-5.4.7
27 | make linux
28 | sudo make install
29 | cd ..
30 |
31 | - name: Prepare
32 | run: |
33 | sudo apt-get -y install libgccjit-13-dev
34 | dpkg -L libgccjit-13-dev
35 | sudo mv /usr/lib/gcc/x86_64-linux-gnu/13/include/libgccjit* /usr/include/
36 | sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/13/libgccjit.so /usr/lib/libgccjit.so
37 |
38 | - name: Build with asan
39 | run: |
40 | set -x
41 | rm build -rf
42 | mkdir build
43 | cd build
44 | export ASAN_OPTIONS=detect_leaks=0
45 | cmake -DUSE_ASAN=ON ..
46 | make -j8
47 | ctest -V
48 | ./bin/bench_mark
49 | ./bin/flua
50 |
--------------------------------------------------------------------------------
/.github/workflows/build_with_cov.yml:
--------------------------------------------------------------------------------
1 | name: BuildWithCOV
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-24.04
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 |
17 | - name: Setup GCC
18 | uses: pkgxdev/setup@v1
19 | with:
20 | +: gcc@13
21 |
22 | - name: Setup Lua
23 | run: |
24 | wget https://www.lua.org/ftp/lua-5.4.7.tar.gz
25 | tar -xf lua-5.4.7.tar.gz
26 | cd lua-5.4.7
27 | make linux
28 | sudo make install
29 | cd ..
30 |
31 | - name: Prepare
32 | run: |
33 | sudo apt-get -y install libgccjit-13-dev
34 | dpkg -L libgccjit-13-dev
35 | sudo mv /usr/lib/gcc/x86_64-linux-gnu/13/include/libgccjit* /usr/include/
36 | sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/13/libgccjit.so /usr/lib/libgccjit.so
37 | wget https://github.com/linux-test-project/lcov/releases/download/v2.0/lcov-2.0.tar.gz
38 | tar -xf lcov-2.0.tar.gz
39 | cd lcov-2.0/
40 | sudo make install
41 | yes|sudo perl -MCPAN -e 'install Capture::Tiny'
42 | sudo apt-get install libdatetime-perl -y
43 | sudo rm /usr/bin/lcov -f
44 | sudo ln -s /usr/local/bin/lcov /usr/bin/lcov
45 | lcov --version
46 | cd ..
47 |
48 | - name: Build with cov
49 | run: |
50 | set -x
51 | rm build -rf
52 | mkdir build
53 | cd build
54 | cmake -DUSE_COV=ON ..
55 | make -j8
56 | ctest -V
57 | ./bin/bench_mark
58 | ./bin/flua
59 | echo "function main() return 0 end" > test.lua
60 | ./bin/flua test.lua
61 | lcov --directory ./ --capture --output-file coverage.info --ignore-errors source --ignore-errors mismatch
62 | ls -l coverage.info
63 | lcov --list coverage.info
64 | bash <(curl -s https://codecov.io/bash) -t ${{ secrets.CODECOV }} -f coverage.info || echo "Codecov did not collect coverage reports"
65 |
66 |
--------------------------------------------------------------------------------
/.github/workflows/cppcheck.yml:
--------------------------------------------------------------------------------
1 | name: CppCheck
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-24.04
13 |
14 | steps:
15 | - uses: actions/checkout@v1
16 |
17 | - name: Setup GCC
18 | uses: pkgxdev/setup@v1
19 | with:
20 | +: gcc@13
21 |
22 | - name: Prepare
23 | run: |
24 | sudo apt-get -y install libgccjit-13-dev
25 | dpkg -L libgccjit-13-dev
26 | sudo mv /usr/lib/gcc/x86_64-linux-gnu/13/include/libgccjit* /usr/include/
27 | sudo ln -s /usr/lib/gcc/x86_64-linux-gnu/13/libgccjit.so /usr/lib/libgccjit.so
28 |
29 | - name: Build
30 | run: |
31 | set -x
32 | wget https://github.com/danmar/cppcheck/archive/refs/tags/2.12.1.tar.gz
33 | tar -xf 2.12.1.tar.gz
34 | cd cppcheck-2.12.1
35 | mkdir build
36 | cd build
37 | cmake ..
38 | make -j8
39 | sudo make install
40 | cd ..
41 | cd ..
42 | cppcheck --version
43 | FILES=`find src/ cmd/ -type f -name "*.cpp" -o -name "*.h"|grep -v parser|grep -v scanner`
44 | cppcheck --language=c++ --check-level=exhaustive --max-ctu-depth=64 -j8 $FILES 2> err.txt
45 | cat err.txt
46 | if [[ -s err.txt ]]
47 | then
48 | exit 1
49 | fi
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Compiled Object files
5 | *.slo
6 | *.lo
7 | *.o
8 | *.obj
9 |
10 | # Precompiled Headers
11 | *.gch
12 | *.pch
13 |
14 | # Compiled Dynamic libraries
15 | *.so
16 | *.dylib
17 | *.dll
18 |
19 | # Fortran module files
20 | *.mod
21 | *.smod
22 |
23 | # Compiled Static libraries
24 | *.lai
25 | *.la
26 | *.a
27 | *.lib
28 |
29 | # Executables
30 | *.exe
31 | *.out
32 | *.app
33 |
34 | .idea
35 | build
36 | cmake-build-debug
37 | cmake_install.cmake
38 | CMakeFiles
39 | CTestTestfile.cmake
40 | Makefile
41 | googletest
42 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2 |
3 | project(fakelua CXX)
4 |
5 | set(CMAKE_CXX_STANDARD 23)
6 |
7 | # add dependencies
8 | include(cmake/CPM.cmake)
9 |
10 | # place binaries and libraries according to GNU standards
11 | include(GNUInstallDirs)
12 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
13 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
14 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
15 |
16 | set(ENV{FAKELUA_HOME} "${CMAKE_CURRENT_SOURCE_DIR}/")
17 |
18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused-local-typedefs -Wno-unused-function -DNDEBUG -g3 -ggdb3 -fPIC")
19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -DNDEBUG -g3 -ggdb3 -fPIC")
20 |
21 | option(USE_ASAN "use asan" OFF)
22 | if (USE_ASAN)
23 | message("build with asan")
24 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
25 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
26 | endif ()
27 |
28 | option(USE_COV "use cov" OFF)
29 | if (USE_COV)
30 | message("build with cov")
31 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fprofile-update=atomic")
32 | endif ()
33 |
34 | IF (WIN32)
35 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
36 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
37 | ELSE ()
38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
39 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
40 | ENDIF ()
41 |
42 | find_program(CCACHE_PROGRAM ccache)
43 | if (CCACHE_PROGRAM)
44 | message("build with ccache")
45 | set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
46 | endif ()
47 |
48 | add_subdirectory(src)
49 | add_subdirectory(cmd)
50 |
51 | enable_testing()
52 | add_subdirectory(test)
53 | add_subdirectory(benchmark)
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 zhao xin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FakeLua(Work in process)
2 | [
](https://github.com/esrrhs/fakelua)
3 | [
](https://github.com/esrrhs/fakelua)
4 | [
](https://github.com/esrrhs/fakelua/actions)
5 | [](https://codecov.io/gh/esrrhs/fakelua)
6 |
7 | FakeLua is a subset of Lua that compiles code into native machine code at runtime using Just-In-Time (JIT) compilation, providing a streamlined language structure and improved performance.
8 |
9 | # Features:
10 | * Compiles with C++23
11 | * Builds on Linux and MinGW
12 | * Supports Lua 5.4 syntax
13 | * Uses Flex and Bison for lexing and parsing
14 | * Compiles to native code using GCC JIT
15 | * Supports GDB for debugging Lua source code
16 |
17 | # Differences from Lua:
18 | * No global variables, only global constants
19 | * No garbage collection (GC); uses a memory pool instead
20 | * No coroutines, threads, userdata, or metatables
21 | * Tables are exclusively hash tables, not array tables
22 | * String concatenation supports all data types
23 | * No closures, as they are slow and complex to implement
24 |
25 |
26 | # Directory structure
27 | * [include](./include) header file
28 | * [src](./src) source code
29 | * [test](./test) test code
30 | * [benchmark](./benchmark) benchmark code
31 | * [cmd](./cmd) command line tool
32 | * [cmake](./cmake) cmake toolchain
33 |
34 | # Build
35 | ### Linux
36 | * Dependent: install gcc-13 with jit, cmake, flex, bison. install Lua for test.
37 | * Build:
38 | ```shell
39 | mkdir build
40 | cd build
41 | cmake ..
42 | make
43 | ```
44 |
45 | ### Mingw
46 | * Dependent: install [MSYS2](https://www.msys2.org). install [mingw-w64-x86_64-libgccjit](https://packages.msys2.org/package/mingw-w64-x86_64-libgccjit), [mingw-w64-x86_64-lua](https://packages.msys2.org/package/mingw-w64-x86_64-lua). install CLion.
47 | * open project with CLion, set mingw toolchains. and build.
48 |
--------------------------------------------------------------------------------
/benchmark/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2 |
3 | project(benchmark)
4 |
5 | #add benchmark
6 | CPMAddPackage(
7 | NAME benchmark
8 | GITHUB_REPOSITORY google/benchmark
9 | GIT_TAG v1.9.4
10 | OPTIONS
11 | "BENCHMARK_ENABLE_TESTING Off"
12 | "BENCHMARK_ENABLE_GTEST_TESTS Off"
13 | "BENCHMARK_ENABLE_ASSEMBLY_TESTS Off"
14 | "BENCHMARK_ENABLE_EXCEPTIONS Off"
15 | "BENCHMARK_ENABLE_INSTALL Off"
16 | "BENCHMARK_ENABLE_LTO Off"
17 | "BENCHMARK_ENABLE_NO_EXCEPTIONS Off"
18 | "BENCHMARK_ENABLE_TESTING Off"
19 | "BENCHMARK_ENABLE_TESTING Off"
20 | "BENCHMARK_USE_LIBCXX Off"
21 | "BENCHMARK_USE_LIBCXXABI Off"
22 | "BENCHMARK_USE_SANITIZER Off"
23 | "BENCHMARK_USE_VALGRIND Off"
24 | "BENCHMARK_DOWNLOAD_DEPENDENCIES Off"
25 | "BENCHMARK_ENABLE_GTEST_TESTS Off"
26 | "BENCHMARK_ENABLE_EXCEPTIONS Off"
27 | "BENCHMARK_ENABLE_INSTALL Off"
28 | "BENCHMARK_ENABLE_LTO Off"
29 | "BENCHMARK_ENABLE_NO_EXCEPTIONS Off"
30 | "BENCHMARK_ENABLE_TESTING Off"
31 | "BENCHMARK_ENABLE_TESTING Off"
32 | "BENCHMARK_USE_LIBCXX Off"
33 | "BENCHMARK_USE_LIBCXXABI Off"
34 | "BENCHMARK_USE_SANITIZER Off"
35 | "BENCHMARK_USE_VALGRIND Off"
36 | "BENCHMARK_DOWNLOAD_DEPENDENCIES Off"
37 | )
38 |
39 | include_directories(${magic_enum_SOURCE_DIR}/include/magic_enum)
40 |
41 | aux_source_directory(./ BENCHMARK_SRC_LIST)
42 | include_directories(./)
43 | include_directories(../include)
44 | include_directories(../src)
45 | include_directories(../src/platform)
46 |
47 | IF (WIN32)
48 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-all-symbols")
49 | ELSE ()
50 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-E")
51 | ENDIF ()
52 |
53 | add_executable(bench_mark ${BENCHMARK_SRC_LIST})
54 |
55 | target_link_libraries(bench_mark PRIVATE fakelua benchmark gccjit lua)
56 |
57 | add_custom_command(
58 | TARGET bench_mark
59 | POST_BUILD
60 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/lua/ ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/
61 | )
62 |
--------------------------------------------------------------------------------
/benchmark/benchmark_common.cpp:
--------------------------------------------------------------------------------
1 | #include "benchmark/benchmark.h"
2 | #include "fakelua.h"
3 | #include "util/common.h"
4 |
5 | using namespace fakelua;
6 |
--------------------------------------------------------------------------------
/benchmark/benchmark_cpp.cpp:
--------------------------------------------------------------------------------
1 | #include "benchmark/benchmark.h"
2 | #include "fakelua.h"
3 | #include "util/common.h"
4 |
5 | using namespace fakelua;
6 |
7 | static int fibonacci(int n) {
8 | if (n <= 1) {
9 | return n;
10 | } else {
11 | return fibonacci(n - 1) + fibonacci(n - 2);
12 | }
13 | }
14 |
15 | static void BM_cpp_fibonacci(benchmark::State &state) {
16 | for (auto _: state) {
17 | int ret = 0;
18 | ret = fibonacci(30);
19 | if (ret != 832040) {
20 | throw std::runtime_error("C++ Fibonacci result is incorrect: " + std::to_string(ret));
21 | }
22 | }
23 | }
24 |
25 | BENCHMARK(BM_cpp_fibonacci);
26 |
--------------------------------------------------------------------------------
/benchmark/benchmark_fakelua.cpp:
--------------------------------------------------------------------------------
1 | #include "benchmark/benchmark.h"
2 | #include "fakelua.h"
3 | #include "util/common.h"
4 |
5 | using namespace fakelua;
6 |
7 | static void load_fakelua_file(fakelua_state_ptr L, const std::string &file) {
8 | try {
9 | L->compile_file(file, {.debug_mode = false});
10 | } catch (...) {
11 | L->compile_file("bin/" + file, {.debug_mode = false});
12 | }
13 | }
14 |
15 | struct FakeLuaGlobalIni {
16 | FakeLuaGlobalIni() {
17 | L = fakelua_newstate();
18 | load_fakelua_file(L, "bench_algo/fibonacci.lua");
19 | }
20 | fakelua_state_ptr L;
21 | };
22 |
23 | static FakeLuaGlobalIni fakelua_global_ini;
24 |
25 | static void BM_fakelua_fibonacci(benchmark::State &state) {
26 | for (auto _: state) {
27 | int ret = 0;
28 | fakelua_global_ini.L->call("main", std::tie(ret), 30);
29 | if (ret != 832040) {
30 | throw std::runtime_error("fakelua Fibonacci result is incorrect: " + std::to_string(ret));
31 | }
32 | }
33 | }
34 |
35 | BENCHMARK(BM_fakelua_fibonacci);
36 |
--------------------------------------------------------------------------------
/benchmark/benchmark_lua.cpp:
--------------------------------------------------------------------------------
1 | #include "benchmark/benchmark.h"
2 | #include "fakelua.h"
3 | #include "util/common.h"
4 | #include // Lua C API
5 |
6 | using namespace fakelua;
7 |
8 | static void load_lua_file(lua_State *L, const std::string &file) {
9 | if (luaL_dofile(L, file.c_str()) != LUA_OK) {
10 | luaL_dofile(L, ("bin/" + file).c_str());
11 | }
12 | }
13 |
14 | template
15 | void push_to_lua(lua_State *L, T value);
16 |
17 | template<>
18 | void push_to_lua(lua_State *L, int value) {
19 | lua_pushinteger(L, value);
20 | }
21 |
22 | template
23 | void push_args(lua_State *L, T first, Args... args) {
24 | push_to_lua(L, first);
25 | push_args(L, args...);
26 | }
27 |
28 | void push_args(lua_State *L) {
29 | }
30 |
31 | template
32 | bool call_lua_func(lua_State *L, const std::string &funcName, int &ret, Args... args) {
33 | int top = lua_gettop(L); // 获取栈顶位置
34 | lua_getglobal(L, funcName.c_str());// 获取函数
35 | DEBUG_ASSERT(lua_isfunction(L, -1));
36 |
37 | push_args(L, args...);
38 |
39 | constexpr int nargs = sizeof...(Args);
40 | int code = lua_pcall(L, nargs, 1, 0);
41 | DEBUG_ASSERT(code == LUA_OK);
42 |
43 | ret = lua_tointeger(L, -1);
44 | lua_settop(L, top);
45 | return true;
46 | }
47 |
48 | struct LuaGlobalIni {
49 | LuaGlobalIni() {
50 | L = luaL_newstate();
51 | luaL_openlibs(L);
52 | load_lua_file(L, "bench_algo/fibonacci.lua");
53 | }
54 | ~LuaGlobalIni() {
55 | if (L) {
56 | lua_close(L);
57 | }
58 | }
59 | lua_State *L = nullptr;
60 | };
61 |
62 | static LuaGlobalIni lua_global_ini;
63 |
64 | static void BM_lua_fibonacci(benchmark::State &state) {
65 | for (auto _: state) {
66 | int ret = 0;
67 | call_lua_func(lua_global_ini.L, "main", ret, 30);
68 | if (ret != 832040) {
69 | throw std::runtime_error("Lua Fibonacci result is incorrect: " + std::to_string(ret));
70 | }
71 | }
72 | }
73 |
74 | BENCHMARK(BM_lua_fibonacci);
75 |
--------------------------------------------------------------------------------
/benchmark/lua/bench_algo/fibonacci.lua:
--------------------------------------------------------------------------------
1 | local function fibonacci(n)
2 | if n <= 1 then
3 | return n
4 | else
5 | return fibonacci(n - 1) + fibonacci(n - 2)
6 | end
7 | end
8 |
9 | function main(arg)
10 | return fibonacci(arg)
11 | end
12 |
--------------------------------------------------------------------------------
/benchmark/main.cpp:
--------------------------------------------------------------------------------
1 | #include "benchmark/benchmark.h"
2 |
3 | BENCHMARK_MAIN();
4 |
--------------------------------------------------------------------------------
/cmake/CPM.cmake:
--------------------------------------------------------------------------------
1 | # SPDX-License-Identifier: MIT
2 | #
3 | # SPDX-FileCopyrightText: Copyright (c) 2019-2023 Lars Melchior and contributors
4 |
5 | set(CPM_DOWNLOAD_VERSION 0.38.7)
6 | set(CPM_HASH_SUM "83e5eb71b2bbb8b1f2ad38f1950287a057624e385c238f6087f94cdfc44af9c5")
7 |
8 | if(CPM_SOURCE_CACHE)
9 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
10 | elseif(DEFINED ENV{CPM_SOURCE_CACHE})
11 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
12 | else()
13 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
14 | endif()
15 |
16 | # Expand relative path. This is important if the provided path contains a tilde (~)
17 | get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
18 |
19 | file(DOWNLOAD
20 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
21 | ${CPM_DOWNLOAD_LOCATION} EXPECTED_HASH SHA256=${CPM_HASH_SUM}
22 | )
23 |
24 | include(${CPM_DOWNLOAD_LOCATION})
25 |
--------------------------------------------------------------------------------
/cmd/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2 |
3 | PROJECT(flua)
4 |
5 | #add gflags
6 | CPMAddPackage(
7 | NAME gflags
8 | GITHUB_REPOSITORY gflags/gflags
9 | GIT_TAG v2.2.2
10 | OPTIONS
11 | "BUILD_SHARED_LIBS OFF"
12 | "INSTALL_HEADERS ON"
13 | "INSTALL_SHARED_LIBS ON"
14 | "INSTALL_STATIC_LIBS ON"
15 | "REGISTER_INSTALL_PREFIX ON"
16 | "BUILD_TESTING OFF"
17 | )
18 |
19 | aux_source_directory(./ LUA_SRC_LIST)
20 | include_directories(./)
21 | include_directories(../include)
22 |
23 | IF (WIN32)
24 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-all-symbols")
25 | ELSE ()
26 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-E")
27 | ENDIF ()
28 |
29 | add_executable(flua ${LUA_SRC_LIST})
30 |
31 | target_link_libraries(flua PRIVATE fakelua gflags::gflags gccjit)
32 |
--------------------------------------------------------------------------------
/cmd/main.cpp:
--------------------------------------------------------------------------------
1 | #include "fakelua.h"
2 | #include "gflags/gflags.h"
3 | #include
4 |
5 | using namespace fakelua;
6 |
7 | // register some global flags
8 | DEFINE_bool(debug, false, "enable debug mode");
9 | DEFINE_string(entry, "main", "entry function name, entry must return code(int) and has no parameter");
10 | DEFINE_int32(repeat, 1, "the repeat run main function times");
11 |
12 | int main(int argc, char **argv) {
13 | gflags::SetUsageMessage("usage: ./flua --help\n"
14 | "\n");
15 | gflags::SetVersionString("0.0.1");
16 | gflags::ParseCommandLineFlags(&argc, (char ***) &argv, true);
17 |
18 | if (argc < 2) {
19 | std::cout << gflags::ProgramUsage() << std::endl;
20 | return 0;
21 | }
22 |
23 | auto L = fakelua_newstate();
24 | L->compile_file(argv[1], {debug_mode: FLAGS_debug});
25 |
26 | int code = 0;
27 | for (int i = 0; i < FLAGS_repeat; i++) {
28 | L->call(FLAGS_entry, std::tie(code));
29 | }
30 | std::cout << "code: " << code << std::endl;
31 |
32 | return code;
33 | }
34 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2 |
3 | project(libfakelua)
4 |
5 | #add magic_enum
6 | CPMAddPackage(
7 | NAME magic_enum
8 | GITHUB_REPOSITORY Neargye/magic_enum
9 | VERSION 0.9.5
10 | )
11 | include_directories(${magic_enum_SOURCE_DIR}/include/magic_enum)
12 |
13 | aux_source_directory(compile/bison FAKELUA_SRC_LIST)
14 | aux_source_directory(compile/flex FAKELUA_SRC_LIST)
15 | aux_source_directory(./compile FAKELUA_SRC_LIST)
16 | aux_source_directory(./state FAKELUA_SRC_LIST)
17 | aux_source_directory(./util FAKELUA_SRC_LIST)
18 | aux_source_directory(./fakelua FAKELUA_SRC_LIST)
19 | aux_source_directory(./jit FAKELUA_SRC_LIST)
20 | aux_source_directory(./var FAKELUA_SRC_LIST)
21 | aux_source_directory(./ FAKELUA_SRC_LIST)
22 | include_directories(./)
23 | include_directories(../include)
24 | include_directories(./platform)
25 | add_library(fakelua SHARED ${FAKELUA_SRC_LIST})
26 |
27 | IF (WIN32)
28 | set(TARGET_LIB gccjit)
29 | ENDIF ()
30 |
31 | if (USE_COV)
32 | set(TARGET_LIB ${TARGET_LIB} gcov)
33 | endif ()
34 |
35 | target_link_libraries(fakelua ${TARGET_LIB})
36 |
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | # Directory structure
2 | * [compile](./compile) use flex bison to lexing parsing lua code
3 | * [fakelua](./fakelua) some global code
4 | * [jit](./jit) use the gccjit library to generate native code
5 | * [platform](./platform) platform code, use cross platform
6 | * [state](./state) lua state code, and some state subclass
7 | * [util](./util) some util code, like memory pool
8 | * [var](./var) the lua variable code, like table, string, number, etc
9 |
--------------------------------------------------------------------------------
/src/compile/README.md:
--------------------------------------------------------------------------------
1 | # The Complete Syntax of Lua
2 | ```
3 | chunk ::= block
4 |
5 | block ::= {stat} [retstat]
6 |
7 | stat ::= ‘;’ |
8 | varlist ‘=’ explist |
9 | functioncall |
10 | label |
11 | break |
12 | goto Name |
13 | do block end |
14 | while exp do block end |
15 | repeat block until exp |
16 | if exp then block {elseif exp then block} [else block] end |
17 | for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end |
18 | for namelist in explist do block end |
19 | function funcname funcbody |
20 | local function Name funcbody |
21 | local attnamelist [‘=’ explist]
22 |
23 | attnamelist ::= Name attrib {‘,’ Name attrib}
24 |
25 | attrib ::= [‘<’ Name ‘>’]
26 |
27 | retstat ::= return [explist] [‘;’]
28 |
29 | label ::= ‘::’ Name ‘::’
30 |
31 | funcname ::= Name {‘.’ Name} [‘:’ Name]
32 |
33 | varlist ::= var {‘,’ var}
34 |
35 | var ::= Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name
36 |
37 | namelist ::= Name {‘,’ Name}
38 |
39 | explist ::= exp {‘,’ exp}
40 |
41 | exp ::= nil | false | true | Numeral | LiteralString | ‘...’ | functiondef |
42 | prefixexp | tableconstructor | exp binop exp | unop exp
43 |
44 | prefixexp ::= var | functioncall | ‘(’ exp ‘)’
45 |
46 | functioncall ::= prefixexp args | prefixexp ‘:’ Name args
47 |
48 | args ::= ‘(’ [explist] ‘)’ | tableconstructor | LiteralString
49 |
50 | functiondef ::= function funcbody
51 |
52 | funcbody ::= ‘(’ [parlist] ‘)’ block end
53 |
54 | parlist ::= namelist [‘,’ ‘...’] | ‘...’
55 |
56 | tableconstructor ::= ‘{’ [fieldlist] ‘}’
57 |
58 | fieldlist ::= field {fieldsep field} [fieldsep]
59 |
60 | field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
61 |
62 | fieldsep ::= ‘,’ | ‘;’
63 |
64 | binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘//’ | ‘^’ | ‘%’ |
65 | ‘&’ | ‘~’ | ‘|’ | ‘>>’ | ‘<<’ | ‘..’ |
66 | ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ |
67 | and | or
68 |
69 | unop ::= ‘-’ | not | ‘#’ | ‘~’
70 | ```
--------------------------------------------------------------------------------
/src/compile/bison/build.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | set -x
3 |
4 | bison parser.y --html --graph --header=parser.h -o parser.cpp
5 | export LC_ALL=en_US.UTF-8
6 | bison parser.y --html --graph --header=parser.h -o parser.cpp
7 |
--------------------------------------------------------------------------------
/src/compile/bison/location.hh:
--------------------------------------------------------------------------------
1 | // A Bison parser, made by GNU Bison 3.8.
2 |
3 | // Locations for Bison parsers in C++
4 |
5 | // Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc.
6 |
7 | // This program is free software: you can redistribute it and/or modify
8 | // it under the terms of the GNU General Public License as published by
9 | // the Free Software Foundation, either version 3 of the License, or
10 | // (at your option) any later version.
11 |
12 | // This program is distributed in the hope that it will be useful,
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | // GNU General Public License for more details.
16 |
17 | // You should have received a copy of the GNU General Public License
18 | // along with this program. If not, see .
19 |
20 | // As a special exception, you may create a larger work that contains
21 | // part or all of the Bison parser skeleton and distribute that work
22 | // under terms of your choice, so long as that work isn't itself a
23 | // parser generator using the skeleton or a modified version thereof
24 | // as a parser skeleton. Alternatively, if you modify or redistribute
25 | // the parser skeleton itself, you may (at your option) remove this
26 | // special exception, which will cause the skeleton and the resulting
27 | // Bison output files to be licensed under the GNU General Public
28 | // License without this special exception.
29 |
30 | // This special exception was added by the Free Software Foundation in
31 | // version 2.2 of Bison.
32 |
33 | /**
34 | ** \file location.hh
35 | ** Define the yy::location class.
36 | */
37 |
38 | #ifndef YY_YY_LOCATION_HH_INCLUDED
39 | # define YY_YY_LOCATION_HH_INCLUDED
40 |
41 | # include
42 | # include
43 |
44 | # ifndef YY_NULLPTR
45 | # if defined __cplusplus
46 | # if 201103L <= __cplusplus
47 | # define YY_NULLPTR nullptr
48 | # else
49 | # define YY_NULLPTR 0
50 | # endif
51 | # else
52 | # define YY_NULLPTR ((void*)0)
53 | # endif
54 | # endif
55 |
56 | namespace yy {
57 | #line 58 "location.hh"
58 |
59 | /// A point in a source file.
60 | class position
61 | {
62 | public:
63 | /// Type for file name.
64 | typedef const std::string filename_type;
65 | /// Type for line and column numbers.
66 | typedef int counter_type;
67 |
68 | /// Construct a position.
69 | explicit position (filename_type* f = YY_NULLPTR,
70 | counter_type l = 1,
71 | counter_type c = 1)
72 | : filename (f)
73 | , line (l)
74 | , column (c)
75 | {}
76 |
77 |
78 | /// Initialization.
79 | void initialize (filename_type* fn = YY_NULLPTR,
80 | counter_type l = 1,
81 | counter_type c = 1)
82 | {
83 | filename = fn;
84 | line = l;
85 | column = c;
86 | }
87 |
88 | /** \name Line and Column related manipulators
89 | ** \{ */
90 | /// (line related) Advance to the COUNT next lines.
91 | void lines (counter_type count = 1)
92 | {
93 | if (count)
94 | {
95 | column = 1;
96 | line = add_ (line, count, 1);
97 | }
98 | }
99 |
100 | /// (column related) Advance to the COUNT next columns.
101 | void columns (counter_type count = 1)
102 | {
103 | column = add_ (column, count, 1);
104 | }
105 | /** \} */
106 |
107 | /// File name to which this position refers.
108 | filename_type* filename;
109 | /// Current line number.
110 | counter_type line;
111 | /// Current column number.
112 | counter_type column;
113 |
114 | private:
115 | /// Compute max (min, lhs+rhs).
116 | static counter_type add_ (counter_type lhs, counter_type rhs, counter_type min)
117 | {
118 | return lhs + rhs < min ? min : lhs + rhs;
119 | }
120 | };
121 |
122 | /// Add \a width columns, in place.
123 | inline position&
124 | operator+= (position& res, position::counter_type width)
125 | {
126 | res.columns (width);
127 | return res;
128 | }
129 |
130 | /// Add \a width columns.
131 | inline position
132 | operator+ (position res, position::counter_type width)
133 | {
134 | return res += width;
135 | }
136 |
137 | /// Subtract \a width columns, in place.
138 | inline position&
139 | operator-= (position& res, position::counter_type width)
140 | {
141 | return res += -width;
142 | }
143 |
144 | /// Subtract \a width columns.
145 | inline position
146 | operator- (position res, position::counter_type width)
147 | {
148 | return res -= width;
149 | }
150 |
151 | /** \brief Intercept output stream redirection.
152 | ** \param ostr the destination output stream
153 | ** \param pos a reference to the position to redirect
154 | */
155 | template
156 | std::basic_ostream&
157 | operator<< (std::basic_ostream& ostr, const position& pos)
158 | {
159 | if (pos.filename)
160 | ostr << *pos.filename << ':';
161 | return ostr << pos.line << '.' << pos.column;
162 | }
163 |
164 | /// Two points in a source file.
165 | class location
166 | {
167 | public:
168 | /// Type for file name.
169 | typedef position::filename_type filename_type;
170 | /// Type for line and column numbers.
171 | typedef position::counter_type counter_type;
172 |
173 | /// Construct a location from \a b to \a e.
174 | location (const position& b, const position& e)
175 | : begin (b)
176 | , end (e)
177 | {}
178 |
179 | /// Construct a 0-width location in \a p.
180 | explicit location (const position& p = position ())
181 | : begin (p)
182 | , end (p)
183 | {}
184 |
185 | /// Construct a 0-width location in \a f, \a l, \a c.
186 | explicit location (filename_type* f,
187 | counter_type l = 1,
188 | counter_type c = 1)
189 | : begin (f, l, c)
190 | , end (f, l, c)
191 | {}
192 |
193 |
194 | /// Initialization.
195 | void initialize (filename_type* f = YY_NULLPTR,
196 | counter_type l = 1,
197 | counter_type c = 1)
198 | {
199 | begin.initialize (f, l, c);
200 | end = begin;
201 | }
202 |
203 | /** \name Line and Column related manipulators
204 | ** \{ */
205 | public:
206 | /// Reset initial location to final location.
207 | void step ()
208 | {
209 | begin = end;
210 | }
211 |
212 | /// Extend the current location to the COUNT next columns.
213 | void columns (counter_type count = 1)
214 | {
215 | end += count;
216 | }
217 |
218 | /// Extend the current location to the COUNT next lines.
219 | void lines (counter_type count = 1)
220 | {
221 | end.lines (count);
222 | }
223 | /** \} */
224 |
225 |
226 | public:
227 | /// Beginning of the located region.
228 | position begin;
229 | /// End of the located region.
230 | position end;
231 | };
232 |
233 | /// Join two locations, in place.
234 | inline location&
235 | operator+= (location& res, const location& end)
236 | {
237 | res.end = end.end;
238 | return res;
239 | }
240 |
241 | /// Join two locations.
242 | inline location
243 | operator+ (location res, const location& end)
244 | {
245 | return res += end;
246 | }
247 |
248 | /// Add \a width columns to the end position, in place.
249 | inline location&
250 | operator+= (location& res, location::counter_type width)
251 | {
252 | res.columns (width);
253 | return res;
254 | }
255 |
256 | /// Add \a width columns to the end position.
257 | inline location
258 | operator+ (location res, location::counter_type width)
259 | {
260 | return res += width;
261 | }
262 |
263 | /// Subtract \a width columns to the end position, in place.
264 | inline location&
265 | operator-= (location& res, location::counter_type width)
266 | {
267 | return res += -width;
268 | }
269 |
270 | /// Subtract \a width columns to the end position.
271 | inline location
272 | operator- (location res, location::counter_type width)
273 | {
274 | return res -= width;
275 | }
276 |
277 | /** \brief Intercept output stream redirection.
278 | ** \param ostr the destination output stream
279 | ** \param loc a reference to the location to redirect
280 | **
281 | ** Avoid duplicate information.
282 | */
283 | template
284 | std::basic_ostream&
285 | operator<< (std::basic_ostream& ostr, const location& loc)
286 | {
287 | location::counter_type end_col
288 | = 0 < loc.end.column ? loc.end.column - 1 : 0;
289 | ostr << loc.begin;
290 | if (loc.end.filename
291 | && (!loc.begin.filename
292 | || *loc.begin.filename != *loc.end.filename))
293 | ostr << '-' << loc.end.filename << ':' << loc.end.line << '.' << end_col;
294 | else if (loc.begin.line < loc.end.line)
295 | ostr << '-' << loc.end.line << '.' << end_col;
296 | else if (loc.begin.column < end_col)
297 | ostr << '-' << end_col;
298 | return ostr;
299 | }
300 |
301 | } // yy
302 | #line 303 "location.hh"
303 |
304 | #endif // !YY_YY_LOCATION_HH_INCLUDED
305 |
--------------------------------------------------------------------------------
/src/compile/compile_common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include