├── .circleci └── config.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── _config.yml ├── clib ├── libheap.c └── libio.c ├── doc ├── production.txt └── sample │ ├── 1.ckx │ ├── 2.ckx │ ├── 3.ckx │ ├── 4.ckx │ ├── 5.ckx │ └── 6.ckx ├── include ├── frontend │ ├── AST │ │ ├── ckx_ast_node.hpp │ │ ├── ckx_ast_node_fwd.hpp │ │ └── ckx_operator.hpp │ ├── lex │ │ ├── ckx_token.hpp │ │ └── ckx_token_stream.hpp │ ├── parse │ │ ├── ckx_parser.hpp │ │ ├── ckx_parser_impl.hpp │ │ ├── ckx_prelexed_type.hpp │ │ ├── ckx_token_set.hpp │ │ └── gg.h │ ├── sema │ │ ├── ckx_context.hpp │ │ ├── ckx_context_manager.hpp │ │ ├── ckx_env_table.hpp │ │ ├── ckx_func_name_mangler.hpp │ │ ├── ckx_llvm_type_builder.hpp │ │ ├── ckx_sema.hpp │ │ ├── ckx_sema_fwd.hpp │ │ ├── ckx_sema_result.hpp │ │ ├── ckx_sema_result_fwd.hpp │ │ └── ckx_type.hpp │ └── util │ │ ├── ckx_error.hpp │ │ └── ckx_src_rng.hpp ├── llvm │ ├── llvm_implicit_list.hpp │ ├── llvm_inst.hpp │ ├── llvm_inst_detail.hpp │ ├── llvm_ir_builder.hpp │ ├── llvm_ir_builder_impl.hpp │ ├── llvm_type.hpp │ ├── llvm_value.hpp │ ├── llvm_value_detail.hpp │ └── opdef.hpp ├── saber │ ├── algorithm.hpp │ ├── c8assert.hpp │ ├── excalibur.hpp │ ├── functional.hpp │ ├── iterator.hpp │ ├── list.hpp │ ├── memory.hpp │ ├── object_pool.hpp │ ├── optional.hpp │ ├── result.hpp │ ├── saber_traits.hpp │ ├── safe_stl_general.hpp │ ├── string.hpp │ ├── string_pool.hpp │ ├── strings.defs.h │ ├── type_traits.hpp │ ├── unordered_map.hpp │ ├── unordered_set.hpp │ ├── utility.hpp │ └── vector.hpp └── we │ ├── defs.hpp │ ├── file_reader.hpp │ └── file_writer.hpp ├── src ├── driver │ └── main.cpp ├── frontend │ ├── AST │ │ ├── ckx_ast_dump.cpp │ │ └── ckx_ast_node.cpp │ ├── lex │ │ ├── ckx_operator.cpp │ │ ├── ckx_token.cpp │ │ └── ckx_token_stream.cpp │ ├── parse │ │ ├── ckx_parser.cpp │ │ ├── ckx_prelexed_type.cpp │ │ └── ckx_token_set.cpp │ └── sema │ │ ├── ckx_context_manager.cpp │ │ ├── ckx_env_table.cpp │ │ ├── ckx_func_name_mangler.cpp │ │ ├── ckx_llvm_type_builder.cpp │ │ ├── ckx_sema.cpp │ │ ├── ckx_sema_test_suite.cpp │ │ ├── ckx_translate.cpp │ │ ├── ckx_type.cpp │ │ └── ckx_type_dump.cpp ├── llvm │ ├── llvm_inst.cpp │ ├── llvm_ir_builder.cpp │ ├── llvm_ir_builder_impl.cpp │ ├── llvm_value.cpp │ └── main_as_test.cpp ├── saber │ └── safe_stl_general.cpp └── we │ ├── file_reader.cpp │ └── file_writer.cpp ├── test-codeship └── test ├── parse ├── test_parse_decl │ └── test_decl.cpp ├── test_parse_expr │ └── test_expr.cpp ├── test_parse_func │ └── test_func.cpp ├── test_parse_stmt │ └── test_stmt.cpp ├── test_parse_udt │ └── test_udt.cpp └── test_parser │ └── test_parser.cpp └── sema ├── test1.cpp ├── test2.cpp └── test3.cpp /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | machine: 4 | environment: 5 | CMAKE_C_COMPILER: clang-4.0 6 | CMAKE_CXX_COMPILER: clang++-4.0 7 | 8 | step-library: 9 | - &setup-llvm-symbolizer 10 | run: 11 | name: Environment Setup 12 | command: | 13 | # LLVM has a hard check for "llvm-symbolizer" and doesn't support suffixed executables 14 | ln -s /usr/bin/llvm-symbolizer-* /usr/bin/llvm-symbolizer 15 | # We'll use tee to redirect stderr to a file so we can check for sanitiziation 16 | # https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/1059947 17 | sed -i 's/"$@" 2>&1/"$@"/' /usr/bin/xvfb-run 18 | 19 | jobs: 20 | build: 21 | docker: 22 | - image: mbgl/7d2403f42e:linux-clang-4 23 | steps: 24 | - checkout 25 | - *setup-llvm-symbolizer 26 | - run: 27 | name: Generate CMake 28 | command: cmake . 29 | - run: 30 | name: Build CMake 31 | command: cmake --build . --target all -- -j 8 32 | - run: 33 | name: List all files 34 | command: ls -l 35 | 36 | - store_artifacts: 37 | path: ckxc 38 | -------------------------------------------------------------------------------- /.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 | # Qt project configuration 35 | *.pro.user 36 | *.pro.user.* 37 | 38 | # CMake project configuration 39 | CMakeLists.txt.user 40 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (compilers-ckx) 3 | 4 | set (CMAKE_CXX_STANDARD 14) 5 | 6 | include_directories (include) 7 | 8 | aux_source_directory (src/driver DRIVER_SRC) 9 | aux_source_directory (src/frontend/AST AST_SRCS) 10 | aux_source_directory (src/frontend/lex LEX_SRCS) 11 | aux_source_directory (src/frontend/parse PARSE_SRCS) 12 | aux_source_directory (src/frontend/sema SEMA_SRCS) 13 | aux_source_directory (src/frontend/util UTIL_SRCS) 14 | aux_source_directory (src/llvm LLVM_SRCS) 15 | aux_source_directory (src/saber SABER_SRCS) 16 | aux_source_directory (src/we WE_SRCS) 17 | 18 | add_library (saber ${SABER_SRCS}) 19 | add_library (we ${WE_SRCS}) 20 | add_library (llvm ${LLVM_SRCS}) 21 | add_library (frontend ${AST_SRCS} ${LEX_SRCS} ${PARSE_SRCS} ${SEMA_SRCS} ${UTIL_SRCS}) 22 | add_executable (ckxc ${DRIVER_SRC}) 23 | 24 | target_link_libraries (we "saber") 25 | target_link_libraries (llvm "we" "saber") 26 | target_link_libraries (frontend "we" "saber") 27 | target_link_libraries (ckxc "we" "saber" "frontend" "llvm") 28 | 29 | aux_source_directory (test/parse/test_parse_decl TEST_PARSE_DECL_SRC) 30 | aux_source_directory (test/parse/test_parse_expr TEST_PARSE_EXPR_SRC) 31 | aux_source_directory (test/parse/test_parse_func TEST_PARSE_FUNC_SRC) 32 | aux_source_directory (test/parse/test_parse_stmt TEST_PARSE_STMT_SRC) 33 | aux_source_directory (test/parse/test_parse_udt TEST_PARSE_UDT_SRC) 34 | 35 | add_executable (test_parse_decl ${TEST_PARSE_DECL_SRC}) 36 | add_executable (test_parse_expr ${TEST_PARSE_EXPR_SRC}) 37 | add_executable (test_parse_func ${TEST_PARSE_FUNC_SRC}) 38 | add_executable (test_parse_stmt ${TEST_PARSE_STMT_SRC}) 39 | add_executable (test_parse_udt ${TEST_PARSE_UDT_SRC}) 40 | 41 | target_link_libraries (test_parse_decl "we" "saber" "frontend" "llvm") 42 | target_link_libraries (test_parse_expr "we" "saber" "frontend" "llvm") 43 | target_link_libraries (test_parse_func "we" "saber" "frontend" "llvm") 44 | target_link_libraries (test_parse_stmt "we" "saber" "frontend" "llvm") 45 | target_link_libraries (test_parse_udt "we" "saber" "frontend" "llvm") 46 | 47 | add_executable (test_sema_1 test/sema/test1.cpp) 48 | add_executable (test_sema_2 test/sema/test2.cpp) 49 | add_executable (test_sema_3 test/sema/test3.cpp) 50 | target_link_libraries (test_sema_1 "we" "saber" "frontend" "llvm") 51 | target_link_libraries (test_sema_2 "we" "saber" "frontend" "llvm") 52 | target_link_libraries (test_sema_3 "we" "saber" "frontend" "llvm") 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The programming language - ckx 2 | 3 | [![CircleCI](https://circleci.com/gh/ILoveChenKX/compilers-ckx.svg?style=svg)](https://circleci.com/gh/ILoveChenKX/compilers-ckx) 4 | 5 | A general purposed programming language -- for my honey -- chenkx 6 | 7 |
8 |
9 | 10 | ## Original idea 11 | 12 | Originally I decided to write a C compiler as a practice in my university. And it may also become a good compiler for freshmen to learn how to build compilers. 13 | 14 | But unfortunately, I don't like the `array` in C 15 | 16 | ```c 17 | int array[10]; // Ok, that's an array. 18 | // ... 19 | 20 | int max(int array[10]); // But this function takes a pointer instead of an array 21 | int m = max(array); // Well, array decays to pointer int* now. 22 | ``` 23 | 24 | So I decided to create another language that would merely improve C... 25 | 26 | And finally I designed ckx which is absolutely not C. 27 | 28 | ## Basic syntax 29 | 30 | > Note : the grammers may change in the further future. Before the version 1.0, everything is uncertain and newer versions may be no compatibility with the former versions. 31 | 32 | ### Basic structure of a ckx program 33 | 34 | 35 | 1) import std.io; 36 | 2) 37 | 3) fn main() : i32 38 | 4) { 39 | 5) vi16 a, b; 40 | 6) input(a); 41 | 7) input(b); 42 | 8) vi16 c = a + b; 43 | 9) print(c); 44 | A) return 0; 45 | B) } 46 | C) 47 | 48 | The first line `import std.io` uses ckx keyword `import` to import `io` utility module from package `std`. As you can see, ckx will have a very powerful module manage system, and we will use this package manage system in the future. But currently I ~~the programmer~~ does not know how to implement this module system. So in the early versions, ckx will include a preprocessor system, importing functions still uses `#include`. 49 | 50 | the `function main` is equivalent to the `main` function in C or C++. it shall returns an integer.. 51 | 52 | ### Basic data types 53 | 54 | Instead of using type names like `int` and `long`, ckx explicitly label the size/capacity in type names. 55 | 56 | * `vi8` `vi16` `vi32` and `vi64` represents signed integers of size 8/16/32/64 bits. 57 | * `vu8` `vu16` `vu32` and `vu64` represents unsigned integers of their corresponding size. 58 | * `vr32` is mostly equivalent to `float` and `vr64` is mosylt equivalent to `double` 59 | * `vch` is the char type for ckx. however, still I don't know what to use for this type. the default C/C++ `char` of size 8 may be a temporary solution. 60 | 61 | ### Functions 62 | 63 | You can `declare` a function like this: 64 | 65 | 1) fn add (vi16 a, vi16 b) : vi16 66 | 67 | And you can define a function like this: 68 | 69 | 1) fn add (vi16 a, vi16 b) : vi16 70 | 2) { 71 | 3) return a + b; 72 | 4) } 73 | 74 | And invoking a function will be: 75 | 76 | 1) vi16 c = add(a, b); 77 | 2) vi16 d; 78 | 3) d = add(add(a, b), c); 79 | 80 | Nothing different from other languages. 81 | 82 | ### User-defined types 83 | 84 | User-defined types grammer are also similar to C. You can use `struct` to define a record type, use `variant` to define a variant/union type, and use `enum` to define an enum type and enumerators. 85 | 86 | > example : Defining a struct student. Note no comma after the closing brace. Once defined, student will become a typename. 87 | 88 | 1) struct student 89 | 2) { 90 | 3) vu64 id; 91 | 4) vr32 score; 92 | 5) } 93 | 94 | ### Pointers 95 | 96 | Pointers in ckx is the same as pointers in C. The powerful low-level operator. 97 | 98 | > I'm not about to include Garbage collection in this programming language. 99 | 100 | 1) vi8 i; 101 | 2) vi8 *p = &i; // Taking address 102 | 3) vi8 *q = heap_alloc(); // Using heap allocation 103 | 4) heap_free(q); // Remember to free! 104 | 5) 105 | 6) vi8 const* = &i; 106 | 107 | > Note: ckx supports `T const*` but does not support `const T*`. 108 | 109 | ### Arrays 110 | 111 | > P0001R0 "Array TS" 112 | 113 | Unlike in C, an `array` in ckx means a `range`. That is to say, for any array, it is possible to calculate its size according to its start point and finish point. 114 | 115 | There are four "create array" syntax: 116 | 117 | type[] array = type[]()(start-point, finish-point); (1) 118 | type[] array = type[](array-size)(start-point); (2) 119 | type[] array = type[](array-size); (3) 120 | type[] array = type[](array-size){initializer-list}; (4) 121 | 122 | (1) Create an array according to the given storage, specified by start-point and finish-point. 123 | 124 | (2) Create an array according to the given storage, unlike (1), the finishpoint is calculated through n automatically. 125 | 126 | (3) Create an array on stack, containing n default-initialized elements. 127 | 128 | (4) Create an array on stack, containing n elements, with the first several elements initialized with initializer-list. 129 | 130 | 131 | ### Other special features 132 | 133 | ##### Type casts 134 | 135 | * Only integers could be implicitly promoted. for example, promoting from `vi8` to `vi16`, or from `vu8` to `vu64`. 136 | * Signed integers will not be implicitly converted to unsigned ints. Vice versa. 137 | * Integers will not be implicitly converted to floats. And floats will also not be implicitly converted to ints. 138 | * Enumerators are actually integer constants. However, they have their individual type so will not be implicitly converted to integers. Integers also could not be implicitly converted to enums. 139 | 140 | ##### Function overloading 141 | 142 | * Function overloading is one targeted feature of ckx. 143 | * Currently I ~~The programmer~~ am not familiar with function overloading, name mangling... So I need some help. 144 | 145 | ##### Closures 146 | 147 | > Still in progress. If you have a good idea about it, contact me and I'll be appreciated. 148 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /clib/libheap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int8_t* heap_alloc_l_Pz(int64_t size) { 5 | return malloc(size); 6 | } 7 | 8 | void heap_free_Pz_N(int8_t* ptr) { 9 | free(ptr); 10 | } 11 | -------------------------------------------------------------------------------- /clib/libio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void print_D_N(double number) { 5 | printf("%g\n", number); 6 | } 7 | 8 | void print_F_N(float number) { 9 | printf("%g\n", number); 10 | } 11 | 12 | void print_l_N(int64_t number) { 13 | printf("%ld\n", number); 14 | } 15 | 16 | void print_i_N(int32_t number) { 17 | printf("%d\n", number); 18 | } 19 | 20 | void print_s_N(int16_t number) { 21 | printf("%hd\n", number); 22 | } 23 | 24 | void print_b_N(int8_t number) { 25 | printf("%d\n", (int)number); 26 | } 27 | 28 | void print_L_N(uint64_t number) { 29 | printf("%lu\n", number); 30 | } 31 | 32 | void input_Pl_N(int64_t *p) { 33 | scanf("%ld", p); 34 | } 35 | 36 | void input_Pi_N(int32_t *p) { 37 | scanf("%d", p); 38 | } 39 | 40 | void input_Ps_N(int16_t *p) { 41 | scanf("%hd", p); 42 | } 43 | 44 | void input_Pb_N(int8_t *p) { 45 | int temp; 46 | scanf("%d", &temp); 47 | *p = temp; 48 | } 49 | 50 | void input_PD_N(double *p) { 51 | scanf("%lf", p); 52 | } 53 | 54 | void input_PF_N(float *p) { 55 | scanf("%f", p); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /doc/production.txt: -------------------------------------------------------------------------------- 1 | translation-unit 2 | global-statements 3 | 4 | global-statement 5 | declaration 6 | function 7 | newtype 8 | 9 | import 10 | export 11 | 12 | statement 13 | declaration 14 | expression-statement 15 | control 16 | compound-statement 17 | 18 | expression-statement 19 | expression ; 20 | 21 | declaration 22 | declarator init-declaration-list; 23 | 24 | function 25 | "fn" id ( param-type-list ) -> declarator SKTT1Faker 26 | 27 | expression 28 | assignment-expression 29 | 30 | assignment-expression 31 | conditional-expression 32 | conditional-expression assignment-operator assignment-expression 33 | 34 | conditional-expression 35 | binary-expression 36 | binary-expression ? expression : assignment-expression 37 | 38 | binary-expression 39 | unary-expression 40 | unary-expression binary-operator binary-expression 41 | 42 | unary-expression 43 | usual-unary-expression 44 | cast-expression 45 | 46 | usual-unary-expression 47 | usual-unary-operator unary-expression 48 | postfix-expression 49 | 50 | postfix-expression 51 | array-subscript-expression 52 | function-invoke-expression 53 | 54 | array-subscript-expression 55 | basic-expression "[" expression "]" 56 | 57 | function-invoke-expression 58 | basic-expression "(" expression-paramaters-list ")" 59 | 60 | cast-expression 61 | static_cast < type > ( expression ) 62 | const_cast < type > ( expression ) 63 | reinterpret_cast < type > ( expression ) 64 | ckx_cast < type > ( expression ) 65 | 66 | basic-expression 67 | id-expression 68 | constant-expression 69 | parthed-expression 70 | sizeof-expression 71 | 72 | parthed-expression 73 | ( expression ) 74 | 75 | sizeof-expression 76 | sizeof ( expression ) 77 | 78 | param-type-list 79 | paramater-declaration [, paramater-type-list]opt 80 | 81 | paramater-declaration 82 | declarator [id]opt 83 | 84 | SKTT1Faker 85 | ; 86 | function-body 87 | 88 | control 89 | if-statement 90 | while-statement 91 | do-while-statement 92 | for-statement 93 | break-statement 94 | continue-statement 95 | return-statement 96 | 97 | newtype 98 | using-statement 99 | struct-decl 100 | variant-decl 101 | enum-decl 102 | 103 | compound-statement 104 | { statements... } 105 | 106 | import 107 | "import" package; 108 | 109 | export 110 | "export" package; 111 | 112 | declarator 113 | typename declarator 114 | cv-qualifier declarator 115 | pointer-declarator declarator 116 | 117 | typename 118 | vi8 | vi16 | vi32 | vi64 | vu8 | vu16 | vu32 | vu64 | vr32 | vr64 | vch 119 | enum-type-id 120 | struct-type-id 121 | variant-type-id 122 | 123 | cv-qualifier 124 | const 125 | 126 | pointer-declarator 127 | * 128 | 129 | init-declaration-list 130 | init-declaration [, init-declaration-list]opt 131 | 132 | init-declaration 133 | id [= init-expression]opt 134 | 135 | init-expression 136 | expression 137 | array-expression 138 | 139 | array-expression 140 | typename [] ( [array-size]opt ) RNGUzi 141 | 142 | RNGUzi 143 | { init-list } 144 | ( start-point [, end-point]opt ) 145 | 146 | if-statement 147 | if ( expression ) statement [else statement]opt 148 | 149 | while-statement 150 | while ( expression ) statement 151 | 152 | do-while-statement 153 | do statement while ( expression ) 154 | 155 | for-statement 156 | for ( [expression]opt ; [expression]opt ; [expression]opt ) statement 157 | 158 | break-statement 159 | break ; 160 | 161 | continue-statement 162 | continue ; 163 | 164 | return-statement 165 | return [expression]opt 166 | 167 | struct-decl 168 | struct id { fields } 169 | 170 | variant-decl 171 | variant id { fields } 172 | 173 | field 174 | declaration ; 175 | 176 | enum-decl 177 | enum id { enumerators } 178 | 179 | enumerators 180 | enumerator [, enumerators]opt 181 | 182 | enumerator 183 | id [= integral-literal]opt 184 | -------------------------------------------------------------------------------- /doc/sample/1.ckx: -------------------------------------------------------------------------------- 1 | fn string_copy(vi8* _dest, vi8 const* _from) : void; 2 | fn inputstr(vi8* _dest) : void; 3 | fn printstr(vi8 const* _from) : void; 4 | fn heap_alloc(vu64 size) : void*; 5 | fn heap_free(void* address) : void; 6 | 7 | fn main() : vi32 8 | { 9 | vi8* stra = reinterpret_cast(heap_alloc(256*sizeof(vi8))), 10 | strb = reinterpret_cast(heap_alloc(256*sizeof(vi8))); 11 | inputstr(stra); 12 | string_copy(strb, stra); 13 | printstr(strb); 14 | heap_free(reinterpret_cast(stra)); 15 | heap_free(reinterpret_cast(strb)); 16 | return 0; 17 | } 18 | 19 | fn string_copy(vi8* _dest, vi8 const * _from) : void { 20 | while (*_from != 0) { 21 | *_dest = *_from; 22 | ++_dest; 23 | ++_from; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /doc/sample/2.ckx: -------------------------------------------------------------------------------- 1 | struct student { 2 | vu16 id; 3 | vu8 chinese; 4 | vu8 math; 5 | vu8 english; 6 | } 7 | 8 | fn create_student(student* stu, 9 | vu16 id, 10 | vu8 chinese, 11 | vu8 math, 12 | vu8 english) : void 13 | { 14 | stu.id = id; 15 | stu.chinese = chinese; 16 | stu.math = math; 17 | stu.english = english; 18 | } 19 | 20 | fn print_student(student const* stu) : void 21 | { 22 | println(stu.id); 23 | println(stu.chinese); 24 | println(stu.math); 25 | println(stu.english); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /doc/sample/3.ckx: -------------------------------------------------------------------------------- 1 | struct grade { 2 | vu8 value; 3 | grade* next; 4 | } 5 | 6 | struct student { 7 | vu16 id; 8 | grade* g; 9 | } 10 | 11 | fn create_student(student* stu, vu16 id) : void { 12 | stu.id = id; 13 | stu.g = nullptr; 14 | } 15 | 16 | fn add_grade(student* stu, vu8 new_grade) : void { 17 | grade** g = &stu.g; 18 | while (*g != nullptr) { 19 | *g = (*g).next; 20 | } 21 | *g = reinterpret_cast(heap_alloc(sizeof(grade))); 22 | (*g).value = new_grade; 23 | (*g).next = nullptr; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /doc/sample/4.ckx: -------------------------------------------------------------------------------- 1 | fn input(vu64 *n) : void; 2 | fn print(vu64 n) : void; 3 | fn fibonacci(vu64 n) : vu64; 4 | 5 | fn main() : vi32 6 | { 7 | vu64 n; 8 | input(&n); 9 | print(fibonacci(n)); 10 | return 0; 11 | } 12 | 13 | fn fibonacci(vu64 n) : vu64 14 | { 15 | if (n == 0) return 0; 16 | if (n == 1) return 1; 17 | return fibonacci(n-1) + fibonacci(n-2); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /doc/sample/5.ckx: -------------------------------------------------------------------------------- 1 | struct student 2 | { 3 | vi8* name; 4 | vu8 chinese; 5 | vu8 math; 6 | vu8 english; 7 | } 8 | 9 | fn createStudent(vi8 const* name, vu8 chinese, vu8 math, vu8 english) : student* 10 | { 11 | student *ret = reinterpret_cast(heap_alloc(sizeof(student))); 12 | string_copy(ret.name, name); 13 | ret.chinese = chinese; 14 | ret.math = math; 15 | ret.english = english; 16 | return ret; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /doc/sample/6.ckx: -------------------------------------------------------------------------------- 1 | struct type { vu8 value; } 2 | struct utype { type t; } 3 | struct vtype { utype u; } 4 | 5 | fn main() : vi32 6 | { 7 | vtype v; 8 | print(v.u.t.value); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /include/frontend/AST/ckx_ast_node_fwd.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_AST_NODE_FWD_HPP 20 | #define CKX_AST_NODE_FWD_HPP 21 | 22 | namespace ckx 23 | { 24 | 25 | class ckx_ast_node; 26 | class ckx_ast_translation_unit; 27 | class ckx_ast_stmt; 28 | 29 | class ckx_ast_compound_stmt; 30 | class ckx_ast_if_stmt; 31 | class ckx_ast_while_stmt; 32 | class ckx_ast_for_stmt; 33 | class ckx_ast_do_while_stmt; 34 | class ckx_ast_break_stmt; 35 | class ckx_ast_continue_stmt; 36 | class ckx_ast_return_stmt; 37 | 38 | class ckx_ast_record_stmt; 39 | class ckx_ast_enum_stmt; 40 | class ckx_ast_alias_stmt; 41 | class ckx_ast_decl_stmt; 42 | class ckx_ast_func_stmt; 43 | class ckx_ast_expr_stmt; 44 | 45 | class ckx_ast_init_decl; 46 | 47 | class ckx_ast_expr; 48 | class ckx_ast_binary_expr; 49 | class ckx_ast_unary_expr; 50 | class ckx_ast_subscript_expr; 51 | class ckx_ast_invoke_expr; 52 | class ckx_ast_extract_expr; 53 | class ckx_ast_enumerator_expr; 54 | class ckx_ast_cond_expr; 55 | class ckx_ast_id_expr; 56 | class ckx_ast_cast_expr; 57 | class ckx_ast_sizeof_expr; 58 | class ckx_ast_vi_literal_expr; 59 | class ckx_ast_vr_literal_expr; 60 | class ckx_ast_nullptr_expr; 61 | class ckx_ast_bool_literal_expr; 62 | class ckx_ast_array_expr; 63 | 64 | } // namespace ckx 65 | 66 | #endif // CKX_AST_NODE_FWD_HPP 67 | -------------------------------------------------------------------------------- /include/frontend/AST/ckx_operator.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_OPERATOR_HPP 2 | #define CKX_OPERATOR_HPP 3 | 4 | #include "frontend/lex/ckx_token.hpp" 5 | 6 | namespace ckx 7 | { 8 | 9 | enum class ckx_op : qchar 10 | { 11 | /// @note undefined, for the failed conversions 12 | op_undefined = -1, 13 | 14 | /// @note unary-operators 15 | op_unary_positive = 1, 16 | op_unary_negative, 17 | op_addr, 18 | op_deref, 19 | op_bit_not, 20 | op_logic_not, 21 | op_inc, 22 | op_dec, 23 | 24 | /// @note binary-operators 25 | op_add, 26 | op_sub, 27 | op_mul, 28 | op_div, 29 | op_mod, 30 | 31 | op_bit_and, 32 | op_bit_or, 33 | op_bit_xor, 34 | 35 | op_logic_and, 36 | op_logic_or, 37 | 38 | op_lt, 39 | op_eq, 40 | op_gt, 41 | op_leq, 42 | op_geq, 43 | op_neq, 44 | 45 | /// @note assignment-operators 46 | /// @attention assignment may also be treated as common binary operators. 47 | op_assign, 48 | op_add_assign, 49 | op_sub_assign, 50 | op_mul_assign, 51 | op_div_assign, 52 | op_mod_assign, 53 | }; 54 | 55 | class ckx_op_helper 56 | { 57 | public: 58 | static ckx_op token2unary(ckx_token::type _token); 59 | static ckx_op token2binary(ckx_token::type _token); 60 | 61 | static bool is_unary(ckx_op _op); 62 | static bool is_binary(ckx_op _op); 63 | static bool is_assign(ckx_op _op); 64 | 65 | static bool is_logical(ckx_op _op); 66 | 67 | static quint8 precedence(ckx_op); 68 | }; 69 | 70 | } 71 | 72 | #endif // CKX_OPERATOR_HPP 73 | -------------------------------------------------------------------------------- /include/frontend/lex/ckx_token.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | 20 | #ifndef CKX_TOKEN_HPP 21 | #define CKX_TOKEN_HPP 22 | 23 | #include "we/defs.hpp" 24 | #include "saber/string_pool.hpp" 25 | #include "saber/c8assert.hpp" 26 | #include "frontend/util/ckx_src_rng.hpp" 27 | 28 | namespace ckx 29 | { 30 | 31 | open_class ckx_token 32 | { 33 | enum class type : qchar 34 | { 35 | tk_assign, // = 36 | 37 | tk_add, // + 38 | tk_sub, // - 39 | tk_mul, // * 40 | tk_div, // / 41 | tk_mod, // % 42 | 43 | tk_add_assign, // += 44 | tk_sub_assign, // -= 45 | tk_mul_assign, // *= 46 | tk_div_assign, // /= 47 | tk_mod_assign, // %= 48 | 49 | tk_inc, // ++ 50 | tk_dec, // -- 51 | 52 | tk_bit_and, // & 53 | tk_bit_or, // | 54 | tk_bit_not, // ~ 55 | tk_bit_xor, // ^ 56 | 57 | tk_logic_and, // && 58 | tk_logic_or, // || 59 | tk_logic_not, // ! 60 | tk_logic_xor, // ^^ 61 | 62 | tk_lt, // < 63 | tk_eq, // == 64 | tk_gt, // > 65 | tk_leq, // <= 66 | tk_geq, // >= 67 | tk_neq, // != 68 | 69 | tk_colon, // : 70 | tk_scope, // :: 71 | tk_semicolon, // ; 72 | tk_comma, // , 73 | tk_dot, // . 74 | 75 | tk_lbrace, // { 76 | tk_rbrace, // } 77 | tk_lbracket, // [ 78 | tk_rbracket, // ] 79 | tk_arr, // [] 80 | tk_lparen, // ( 81 | tk_rparen, // ) 82 | 83 | tk_ques, // ? 84 | 85 | tk_vi8, // vi8 86 | tk_vi16, // vi16 87 | tk_vi32, // vi32 88 | tk_vi64, // vi64 89 | 90 | tk_vu8, // vu8 91 | tk_vu16, // vu16 92 | tk_vu32, // vu32 93 | tk_vu64, // vu64 94 | 95 | tk_vch, // vch 96 | 97 | tk_vr32, // vr32 98 | tk_vr64, // vr64 99 | 100 | tk_vnullptr_t, // vnptr_t 101 | tk_vbool, // vb1 102 | 103 | tk_void, // void 104 | 105 | tk_function, // fn 106 | 107 | tk_struct, // struct 108 | tk_variant, // variant 109 | tk_enum, // enum 110 | tk_alias, // alias 111 | 112 | tk_const, // const 113 | 114 | tk_if, // if 115 | tk_else, // else 116 | tk_for, // for 117 | tk_while, // while 118 | tk_do, // do 119 | tk_switch, // switch 120 | tk_case, // case 121 | tk_return, // return 122 | tk_break, // break 123 | tk_continue, // continue 124 | 125 | tk_operator, // operator 126 | 127 | tk_id, // identifier 128 | 129 | tk_vi_literal, // int literal 130 | // reserved 131 | tk_vu_literal, // unsigned literal 132 | tk_vr_literal, // real literal 133 | tk_vchar_literal, // char literal 134 | // reserved 135 | tk_string_literal, // string literal 136 | tk_nullptr, // nullptr 137 | tk_true, // true 138 | tk_false, // false 139 | 140 | tk_static_cast, // static_cast 141 | tk_reinterpret_cast, // reinterpret_cast 142 | tk_const_cast, // const_cast 143 | tk_ckx_cast, // ckx_cast 144 | 145 | tk_sizeof, // sizeof 146 | 147 | tk_eoi // EOI 148 | }; 149 | 150 | ckx_token(ckx_src_rng _rng, type _operator); 151 | ckx_token(ckx_src_rng _rng, qint64 _int_literal); 152 | ckx_token(ckx_src_rng _rng, quint64 _unsigned_literal); 153 | ckx_token(ckx_src_rng _rng, qreal _real_literal); 154 | ckx_token(ckx_src_rng _rng, qchar _char_literal); 155 | ckx_token(ckx_src_rng _rng, saber_string_view _id); 156 | 157 | ckx_token() = delete; 158 | ~ckx_token() = default; 159 | 160 | const ckx_src_rng rng; 161 | 162 | type token_type; 163 | variant token_value 164 | { 165 | const qchar ch; 166 | const qint64 i64; 167 | const quint64 u64; 168 | const qreal r; 169 | 170 | token_value() {} 171 | token_value(qchar _ch) : ch(_ch) {} 172 | token_value(qint64 _i64) : i64(_i64) {} 173 | token_value(quint64 _u64) : u64(_u64) {} 174 | token_value(qreal _r) : r(_r) {} 175 | ~token_value() = default; 176 | } v; 177 | const saber_string_view str = saber_string_pool::create_view(""); 178 | }; 179 | 180 | struct ckx_token_type_hash 181 | { 182 | size_t operator() (ckx_token::type _type) const 183 | { 184 | return std::hash()(static_cast(_type)); 185 | } 186 | }; 187 | 188 | saber_string to_string_helper(ckx_token _token); 189 | 190 | } // namespace ckx 191 | 192 | #endif // CKX_TOKEN_HPP 193 | -------------------------------------------------------------------------------- /include/frontend/lex/ckx_token_stream.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_TOKEN_STREAM_HPP 20 | #define CKX_TOKEN_STREAM_HPP 21 | 22 | #include "saber/memory.hpp" 23 | #include "saber/string.hpp" 24 | #include "saber/vector.hpp" 25 | #include "saber/unordered_map.hpp" 26 | #include "we/file_reader.hpp" 27 | 28 | #include "frontend/lex/ckx_token.hpp" 29 | #include "frontend/util/ckx_error.hpp" 30 | 31 | namespace ckx 32 | { 33 | 34 | namespace detail 35 | { 36 | class ckx_token_stream_impl; 37 | } // namespace detail 38 | 39 | 40 | class ckx_token_stream final 41 | { 42 | public: 43 | explicit ckx_token_stream(we::we_file_reader &_file_reader); 44 | ~ckx_token_stream(); 45 | 46 | ckx_token& operator[] (int _offset); 47 | saber::vector& get_error(); 48 | void operator++ (); 49 | 50 | private: 51 | detail::ckx_token_stream_impl *impl; 52 | }; 53 | 54 | } // namespace ckx 55 | 56 | #endif // CKX_TOKEN_STREAM_HPP 57 | -------------------------------------------------------------------------------- /include/frontend/parse/ckx_parser.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_PARSER_HPP 20 | #define CKX_PARSER_HPP 21 | 22 | #include "frontend/lex/ckx_token_stream.hpp" 23 | #include "frontend/AST/ckx_ast_node_fwd.hpp" 24 | #include "saber/list.hpp" 25 | #include "saber/memory.hpp" 26 | 27 | namespace ckx 28 | { 29 | 30 | namespace detail 31 | { 32 | class ckx_parser_impl; 33 | } // namespace detail 34 | 35 | class ckx_syntax_error 36 | { 37 | public: 38 | ckx_syntax_error(ckx_src_rng _rng, saber_string_view _desc) : 39 | rng(_rng), desc(_desc) {} 40 | 41 | ckx_src_rng rng; 42 | saber_string_view desc; 43 | }; 44 | 45 | class ckx_parser 46 | { 47 | public: 48 | struct parse_result 49 | { 50 | parse_result(ckx_ast_translation_unit *_trans_unit, 51 | saber::list &&_error_list, 52 | saber::list &&_warn_list); 53 | ~parse_result() = default; 54 | 55 | parse_result(const parse_result& _another) = delete; 56 | parse_result(parse_result&& _another); 57 | 58 | saber::caster_ptr trans_unit; 59 | saber::list error_list; 60 | saber::list warn_list; 61 | }; 62 | 63 | ckx_parser(); 64 | ~ckx_parser(); 65 | 66 | ckx_parser(const ckx_parser&) = delete; 67 | ckx_parser(ckx_parser&&) = delete; 68 | 69 | parse_result parse(ckx_token_stream *_token_stream); 70 | 71 | private: 72 | detail::ckx_parser_impl* p_impl; 73 | }; 74 | 75 | } // namespace ckx 76 | 77 | #endif // CKX_PARSER_HPP 78 | -------------------------------------------------------------------------------- /include/frontend/parse/ckx_parser_impl.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_PARSER_IMPL_HPP 2 | #define CKX_PARSER_IMPL_HPP 3 | 4 | #include "frontend/parse/ckx_parser.hpp" 5 | #include "frontend/parse/ckx_token_set.hpp" 6 | #include "frontend/AST/ckx_ast_node.hpp" 7 | #include "saber/unordered_set.hpp" 8 | #include "saber/optional.hpp" 9 | 10 | namespace ckx 11 | { 12 | 13 | namespace detail 14 | { 15 | 16 | class ckx_typename_table final 17 | { 18 | public: 19 | explicit ckx_typename_table() = default; 20 | ~ckx_typename_table() = default; 21 | 22 | void add_typename(saber_string_view _name) 23 | { 24 | typenames.emplace(_name); 25 | } 26 | 27 | bool query_typename(saber_string_view _name) const 28 | { 29 | if (typenames.find(_name) != typenames.end()) 30 | return true; 31 | return false; 32 | } 33 | 34 | void cleanup() 35 | { 36 | typenames.clear(); 37 | } 38 | 39 | private: 40 | saber::unordered_set typenames; 41 | }; 42 | 43 | 44 | class ckx_parser_impl 45 | { 46 | public: 47 | explicit ckx_parser_impl() = default; 48 | ~ckx_parser_impl() = default; 49 | 50 | ckx_parser_impl(const ckx_parser_impl&) = delete; 51 | ckx_parser_impl(ckx_parser_impl&&) = delete; 52 | 53 | typename ckx_parser::parse_result 54 | parse_impl(ckx_token_stream* _token_stream); 55 | 56 | protected: 57 | /// @brief General parsing functions 58 | /// for productions, see compilers-ckx/compiler/production.txt 59 | ckx_ast_stmt* parse_global_stmt(); 60 | ckx_ast_stmt* parse_stmt(); 61 | 62 | ckx_ast_decl_stmt* parse_decl_stmt(); 63 | ckx_ast_func_stmt* parse_func_stmt(); 64 | ckx_ast_record_stmt* parse_record_stmt(); 65 | ckx_ast_enum_stmt* parse_enum_stmt(); 66 | ckx_ast_alias_stmt* parse_alias_stmt(); 67 | 68 | ckx_ast_expr_stmt* parse_expr_stmt(); 69 | ckx_ast_if_stmt* parse_if_stmt(); 70 | ckx_ast_while_stmt* parse_while_stmt(); 71 | ckx_ast_do_while_stmt* parse_do_while_stmt(); 72 | ckx_ast_for_stmt* parse_for_stmt(); 73 | ckx_ast_break_stmt* parse_break_stmt(); 74 | ckx_ast_continue_stmt* parse_continue_stmt(); 75 | ckx_ast_return_stmt* parse_return_stmt(); 76 | ckx_ast_compound_stmt* parse_compound_stmt(); 77 | 78 | ckx_ast_expr* parse_expr(); 79 | ckx_ast_expr* parse_init_expr(); 80 | ckx_ast_expr* parse_array_expr(); 81 | 82 | ckx_ast_expr* parse_cond_expr(); 83 | ckx_ast_expr* parse_binary_expr(quint8 _prec); 84 | ckx_ast_expr* parse_assign_expr(); 85 | ckx_ast_expr* parse_unary_expr(); 86 | ckx_ast_expr* parse_postfix_expr(); 87 | 88 | ckx_ast_cast_expr* parse_cast_expr(); 89 | ckx_ast_expr* parse_basic_expr(); 90 | ckx_ast_id_expr* parse_id(); 91 | 92 | protected: 93 | 94 | /// @fn we need this function to ease the type resolving. 95 | ckx_prelexed_type parse_type(); 96 | 97 | /// @brief utility functions 98 | bool id_is_typename(ckx_token _token); 99 | 100 | /// @brief token-access functions 101 | /// simply encapsuled token-stream again. 102 | inline ckx_token& current_token(); 103 | inline ckx_token& peek_next_token(); 104 | inline void next_token(); 105 | 106 | inline saber::optional 107 | expect_n_eat(ckx_token::type _token_type); 108 | 109 | inline saber::optional 110 | expect(ckx_token::type _token_type); 111 | 112 | /// @brief functions for reporting problem. 113 | void syntax_error(ckx_src_rng _rng, saber_string_view _desc); 114 | void syntax_warn(ckx_src_rng _rng, saber_string_view _desc); 115 | 116 | /// @brief and here are functions for recovering from a syntax error. 117 | void skip2_token(const ckx_token_set& _token_set); 118 | 119 | protected: 120 | ckx_token_stream *token_stream; 121 | 122 | saber::list error_list; 123 | saber::list warn_list; 124 | 125 | /// @note still we need a table for storing types occured in parsing 126 | ckx_typename_table typename_table; 127 | }; 128 | 129 | 130 | } // namespace detail 131 | 132 | } // namespace ckx 133 | 134 | #endif // CKX_PARSER_IMPL_HPP 135 | -------------------------------------------------------------------------------- /include/frontend/parse/ckx_prelexed_type.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_PRELEXED_TYPE_HPP 2 | #define CKX_PRELEXED_TYPE_HPP 3 | 4 | #include "frontend/lex/ckx_token.hpp" 5 | #include "saber/vector.hpp" 6 | #include "saber/string_pool.hpp" 7 | 8 | namespace ckx 9 | { 10 | 11 | class ckx_prelexed_type 12 | { 13 | public: 14 | /// @note once determined, it's immutable. 15 | explicit ckx_prelexed_type(saber::vector&& _prelexed_tokens) : 16 | prelexed_tokens(saber::move(_prelexed_tokens)) {} 17 | ~ckx_prelexed_type() = default; 18 | ckx_prelexed_type(ckx_prelexed_type&& _another) : 19 | prelexed_tokens(saber::move(_another.prelexed_tokens)) {} 20 | 21 | ckx_prelexed_type(const ckx_prelexed_type&) = delete; 22 | 23 | const saber::vector& get_prelexed_tokens() const 24 | { 25 | return prelexed_tokens; 26 | } 27 | 28 | saber_string to_string() const 29 | { 30 | saber_string ret = ""; 31 | for (auto& token : prelexed_tokens) 32 | ret += to_string_helper(token) + " "; 33 | return ret; 34 | } 35 | 36 | private: 37 | const saber::vector prelexed_tokens; 38 | }; 39 | 40 | } 41 | 42 | #endif // CKX_PRELEXED_TYPE_HPP 43 | -------------------------------------------------------------------------------- /include/frontend/parse/ckx_token_set.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_TOKEN_SET_HPP 20 | #define CKX_TOKEN_SET_HPP 21 | 22 | #include "frontend/lex/ckx_token.hpp" 23 | #include "saber/unordered_set.hpp" 24 | 25 | namespace ckx 26 | { 27 | 28 | namespace detail 29 | { 30 | 31 | using ckx_token_set = saber::unordered_set; 33 | /** 34 | @brief The ckx_token_sets class 35 | static helper class that allows parser to obtain pre-built token_sets 36 | */ 37 | class ckx_token_sets 38 | { 39 | public: 40 | /// @todo more sets may be added here 41 | /// after we get a complete error recover strategy 42 | 43 | static const ckx_token_set& first_stmt_set(); 44 | static const ckx_token_set& first_global_set(); 45 | static const ckx_token_set& close_scope_set(); 46 | static const ckx_token_set& close_declarator_set(); 47 | static const ckx_token_set& close_struct_decl_set(); 48 | }; 49 | 50 | } // namespace detail 51 | 52 | } // namespace ckx 53 | 54 | #endif // CKX_TOKEN_SET_HPP 55 | -------------------------------------------------------------------------------- /include/frontend/parse/gg.h: -------------------------------------------------------------------------------- 1 | #ifndef GGLEX 2 | #define GGLEX(X, Y) 3 | #endif 4 | 5 | GGLEX("vi8", vi8) 6 | GGLEX("vi16", vi16) 7 | GGLEX("vi32", vi32) 8 | GGLEX("vi64", vi64) 9 | GGLEX("vu8", vu8) 10 | GGLEX("vu16", vu16) 11 | GGLEX("vu32", vu32) 12 | GGLEX("vu64", vu64) 13 | GGLEX("vch", vch) 14 | GGLEX("vr32", vr32) 15 | GGLEX("vr64", vr64) 16 | GGLEX("vnptr_t", vnullptr_t) 17 | GGLEX("vb1", vbool) 18 | GGLEX("void", void) 19 | GGLEX("fn", function) 20 | GGLEX("struct", struct) 21 | GGLEX("variant", variant) 22 | GGLEX("enum", enum) 23 | GGLEX("alias", alias) 24 | GGLEX("const", const) 25 | GGLEX("if", if) 26 | GGLEX("else", else) 27 | GGLEX("for", for) 28 | GGLEX("while", while) 29 | GGLEX("do", do) 30 | GGLEX("switch", switch) 31 | GGLEX("case", case) 32 | GGLEX("return", return) 33 | GGLEX("break", break) 34 | GGLEX("continue", continue) 35 | GGLEX("operator", operator) 36 | GGLEX("nullptr", nullptr) 37 | GGLEX("true", true) 38 | GGLEX("false", false) 39 | GGLEX("static_cast", static_cast) 40 | GGLEX("reinterpret_cast", reinterpret_cast) 41 | GGLEX("const_cast", const_cast) 42 | GGLEX("ckx_cast", ckx_cast) 43 | GGLEX("sizeof", sizeof) 44 | 45 | #ifndef GG2LEX 46 | #define GG2LEX(X, Y) 47 | #endif 48 | 49 | GG2LEX("=", assign) 50 | GG2LEX("+", add) 51 | GG2LEX("-", sub) 52 | GG2LEX("*", mul) 53 | GG2LEX("/", div) 54 | GG2LEX("%", mod) 55 | GG2LEX("++", inc) 56 | GG2LEX("--", dec) 57 | GG2LEX("+=", add_assign) 58 | GG2LEX("-=", sub_assign) 59 | GG2LEX("*=", mul_assign) 60 | GG2LEX("/=", div_assign) 61 | GG2LEX("%=", mod_assign) 62 | GG2LEX("&", bit_and) 63 | GG2LEX("|", bit_or) 64 | GG2LEX("~", bit_not) 65 | GG2LEX("^", bit_xor) 66 | GG2LEX("&&", logic_and) 67 | GG2LEX("||", logic_or) 68 | GG2LEX("!", logic_not) 69 | GG2LEX("^^", logic_xor) 70 | GG2LEX("<", lt) 71 | GG2LEX("==", eq) 72 | GG2LEX(">", gt) 73 | GG2LEX("<=", leq) 74 | GG2LEX(">=", geq) 75 | GG2LEX("!=", neq) 76 | GG2LEX(":", colon) 77 | GG2LEX("::", scope) 78 | GG2LEX(";", semicolon) 79 | GG2LEX(",", comma) 80 | GG2LEX(".", dot) 81 | GG2LEX("{", lbrace) 82 | GG2LEX("}", rbrace) 83 | GG2LEX("[", lbracket) 84 | GG2LEX("]", rbracket) 85 | GG2LEX("[]", arr) 86 | GG2LEX("(", lparen) 87 | GG2LEX(")", rparen) 88 | GG2LEX("?", ques) 89 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_context.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_CONTEXT_HPP 2 | #define CKX_CONTEXT_HPP 3 | 4 | #include "llvm/llvm_inst.hpp" 5 | #include "llvm/llvm_type.hpp" 6 | #include "frontend/sema/ckx_type.hpp" 7 | 8 | namespace ckx 9 | { 10 | 11 | open_class ckx_context 12 | { 13 | enum class context_type : qchar 14 | { 15 | cxt_global, 16 | cxt_func, 17 | cxt_while, 18 | cxt_do_while, 19 | cxt_for, 20 | cxt_if 21 | }; 22 | 23 | context_type const type; 24 | 25 | ckx_context(context_type _type) : type(_type) {} 26 | /* virtual */ ~ckx_context() = default; 27 | 28 | ckx_context(const ckx_context& _another) = delete; 29 | }; 30 | 31 | open_class ckx_global_context final make_use_of ckx_context 32 | { 33 | ckx_global_context() : ckx_context(context_type::cxt_global) {} 34 | ~ckx_global_context() = default; 35 | }; 36 | 37 | open_class ckx_func_context final make_use_of ckx_context 38 | { 39 | ckx_func_type *const func_type; 40 | 41 | ckx_func_context(ckx_func_type *_func_type) : 42 | func_type(_func_type), ckx_context(context_type::cxt_func) {} 43 | ~ckx_func_context() = default; 44 | }; 45 | 46 | open_class ckx_if_context final make_use_of ckx_context 47 | { 48 | faker::llvm_label *const then_label; 49 | faker::llvm_label *const else_label; 50 | faker::llvm_label *const endif_label; 51 | 52 | ckx_if_context(faker::llvm_label *const _then_label, 53 | faker::llvm_label *const _else_label, 54 | faker::llvm_label *const _endif_label) : 55 | ckx_context(context_type::cxt_if), 56 | then_label(_then_label), 57 | else_label(_else_label), 58 | endif_label(_endif_label) {} 59 | ~ckx_if_context() = default; 60 | }; 61 | 62 | open_class ckx_while_context final make_use_of ckx_context 63 | { 64 | faker::llvm_label *const while_label; 65 | faker::llvm_label *const while_body; 66 | faker::llvm_label *const end_while; 67 | 68 | ckx_while_context(faker::llvm_label *const _while_label, 69 | faker::llvm_label *const _while_body, 70 | faker::llvm_label *const _end_while) : 71 | ckx_context(context_type::cxt_while), 72 | while_label(_while_label), 73 | while_body(_while_body), 74 | end_while(_end_while) {} 75 | ~ckx_while_context() = default; 76 | }; 77 | 78 | } // namespace ckx 79 | 80 | #endif // CKX_CONTEXT_HPP 81 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_context_manager.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_CONTEXT_MANAGER_HPP 2 | #define CKX_CONTEXT_MANAGER_HPP 3 | 4 | #include "frontend/sema/ckx_context.hpp" 5 | #include "saber/optional.hpp" 6 | 7 | namespace ckx 8 | { 9 | 10 | class ckx_context_manager 11 | { 12 | friend class func_context_raii; 13 | public: 14 | ckx_context_manager(); 15 | ~ckx_context_manager(); 16 | 17 | ckx_context_manager(const ckx_context_manager&) = delete; 18 | ckx_context_manager(ckx_context_manager&&) = delete; 19 | 20 | ckx_func_context* lookup_func_context(); 21 | ckx_if_context* lookup_if_context(); 22 | ckx_while_context* lookup_while_context(); 23 | 24 | void enter_func_context(ckx_func_type *_func_type); 25 | void exit_func_context(); 26 | 27 | void enter_if_context(ckx_if_context *_if_context); 28 | void exit_if_context(); 29 | 30 | void enter_while_context(ckx_while_context *_while_context); 31 | void exit_while_context(); 32 | 33 | private: 34 | ckx_context::context_type current_context_type_intern() const; 35 | 36 | saber::vector context_chain; 37 | }; 38 | 39 | } // namespace ckx 40 | 41 | #endif // CKX_CONTEXT_MANAGER_HPP 42 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_env_table.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_ENV_TABLE_HPP 20 | #define CKX_ENV_TABLE_HPP 21 | 22 | #include "saber/string_pool.hpp" 23 | #include "saber/vector.hpp" 24 | #include "saber/unordered_map.hpp" 25 | #include "saber/result.hpp" 26 | #include "saber/optional.hpp" 27 | #include "we/defs.hpp" 28 | 29 | #include "frontend/util/ckx_src_rng.hpp" 30 | #include "frontend/sema/ckx_type.hpp" 31 | #include "llvm/llvm_value.hpp" 32 | #include "llvm/llvm_type.hpp" 33 | 34 | namespace ckx 35 | { 36 | 37 | using saber::saber_ptr; 38 | 39 | open_class ckx_env_var_entry 40 | { 41 | ckx_src_rng decl_at; 42 | saber_string_view name; 43 | ckx_type* type; 44 | 45 | /// @note these variables require external components working on it. 46 | faker::llvm_value *llvm_value_bind = nullptr; 47 | 48 | ckx_env_var_entry(ckx_src_rng _decl_at, saber_string_view _name, 49 | ckx_type* _type) : 50 | decl_at(_decl_at), name(_name), type(_type) {} 51 | }; 52 | 53 | open_class ckx_env_type_entry 54 | { 55 | ckx_src_rng decl_at; 56 | saber_string_view name; 57 | ckx_type* type; 58 | 59 | faker::llvm_type llvm_type_bind = saber_string_pool::create_view(""); 60 | 61 | ckx_env_type_entry(ckx_src_rng _decl_at, saber_string_view _name, 62 | ckx_type* _type) : 63 | decl_at(_decl_at), name(_name), type(_type) {} 64 | }; 65 | 66 | open_class ckx_env_func_entry 67 | { 68 | ckx_src_rng decl_at; 69 | saber_string_view name; 70 | ckx_func_type* type; 71 | saber_string_view llvm_name; 72 | 73 | bool defined = false; 74 | 75 | ckx_env_func_entry(ckx_src_rng _decl_at, saber_string_view _name, 76 | ckx_func_type* _type, saber_string_view _llvm_name) : 77 | decl_at(_decl_at), name(_name), 78 | type(_type), llvm_name(_llvm_name) {} 79 | }; 80 | 81 | 82 | class ckx_env 83 | { 84 | public: 85 | open_class err_add_var 86 | { 87 | enum class err_status : qchar { conflict, fail } status; 88 | saber::optional conflict_decl; 89 | err_add_var(err_status _status, 90 | ckx_env_var_entry* _conflict_decl = nullptr) : 91 | status(_status), conflict_decl(_conflict_decl) {} 92 | }; 93 | 94 | open_class err_add_type 95 | { 96 | enum class err_status : qchar{ conflict, fail } status; 97 | saber::optional conflict_decl; 98 | err_add_type(err_status _status, 99 | ckx_env_type_entry* _conflict_decl = nullptr): 100 | status(_status), conflict_decl(_conflict_decl) {} 101 | }; 102 | 103 | open_class result_add_func 104 | { 105 | enum class add_status 106 | { 107 | declare, redeclare, conflict, fail 108 | } 109 | status; 110 | ckx_env_func_entry* added_or_conflict_func; 111 | result_add_func(add_status _status, ckx_env_func_entry *_entry) : 112 | status(_status), added_or_conflict_func(_entry) {} 113 | }; 114 | 115 | ckx_env(ckx_env* _parent = nullptr) : parent(_parent) {} 116 | 117 | ckx_env* get_parent() { return parent; } 118 | 119 | bool lookup(saber_string_view _name); 120 | bool lookup_local(saber_string_view _name); 121 | 122 | ckx_env_var_entry* lookup_var(saber_string_view _name); 123 | ckx_env_type_entry* lookup_type(saber_string_view _name); 124 | saber::vector* lookup_func(saber_string_view _name); 125 | 126 | ckx_env_var_entry* lookup_var_local(saber_string_view _name); 127 | ckx_env_type_entry* lookup_type_local(saber_string_view _name); 128 | saber::vector* 129 | lookup_func_local(saber_string_view _name); 130 | 131 | saber::result 132 | add_var(ckx_src_rng _decl_at, saber_string_view _name, ckx_type* _type); 133 | 134 | saber::result 135 | add_type(ckx_src_rng _decl_at, saber_string_view _name, ckx_type* _type); 136 | 137 | result_add_func add_func(ckx_src_rng _decl_at, 138 | saber_string_view _name, 139 | ckx_func_type *_type); 140 | 141 | private: 142 | /// just for shortening identifiers 143 | using sv = saber_string_view; 144 | using svhash = string_view_hash; 145 | 146 | saber::unordered_map vars; 147 | saber::unordered_map types; 148 | saber::unordered_map, svhash> funcs; 149 | 150 | ckx_env *const parent; 151 | }; 152 | 153 | 154 | } // namespace ckx 155 | 156 | #endif // CKX_ENV_TABLE_HPP 157 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_func_name_mangler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_FUNC_NAME_MANGLER_HPP 2 | #define CKX_FUNC_NAME_MANGLER_HPP 3 | 4 | #include "frontend/sema/ckx_type.hpp" 5 | #include "saber/string_pool.hpp" 6 | 7 | namespace ckx 8 | { 9 | 10 | class ckx_func_name_mangler 11 | { 12 | public: 13 | static saber_string_view std_mangle(saber_string_view _func_name, 14 | ckx_type* _func_type); 15 | static saber_string_view simple_mangle(saber_string_view _func_name); 16 | static saber_string_view prime(saber_string_view _func_name); 17 | }; 18 | 19 | }; 20 | 21 | #endif // CKX_FUNC_NAME_MANGLER_HPP 22 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_llvm_type_builder.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_LLVM_TYPE_BUILDER_HPP 2 | #define CKX_LLVM_TYPE_BUILDER_HPP 3 | 4 | #include "frontend/sema/ckx_type.hpp" 5 | #include "llvm/llvm_type.hpp" 6 | 7 | namespace ckx 8 | { 9 | 10 | class ckx_llvm_type_builder final 11 | { 12 | public: 13 | static faker::llvm_type build(ckx_type *_type); 14 | static saber_string_view full_name_for_struct(saber_string_view _origin); 15 | static saber_string_view full_name_for_variant(saber_string_view _origin); 16 | }; 17 | 18 | } // namespace ckx 19 | 20 | #endif // CKX_LLVM_TYPE_BUILDER_HPP 21 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_sema.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_SEMA_HPP 2 | #define CKX_SEMA_HPP 3 | 4 | #include "frontend/AST/ckx_ast_node.hpp" 5 | #include "frontend/parse/ckx_prelexed_type.hpp" 6 | #include "frontend/util/ckx_src_rng.hpp" 7 | #include "frontend/sema/ckx_type.hpp" 8 | #include "frontend/sema/ckx_env_table.hpp" 9 | #include "frontend/sema/ckx_context_manager.hpp" 10 | #include "frontend/sema/ckx_sema_result.hpp" 11 | #include "llvm/llvm_ir_builder.hpp" 12 | #include "saber/optional.hpp" 13 | 14 | namespace ckx 15 | { 16 | 17 | class ckx_sema_engine 18 | { 19 | public: 20 | ckx_sema_engine() = default; 21 | ~ckx_sema_engine() = default; 22 | 23 | ckx_sema_engine(const ckx_sema_engine&) = delete; 24 | ckx_sema_engine(ckx_sema_engine&&) = delete; 25 | 26 | void visit_translation_unit(ckx_ast_translation_unit *_unit); 27 | void visit_compound_stmt(ckx_ast_compound_stmt *_stmt); 28 | void visit_decl_stmt(ckx_ast_decl_stmt* _decl_stmt); 29 | void visit_record_stmt(ckx_ast_record_stmt* _record_stmt); 30 | void visit_func_stmt(ckx_ast_func_stmt* _func_stmt); 31 | void visit_return_stmt(ckx_ast_return_stmt* _return_stmt); 32 | void visit_if_stmt(ckx_ast_if_stmt* _if_stmt); 33 | void visit_while_stmt(ckx_ast_while_stmt* _while_stmt); 34 | 35 | ckx_expr_result decay_to_rvalue(ckx_expr_result _expr); 36 | 37 | saber::optional 38 | try_implicit_cast(ckx_expr_result _expr, ckx_type *_desired); 39 | saber::optional 40 | try_static_cast(ckx_expr_result _expr, ckx_type *_desired); 41 | saber::optional 42 | try_const_cast(ckx_expr_result _expr, ckx_type *_desired); 43 | saber::optional 44 | try_reinter_cast(ckx_expr_result _expr, ckx_type* _desired); 45 | saber::optional 46 | try_ckx_cast(ckx_expr_result _expr, ckx_type* _desired); 47 | 48 | saber::optional 49 | visit_binary_expr(ckx_ast_binary_expr *_binary_expr); 50 | saber::optional 51 | visit_unary_expr(ckx_ast_unary_expr *_unary_expr); 52 | saber::optional 53 | visit_invoke_expr(ckx_ast_invoke_expr *_invoke_expr); 54 | saber::optional 55 | visit_cast_expr(ckx_ast_cast_expr *_cast_expr); 56 | saber::optional 57 | visit_extract_expr(ckx_ast_extract_expr *_extract_expr); 58 | saber::optional 59 | visit_id_expr(ckx_ast_id_expr *_id_expr); 60 | ckx_expr_result 61 | visit_vi_literal_node(ckx_ast_vi_literal_expr* _literal_expr); 62 | ckx_expr_result 63 | visit_vr_literal_node(ckx_ast_vr_literal_expr* _literal_expr); 64 | ckx_expr_result 65 | visit_vbool_literal_expr(ckx_ast_bool_literal_expr *_literal_expr); 66 | ckx_expr_result 67 | visit_nullptr_expr(ckx_ast_nullptr_expr *_nullptr_expr); 68 | 69 | /// @note for test only. 70 | void test_print(we::we_file_writer& writer); 71 | void test_enter_scope(); 72 | void test_leave_scope(); 73 | 74 | private: 75 | void visit_global_decl(ckx_ast_decl_stmt *_decl_stmt); 76 | void visit_local_decl(ckx_ast_decl_stmt *_decl_stmt); 77 | void visit_struct_decl(ckx_ast_record_stmt *_struct_stmt); 78 | void visit_variant_decl(ckx_ast_record_stmt *_variant_stmt); 79 | void visit_func_decl(ckx_ast_func_stmt *_func_stmt); 80 | void visit_func_def(ckx_ast_func_stmt *_func_stmt); 81 | 82 | open_class function_header_info 83 | { 84 | ckx_func_type *func_type; 85 | saber::vector param_names; 86 | 87 | function_header_info( 88 | ckx_func_type *_func_type, 89 | saber::vector &&_param_names) : 90 | func_type(_func_type), 91 | param_names(saber::move(_param_names)) {} 92 | 93 | function_header_info(function_header_info&& _another) : 94 | function_header_info(_another.func_type, 95 | saber::move(_another.param_names)) 96 | { _another.func_type = nullptr; } 97 | 98 | function_header_info(const function_header_info&) = delete; 99 | }; 100 | 101 | ckx_env::result_add_func 102 | try_register_func(function_header_info&& _func_header_info); 103 | saber::optional 104 | visit_function_header(ckx_ast_func_stmt *_func_stmt); 105 | saber::optional 106 | visit_assign(ckx_expr_result _dest, ckx_expr_result _from); 107 | saber::optional 108 | visit_add(ckx_expr_result _expr1, ckx_expr_result _expr2); 109 | saber::optional 110 | visit_sub(ckx_expr_result _expr1, ckx_expr_result _expr2); 111 | saber::optional 112 | visit_mul(ckx_expr_result _expr1, ckx_expr_result _expr2); 113 | saber::optional 114 | visit_div(ckx_expr_result _expr1, ckx_expr_result _expr2); 115 | template 116 | saber::optional 117 | visit_numeric_calc(ckx_expr_result _expr1, ckx_expr_result _expr2, 118 | ActionOnFloat&& _action_on_float, 119 | ActionOnInt&& _action_on_int, 120 | ActionOnUInt&& _action_on_uint); 121 | template 122 | saber::optional 123 | visit_comparsion(ckx_expr_result _expr1, ckx_expr_result _expr2, 124 | ActionOnFloat&& _action_on_float, 125 | ActionOnInt&& _action_on_int, 126 | ActionOnUInt&& _action_on_uint); 127 | saber::optional 128 | visit_ptroffset(ckx_expr_result _expr1, ckx_expr_result _expr2, bool _add); 129 | saber::optional 130 | visit_ptrdiff(ckx_expr_result _expr1, ckx_expr_result _expr2); 131 | saber::optional 132 | visit_addressof_expr(ckx_ast_unary_expr *_unary_expr); 133 | saber::optional 134 | visit_deref_expr(ckx_ast_unary_expr *_unary_expr); 135 | 136 | quint64 calculate_disagreements(const saber::vector& _args, 137 | const saber::vector& _params); 138 | 139 | ckx_type* 140 | re_lex_type(const ckx_prelexed_type &_prelexed_type); 141 | 142 | quint64 var_name_mangle_count() { return ++vname_mangle_count; } 143 | 144 | class enter_func_protection_raii 145 | { 146 | public: 147 | enter_func_protection_raii(ckx_sema_engine& _sema, 148 | ckx_func_type* _func_type); 149 | ~enter_func_protection_raii(); 150 | private: 151 | ckx_sema_engine& sema; 152 | }; 153 | 154 | class enter_if_protection_raii 155 | { 156 | public: 157 | enter_if_protection_raii(ckx_sema_engine& _sema, 158 | ckx_if_context *_context); 159 | ~enter_if_protection_raii(); 160 | private: 161 | ckx_sema_engine& sema; 162 | ckx_if_context *context; 163 | }; 164 | 165 | class enter_while_protection_raii 166 | { 167 | public: 168 | enter_while_protection_raii(ckx_sema_engine& _sema, 169 | ckx_while_context *_context); 170 | ~enter_while_protection_raii(); 171 | private: 172 | ckx_sema_engine& sema; 173 | ckx_while_context *context; 174 | }; 175 | 176 | bool is_in_func(); 177 | void enter_scope(); 178 | void leave_scope(); 179 | void error() { std::printf("fuck!\n"); abort(); } 180 | 181 | ckx_env root_env; 182 | ckx_env *current_env = &root_env; 183 | 184 | ckx_context_manager context_manager; 185 | 186 | bool in_func = false; 187 | quint64 vname_mangle_count = 0; 188 | 189 | faker::llvm_ir_builder builder; 190 | }; 191 | 192 | } // namespace ckx 193 | 194 | #endif // CKX_SEMA_HPP 195 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_sema_fwd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_SEMA_FWD_HPP 2 | #define CKX_SEMA_FWD_HPP 3 | 4 | namespace ckx 5 | { 6 | 7 | class ckx_sema_engine; 8 | 9 | } // namespace ckx 10 | 11 | #endif // CKX_SEMA_FWD_HPP 12 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_sema_result.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_SEMA_RESULT_HPP 2 | #define CKX_SEMA_RESULT_HPP 3 | 4 | #include "llvm/llvm_ir_builder.hpp" 5 | #include "frontend/sema/ckx_env_table.hpp" 6 | 7 | namespace ckx 8 | { 9 | 10 | open_class ckx_expr_result 11 | { 12 | enum class value_category : qchar 13 | { 14 | lvalue, 15 | xvalue, /// @note reserved for further development 16 | prvalue 17 | }; 18 | 19 | ckx_type *const type; 20 | value_category const categ; 21 | faker::llvm_value *const llvm_value_bind; 22 | 23 | ckx_expr_result(ckx_type* _type, value_category _categ, 24 | faker::llvm_value* _llvm_value_bind) : 25 | type(_type), categ(_categ), 26 | llvm_value_bind(_llvm_value_bind) {} 27 | }; 28 | 29 | } // namespace ckx 30 | 31 | #endif // CKX_SEMA_RESULT_HPP 32 | -------------------------------------------------------------------------------- /include/frontend/sema/ckx_sema_result_fwd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_SEMA_RESULT_FWD_HPP 2 | #define CKX_SEMA_RESULT_FWD_HPP 3 | 4 | namespace ckx 5 | { 6 | 7 | struct ckx_expr_result; 8 | 9 | }; 10 | 11 | #endif // CKX_SEMA_RESULT_FWD_HPP 12 | -------------------------------------------------------------------------------- /include/frontend/util/ckx_error.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef CKX_ERROR_HPP 20 | #define CKX_ERROR_HPP 21 | 22 | #include "we/defs.hpp" 23 | #include "saber/string_pool.hpp" 24 | #include "saber/memory.hpp" 25 | 26 | namespace ckx 27 | { 28 | 29 | class ckx_error 30 | { 31 | public: 32 | ckx_error(const qcoord& _pos, saber_string_view _desc) : 33 | pos(_pos), desc(_desc) {} 34 | 35 | qcoord pos; 36 | saber_string_view desc; 37 | }; 38 | 39 | } 40 | #endif // CKX_ERROR_HPP 41 | -------------------------------------------------------------------------------- /include/frontend/util/ckx_src_rng.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CKX_SRC_RNG_HPP 2 | #define CKX_SRC_RNG_HPP 3 | 4 | #include "we/defs.hpp" 5 | 6 | namespace ckx 7 | { 8 | 9 | open_class ckx_src_rng 10 | { 11 | const quint16 begin_line; 12 | const quint16 begin_col; 13 | const quint16 end_line; 14 | const quint16 end_col; 15 | 16 | ckx_src_rng(quint16 _begin_line, quint16 _begin_col, 17 | quint16 _end_line, quint16 _end_col) 18 | : begin_line(_begin_line), begin_col(_begin_col), 19 | end_line(_end_line), end_col(_end_col) {} 20 | 21 | ckx_src_rng(qcoord _begin_coord, qcoord _end_coord) 22 | : ckx_src_rng(_begin_coord.line, _begin_coord.col, 23 | _end_coord.line, _end_coord.col) {} 24 | 25 | static ckx_src_rng concat(ckx_src_rng r1, ckx_src_rng r2) 26 | { 27 | C8ASSERT(r2.end_line == r1.end_line ? 28 | r2.end_col >= r1.end_col : r2.end_line > r1.end_line); 29 | return ckx_src_rng(r1.begin_line, r1.begin_col, 30 | r2.end_line, r2.end_col); 31 | } 32 | 33 | static ckx_src_rng empty() 34 | { 35 | return ckx_src_rng(-1, -1, -1, -1); 36 | } 37 | }; 38 | 39 | } // namespace ckx 40 | 41 | #endif // CKX_SRC_RNG_HPP 42 | -------------------------------------------------------------------------------- /include/llvm/llvm_implicit_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_IMPLICIT_LIST_HPP 21 | #define LLVM_IMPLICIT_LIST_HPP 22 | 23 | namespace faker 24 | { 25 | 26 | class llvm_implicit_list_node 27 | { 28 | public: 29 | llvm_implicit_list_node() {} 30 | ~llvm_implicit_list_node() {} 31 | 32 | llvm_implicit_list_node* get_prev() noexcept { return prev; } 33 | llvm_implicit_list_node* get_next() noexcept { return next; } 34 | 35 | void insert_self_before(llvm_implicit_list_node *_another) noexcept 36 | { 37 | this->prev = _another->prev; 38 | _another->next = this->next; 39 | this->next = _another; 40 | _another->prev = this; 41 | } 42 | 43 | void insert_self_after(llvm_implicit_list_node* _another) noexcept 44 | { 45 | this->next = _another->next; 46 | _another->prev = this->prev; 47 | this->prev = _another; 48 | _another->next = this; 49 | } 50 | 51 | private: 52 | llvm_implicit_list_node *prev = nullptr, *next = nullptr; 53 | }; 54 | 55 | } // namespace faker 56 | 57 | #endif // LLVM_IMPLICIT_LIST_HPP 58 | -------------------------------------------------------------------------------- /include/llvm/llvm_inst.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_INST_HPP 21 | #define LLVM_INST_HPP 22 | 23 | #include "we/defs.hpp" 24 | #include "we/file_writer.hpp" 25 | #include "saber/string_pool.hpp" 26 | #include "llvm/llvm_implicit_list.hpp" 27 | 28 | namespace faker 29 | { 30 | 31 | interface llvm_instruction make_use_of llvm_implicit_list_node 32 | { 33 | public: 34 | llvm_instruction() = default; 35 | virtual ~llvm_instruction() = 0; 36 | 37 | /// @note Yes. We did this on purpose. 38 | llvm_instruction* get_prev() noexcept 39 | { 40 | return static_cast( 41 | llvm_implicit_list_node::get_prev()); 42 | } 43 | 44 | llvm_instruction* get_next() noexcept 45 | { 46 | return static_cast( 47 | llvm_implicit_list_node::get_next()); 48 | } 49 | 50 | virtual void pretty_print(we::we_file_writer& writer) = 0; 51 | }; 52 | 53 | class llvm_func_decl; 54 | class llvm_func_def; 55 | class llvm_global_constant; 56 | class llvm_global_variable; 57 | class llvm_new_type; 58 | 59 | class llvm_label; 60 | class llvm_ret_instruction; 61 | class llvm_call_instruction; 62 | class llvm_br_instruction; 63 | class llvm_condbr_instruction; 64 | class llvm_phi_instruction; 65 | class llvm_binary_instruction; 66 | class llvm_cast_instruction; 67 | class llvm_cmp_instruction; 68 | class llvm_alloca_instruction; 69 | class llvm_load_instruction; 70 | class llvm_store_instruction; 71 | class llvm_extractvalue_instruction; 72 | class llvm_getelementptr_instruction; 73 | class llvm_getelementptr2_instruction; 74 | 75 | class llvm_func_attrs 76 | { 77 | public: 78 | enum inline_type 79 | { 80 | it_default, 81 | it_defaultinline, 82 | it_noinline, 83 | it_always, 84 | }; 85 | 86 | llvm_func_attrs(bool _nounwind, inline_type _inlining) : 87 | nounwind(_nounwind), inlining(_inlining) {} 88 | 89 | ~llvm_func_attrs() = default; 90 | 91 | void pretty_print(we::we_file_writer &_writer); 92 | 93 | private: 94 | bool nounwind : 1; 95 | unsigned inlining : 2; 96 | }; 97 | 98 | } // namespace faker 99 | 100 | #endif // LLVM_INST_HPP 101 | -------------------------------------------------------------------------------- /include/llvm/llvm_ir_builder.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_IR_BUILDER_HPP 21 | #define LLVM_IR_BUILDER_HPP 22 | 23 | #include "llvm/llvm_inst.hpp" 24 | #include "llvm/llvm_type.hpp" 25 | #include "llvm/llvm_value.hpp" 26 | 27 | #include "saber/vector.hpp" 28 | #include "saber/string_pool.hpp" 29 | 30 | namespace faker 31 | { 32 | 33 | namespace detail 34 | { 35 | class llvm_ir_builder_impl; 36 | } // namespace detail 37 | 38 | 39 | class llvm_ir_builder final 40 | { 41 | public: 42 | llvm_ir_builder(); 43 | ~llvm_ir_builder(); 44 | llvm_ir_builder(const llvm_ir_builder&) = delete; 45 | llvm_ir_builder(llvm_ir_builder&&) = delete; 46 | 47 | llvm_ir_builder& operator= (const llvm_ir_builder&) = delete; 48 | llvm_ir_builder& operator= (llvm_ir_builder&&) = delete; 49 | 50 | void pretty_print(we::we_file_writer& _writer); 51 | 52 | void create_n_enter_func(llvm_type _return_type, saber_string_view _name, 53 | saber::vector &&_param_type_list, 54 | saber::vector _param_name_list, 55 | llvm_func_attrs _attrs); 56 | void leave_func(); 57 | 58 | llvm_instruction* get_insert_point(); 59 | void set_insert_after(llvm_instruction* _instruction); 60 | 61 | /// @fn control flows 62 | llvm_instruction* create_func_decl( 63 | llvm_type _return_type, saber_string_view _name, 64 | saber::vector &&_param_type_list, 65 | saber::vector _param_name_list, 66 | llvm_func_attrs _attrs); 67 | llvm_instruction* create_return_void(); 68 | llvm_instruction* create_return(llvm_type _type, llvm_value* _value); 69 | llvm_instruction* create_branch(llvm_label *_label); 70 | llvm_instruction* create_cond_branch(llvm_value *_cond, 71 | llvm_label *_true_label, 72 | llvm_label *_false_label); 73 | llvm_instruction* create_phi(llvm_value* _result, llvm_type _type, 74 | llvm_label *_label1, llvm_value *_val1, 75 | llvm_label *_label2, llvm_value *_val2); 76 | llvm_instruction* create_call(llvm_value* _result, llvm_type _type, 77 | saber_string_view _func_name, 78 | saber::vector &&_types, 79 | saber::vector &&_args); 80 | llvm_label* create_label(saber_string_view _name); 81 | llvm_label* create_temporary_label(); 82 | 83 | COMMENT(BEGIN_BLOCK) 84 | 85 | /// @attention We are using macro to write function declarations! 86 | /// LLVM did so, so we decides to copy its idea! 87 | /// @fn binary operations, especially calculations 88 | # define BINOP(OPCODE) \ 89 | llvm_instruction* create_##OPCODE(llvm_value *_result, llvm_type _type,\ 90 | llvm_value* _lhs, llvm_value *_rhs); 91 | /// @fn cast operations 92 | # define CASTOP(OPCODE) \ 93 | llvm_instruction* create_##OPCODE(llvm_value *_result, llvm_type _src_type,\ 94 | llvm_value *_src, llvm_type _dest_type); 95 | 96 | /// @fn comparsions 97 | # define CMPOP(OPCODE) \ 98 | llvm_instruction* create_##OPCODE(llvm_value *_result, llvm_type _type,\ 99 | llvm_value *_val1, llvm_value *_val2); 100 | 101 | # include "llvm/opdef.hpp" 102 | # undef BINOP 103 | # undef CASTOP 104 | # undef CMPOP 105 | 106 | COMMENT(END_BLOCK) 107 | 108 | /// @fn memory accessing operations 109 | llvm_instruction* create_alloca(llvm_value *_result, llvm_type _type, 110 | quint32 _array_size); 111 | llvm_instruction* create_load(llvm_value *_result, llvm_type _type, 112 | llvm_value *_ptr); 113 | llvm_instruction* create_store(llvm_type _type, 114 | llvm_value *_src, llvm_value *_result); 115 | llvm_instruction* create_extractvalue(llvm_value *_result, 116 | llvm_type _type, 117 | llvm_value *_value, 118 | llvm_value *_idx); 119 | llvm_instruction* create_getelementptr(llvm_value *_result, 120 | llvm_type _type, llvm_value *_ptr, 121 | llvm_type _ty, llvm_value *_idx); 122 | llvm_instruction* create_getelementptr2(llvm_value *_result, 123 | llvm_type _type, llvm_value *_ptr, 124 | llvm_type _ty1, llvm_value *_idx1, 125 | llvm_type _ty2, llvm_value *_idx2); 126 | llvm_instruction* create_udt(saber_string_view _name, 127 | saber::vector&& _fields); 128 | 129 | /// @fn functions dealing with values 130 | llvm_value *create_string_constant(saber_string_view _str); 131 | llvm_value *create_signed_constant(qint64 _i); 132 | llvm_value *create_unsigned_constant(quint64 _u); 133 | llvm_value *create_floating_constant(qreal _r); 134 | llvm_value *create_bool_constant(bool _b); 135 | llvm_value *create_null(); 136 | 137 | 138 | llvm_value *create_temporary_var(); 139 | llvm_value *create_named_var(saber_string_view _name); 140 | 141 | private: 142 | detail::llvm_ir_builder_impl* impl; 143 | }; 144 | 145 | } // namespace faker 146 | 147 | #endif // LLVM_IR_BUILDER_HPP 148 | -------------------------------------------------------------------------------- /include/llvm/llvm_ir_builder_impl.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_IR_BUILDER_IMPL_HPP 21 | #define LLVM_IR_BUILDER_IMPL_HPP 22 | 23 | #include "saber/vector.hpp" 24 | #include "saber/list.hpp" 25 | #include "llvm/llvm_inst_detail.hpp" 26 | #include "llvm/llvm_value.hpp" 27 | #include "llvm/llvm_type.hpp" 28 | 29 | namespace faker 30 | { 31 | namespace detail 32 | { 33 | 34 | class llvm_ir_builder_impl final 35 | { 36 | public: 37 | llvm_ir_builder_impl() = default; 38 | ~llvm_ir_builder_impl(); 39 | 40 | llvm_ir_builder_impl(const llvm_ir_builder_impl&) = delete; 41 | llvm_ir_builder_impl(llvm_ir_builder_impl&&) = delete; 42 | llvm_ir_builder_impl& operator= (const llvm_ir_builder_impl&) = delete; 43 | llvm_ir_builder_impl& operator= (llvm_ir_builder_impl&&) = delete; 44 | 45 | void pretty_print(we::we_file_writer& _writer); 46 | 47 | void create_n_enter_func(llvm_type _return_type, saber_string_view _name, 48 | saber::vector&& _param_type_list, 49 | saber::vector _param_name_list, 50 | llvm_func_attrs _attrs); 51 | void leave_func(); 52 | 53 | llvm_instruction* get_insert_point(); 54 | void set_insert_after(llvm_instruction* _instruction); 55 | 56 | /// @note all `create` functions here mean `create and insert after current` 57 | llvm_func_decl* create_func_decl( 58 | llvm_type _return_type, saber_string_view _name, 59 | saber::vector&& _param_type_list, 60 | saber::vector _param_name_list, 61 | llvm_func_attrs _attrs); 62 | 63 | llvm_ret_instruction* create_return(llvm_type _type, llvm_value* _value); 64 | 65 | llvm_br_instruction* create_branch(llvm_label* _label); 66 | 67 | llvm_condbr_instruction* create_cond_branch(llvm_value *_cond, 68 | llvm_label *_true_label, 69 | llvm_label *_false_label); 70 | 71 | llvm_phi_instruction* create_phi(llvm_value *_result, llvm_type _type, 72 | llvm_label *_label1, llvm_value *_val1, 73 | llvm_label *_label2, llvm_value *_val2); 74 | 75 | llvm_call_instruction* create_call(llvm_value* _result, llvm_type _type, 76 | saber_string_view _func_name, saber::vector &&_types, 77 | saber::vector &&_args); 78 | 79 | llvm_label* create_label(saber_string_view _name); 80 | llvm_label* create_temporary_label(); 81 | 82 | llvm_binary_instruction* create_binary_instruction( 83 | llvm_value* _result, 84 | llvm_binary_instruction::operator_type _op, 85 | llvm_type _type, 86 | llvm_value* _lhs, llvm_value* _rhs); 87 | 88 | llvm_cast_instruction* create_cast_instruction( 89 | llvm_value* _result, llvm_cast_instruction::operator_type _op, 90 | llvm_type _src_type, llvm_value *_value, llvm_type _dest_type); 91 | 92 | llvm_cmp_instruction* create_cmp_instruction( 93 | llvm_value* _result, llvm_cmp_instruction::comparsion_type _op, 94 | llvm_type _compared_type, llvm_value *_val1, llvm_value *_val2); 95 | 96 | llvm_alloca_instruction* create_alloca(llvm_value *_result, 97 | llvm_type _yield_type, 98 | quint32 _num_elems = 1); 99 | 100 | llvm_load_instruction* create_load(llvm_value *_result, 101 | llvm_type _yield_type, 102 | llvm_value *_ptr); 103 | 104 | llvm_store_instruction* create_store(llvm_type _src_type, 105 | llvm_value *_src, 106 | llvm_value *_result); 107 | 108 | llvm_extractvalue_instruction* create_extractvalue(llvm_value *_result, 109 | llvm_type _type, 110 | llvm_value *_value, 111 | llvm_value *_idx); 112 | 113 | llvm_getelementptr_instruction* create_getelementptr(llvm_value *_result, 114 | llvm_type _base_type, 115 | llvm_value* _ptr, 116 | llvm_type _ty, 117 | llvm_value* _idx); 118 | llvm_getelementptr2_instruction *create_getelementptr2(llvm_value *_result, 119 | llvm_type _base_type, 120 | llvm_value* _ptr, 121 | llvm_type _ty1, 122 | llvm_value* _idx1, 123 | llvm_type _ty2, 124 | llvm_value* _idx2); 125 | 126 | llvm_new_type* create_udt(saber_string_view _type_name, 127 | saber::vector&& _fields); 128 | 129 | llvm_value* create_string_constant(saber_string_view _str); 130 | llvm_value* create_signed_constant(qint64 _i); 131 | llvm_value* create_unsigned_constant(quint64 _u); 132 | llvm_value* create_floating_constant(qreal _r); 133 | llvm_value* create_bool_constant(bool _b); 134 | llvm_value* create_null(); 135 | 136 | llvm_value* create_temporary_var(); 137 | llvm_value* create_named_var(saber_string_view _name); 138 | 139 | private: 140 | open_class llvm_function_block /// `Type rich programming`? 141 | { 142 | llvm_function_block() = delete; 143 | llvm_function_block(const llvm_function_block&) = delete; 144 | llvm_function_block(llvm_function_block&&) = delete; 145 | 146 | llvm_function_block(llvm_func_def* _fndef) : fndef(_fndef) {} 147 | ~llvm_function_block() { delete fndef; } 148 | llvm_func_def* fndef; 149 | }; 150 | 151 | template 152 | InstructionPtrType insert_after_current(InstructionPtrType _instruction) 153 | { 154 | _instruction->insert_self_after(cur_insertion_point); 155 | cur_insertion_point = _instruction; 156 | return _instruction; 157 | } 158 | 159 | llvm_value* insert_into_table(llvm_value* _value) 160 | { 161 | value_table.push_back(_value); 162 | return _value; 163 | } 164 | 165 | saber::vector functions; 166 | llvm_implicit_list_node global_head_node; 167 | llvm_implicit_list_node *stashed_global_insertion_point = nullptr; 168 | llvm_implicit_list_node *cur_insertion_point = &global_head_node; 169 | 170 | quint64 local_temp_var_counter = 0; 171 | quint64 local_temp_label_counter = 0; 172 | 173 | saber::vector value_table; 174 | }; 175 | 176 | } // namespace detail 177 | } // namespace faker 178 | 179 | #endif // LLVM_IR_BUILDER_IMPL_HPP 180 | -------------------------------------------------------------------------------- /include/llvm/llvm_type.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LLVM_TYPE_HPP 2 | #define LLVM_TYPE_HPP 3 | 4 | #include "saber/string_pool.hpp" 5 | 6 | namespace faker 7 | { 8 | 9 | /// @brief Don't be scared. We did this on purpose. 10 | using llvm_type = saber_string_view; 11 | 12 | } // namespace faker 13 | 14 | #endif // LLVM_TYPE_HPP 15 | -------------------------------------------------------------------------------- /include/llvm/llvm_value.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_VALUE_HPP 21 | #define LLVM_VALUE_HPP 22 | 23 | #include "we/defs.hpp" 24 | #include "saber/string_pool.hpp" 25 | 26 | namespace faker 27 | { 28 | 29 | interface llvm_value 30 | { 31 | public: 32 | llvm_value() = default; 33 | virtual ~llvm_value() = 0; 34 | virtual saber_string_view to_string() = 0; 35 | }; 36 | 37 | } // namespace faker 38 | 39 | #endif // LLVM_VALUE_HPP 40 | -------------------------------------------------------------------------------- /include/llvm/llvm_value_detail.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #ifndef LLVM_VALUE_DETAIL_HPP 21 | #define LLVM_VALUE_DETAIL_HPP 22 | 23 | #include "llvm/llvm_value.hpp" 24 | 25 | namespace faker 26 | { 27 | 28 | class llvm_constant final implements llvm_value 29 | { 30 | public: 31 | llvm_constant() = delete; 32 | llvm_constant(const llvm_constant& _another) = delete; 33 | 34 | llvm_constant(qint64 _val); 35 | llvm_constant(quint64 _val); 36 | llvm_constant(qreal _val); 37 | llvm_constant(decltype(nullptr)); 38 | llvm_constant(bool _val); 39 | llvm_constant(saber_string_view _val); 40 | ~llvm_constant() override final = default; 41 | 42 | saber_string_view to_string() override final; 43 | 44 | private: 45 | enum class constant_type { ct_int, ct_uint, ct_real, ct_nullptr, 46 | ct_bool, ct_string } type; 47 | variant { qint64 i; quint64 u; qreal r; bool b; } v; 48 | saber_string_view str = saber_string_pool::create_view(""); 49 | }; 50 | 51 | 52 | class llvm_global final implements llvm_value 53 | { 54 | public: 55 | llvm_global() = delete; 56 | llvm_global(const llvm_global& _another) = delete; 57 | llvm_global(saber_string_view _name); 58 | ~llvm_global() override final = default; 59 | 60 | saber_string_view to_string() override final; 61 | 62 | private: 63 | saber_string_view name; 64 | }; 65 | 66 | 67 | class llvm_variable final implements llvm_value 68 | { 69 | public: 70 | llvm_variable() = delete; 71 | llvm_variable(const llvm_variable& _another) = delete; 72 | llvm_variable(saber_string_view _name); 73 | ~llvm_variable() override final = default; 74 | 75 | saber_string_view to_string() override final; 76 | 77 | private: 78 | saber_string_view name; 79 | }; 80 | 81 | class llvm_null final implements llvm_value 82 | { 83 | public: 84 | llvm_null() = default; 85 | llvm_null(const llvm_null&) = delete; 86 | ~llvm_null() override final = default; 87 | 88 | saber_string_view to_string() override final; 89 | }; 90 | 91 | } // namespace faker 92 | 93 | #endif // LLVM_VALUE_DETAIL_HPP 94 | -------------------------------------------------------------------------------- /include/llvm/opdef.hpp: -------------------------------------------------------------------------------- 1 |  2 | #ifndef BINOP 3 | #define BINOP(OP_NAME) 4 | #endif 5 | 6 | 7 | #ifndef CASTOP 8 | #define CASTOP(OP_NAME) 9 | #endif 10 | 11 | 12 | #ifndef CMPOP 13 | #define CMPOP(OP_NAME) 14 | #endif 15 | 16 | 17 | BINOP(add) 18 | BINOP(sub) 19 | BINOP(mul) 20 | BINOP(sdiv) 21 | BINOP(udiv) 22 | BINOP(srem) 23 | BINOP(urem) 24 | BINOP(fadd) 25 | BINOP(fsub) 26 | BINOP(fmul) 27 | BINOP(fdiv) 28 | BINOP(shl) 29 | BINOP(lshr) 30 | BINOP(ashr) 31 | BINOP(and) 32 | BINOP(or) 33 | BINOP(xor) 34 | 35 | 36 | CASTOP(trunc) 37 | CASTOP(fptrunc) 38 | CASTOP(zext) 39 | CASTOP(sext) 40 | CASTOP(fpext) 41 | CASTOP(fptosi) 42 | CASTOP(sitofp) 43 | CASTOP(fptoui) 44 | CASTOP(uitofp) 45 | CASTOP(inttoptr) 46 | CASTOP(ptrtoint) 47 | CASTOP(bitcast) 48 | 49 | 50 | CMPOP(icmp_ne) 51 | CMPOP(icmp_eq) 52 | CMPOP(icmp_sgt) 53 | CMPOP(icmp_sge) 54 | CMPOP(icmp_slt) 55 | CMPOP(icmp_sle) 56 | CMPOP(icmp_ugt) 57 | CMPOP(icmp_uge) 58 | CMPOP(icmp_ult) 59 | CMPOP(icmp_ule) 60 | CMPOP(fcmp_oeq) 61 | CMPOP(fcmp_one) 62 | CMPOP(fcmp_ogt) 63 | CMPOP(fcmp_oge) 64 | CMPOP(fcmp_olt) 65 | CMPOP(fcmp_ole) 66 | -------------------------------------------------------------------------------- /include/saber/algorithm.hpp: -------------------------------------------------------------------------------- 1 | // ///////////////////////////////////////////////////////////////////////// // 2 | 3 | // たとえば途切れた空が - 你若看见了 // 4 | // 見えたなら - 那断裂的苍空 // 5 | // 震える僕の声が聞こえるのなら - 你若听见了我颤抖的歌声 // 6 | // バラバラに砕けるほど - 纵使被击成粉碎 // 7 | // 舞い上がれ - 亦要向苍空飞舞 // 8 | // 引き裂かれた - 支离破碎的记忆 // 9 | // 記憶の果敢なきツバサ - 无尽飘飞的羽翼 // 10 | // あの日語り合ったこと - 那一天的促膝长谈 // 11 | // いつも笑い合えたこと - 昔日里的谈笑风生 // 12 | // よみがえる日まで - 在这一切复苏之前 // 13 | // 立ち上がるだけ - 唯有再度振奋 // 14 | 15 | // 壊してもっともっと僕を感じて - 破坏吧 更多地 更多地感受我 // 16 | // そこにそこに君はいますか - 那里 那里 是否你就在那里 // 17 | // 戦場に咲く命よ燃えろ燃えろ - 战场上绽放的生命 燃烧吧 燃烧吧 // 18 | // 殺していっそいっそ - 索性 索性就此扼杀一切 // 19 | // 朽ち果てるなら - 如果万物终将走向湮灭 // 20 | // たぎれたぎれ破滅の果てに - 重拾心中的沸腾 在那破灭的尽头 // 21 | // 奇跡を呼び覚ませ - 唤醒奇迹 // 22 | // 閉ざされた空へ - 飞向那片封锁的苍空 // 23 | 24 | // 飛び交う無数の感覚のなかで - 纷飞交错的无数感受之中 // 25 | // 本当の自分さえも失くしてしまう - 连真正的自我也迷失不再 // 26 | // 見えない不安を集中砲火に - 集中火力对抗隐形的不安 // 27 | // 勝ち残るのは弱さ認める強さ - 敢于承认自身的弱小 方能赢到最后 // 28 | // もしも僕じゃなかったら - 如若我不是我 // 29 | // もしも君じゃなかったら - 你不是你 // 30 | // こんな気持ちさえ - 就连这份心情 // 31 | // 知らずにいたね - 我也不曾知晓 // 32 | // 切り裂けもっともっと - 撕裂苍空 竭力飞向 // 33 | // 正義の闇へ - 那正义的黑暗 // 34 | 35 | // はしれはしれ灰になるまで - 奔跑吧 奔跑吧 直至燃为灰烬 // 36 | // 理屈を捨てて心で - 舍弃理性 // 37 | // 吠えろ吠えろ - 发自真心地嘶吼吧 咆哮吧 // 38 | // 断ち切れやがてやがて - 斩断阻隔 // 39 | // 生まれる銀河に - 在那终获重生的银河之处 // 40 | // 君が君が居てくれるなら - 只要你 你还在我的身边 // 41 | // 僕らのかがやきは - 我们的这份光芒 // 42 | // 無敵にもなれる - 定将无人能敌 // 43 | 44 | // 右にならえと - 只要随波逐流 // 45 | // 誰もが今日を生きてる - 就能幸免于难 // 46 | // もどかしさに理由もないまま - 心浮气躁 缘由依然无从得知 // 47 | // 死んだみたいに生きてくよりも - 与其行尸走肉般苟且偷生 // 48 | // 赤い血を流し牙を剥け - 不如挥洒赤血大放异彩 // 49 | // それが僕が君が生きてる証明 - 那是我 也是你的生存证明 // 50 | 51 | // 壊してもっともっと僕を感じて - 破坏吧 更多地 更多地感受我 // 52 | // そこにそこに君はいますか - 那里 那里 是否你就在那里 // 53 | // 戦場に咲く命よ燃えろ燃えろ - 战场上绽放的生命 燃烧吧 燃烧吧 // 54 | // 殺していっそいっそ - 索性 索性就此扼杀一切 // 55 | // 朽ち果てるなら - 如果万物终将走向湮灭 // 56 | // たぎれたぎれ破滅の果てに - 重拾心中的沸腾 在那破灭的尽头 // 57 | // 奇跡を呼び覚ませ - 唤醒奇迹 // 58 | // 閉ざされた空へ - 飞向那片封锁的苍空 // 59 | // 60 | // ///////////////////////////////////////////////////////////////////////// // 61 | 62 | #ifdef _MSC_VER 63 | #pragma once 64 | #endif 65 | 66 | #ifndef ALGORITHM_HPP 67 | #define ALGORITHM_HPP 68 | 69 | #include "saber/memory.hpp" 70 | #include "saber/iterator.hpp" 71 | #include "saber/saber_traits.hpp" 72 | 73 | namespace saber 74 | { 75 | 76 | template 77 | OutputIterator 78 | copy(InputIterator _first, InputIterator _last, OutputIterator _d_first) 79 | { 80 | static_assert(traits::is_input_iterator::value, 81 | C8_STAT__TEMPLATE_ARG__ITER__NOT_INPUT_ITERATOR); 82 | static_assert(traits::is_output_iterator::value, 83 | C8_STAT__TEMPLATE_ARG__ITER__NOT_OUTPUT_ITERATOR); 84 | 85 | while (_first != _last) 86 | { 87 | *_d_first++ = *_first++; 88 | } 89 | 90 | return _d_first; 91 | } 92 | 93 | template 94 | OutputIterator 95 | copy_if(InputIterator _first, 96 | InputIterator _last, 97 | OutputIterator _d_first, 98 | Predicator _pred) 99 | { 100 | static_assert(traits::is_input_iterator::value, 101 | C8_STAT__TEMPLATE_ARG__ITER__NOT_INPUT_ITERATOR); 102 | static_assert(traits::is_output_iterator::value, 103 | C8_STAT__TEMPLATE_ARG__ITER__NOT_OUTPUT_ITERATOR); 104 | 105 | while (_first != _last) 106 | { 107 | if (_pred(*_first)) 108 | { 109 | *_d_first++ = *_first; 110 | } 111 | _first++; 112 | } 113 | return _d_first; 114 | } 115 | 116 | template 117 | OutputIterator 118 | copy_n(InputIterator _first, Size _count, OutputIterator _d_first) 119 | { 120 | if (_count > 0) 121 | { 122 | *_d_first++ = *_first; 123 | for (Size i = 1; i < _count; ++i) 124 | { 125 | *_d_first++ = *++_first; 126 | } 127 | } 128 | return _d_first; 129 | } 130 | 131 | template 132 | OutputIterator 133 | reverse_copy(BidirectionalIterator _first, 134 | BidirectionalIterator _last, 135 | OutputIterator _d_first) 136 | { 137 | while (_first != _last) 138 | { 139 | --_last; 140 | *_d_first = *_last; 141 | ++_d_first; 142 | } 143 | return _d_first; 144 | } 145 | 146 | template 147 | void 148 | fill(ForwardIterator _first, ForwardIterator _last, const T& _value) 149 | { 150 | for (; _first != _last; ++_first) 151 | { 152 | *_first = _value; 153 | } 154 | } 155 | 156 | template 157 | OutputIterator 158 | fill_n(OutputIterator _first, Size _count, const T& _value) 159 | { 160 | for (Size i = 0; i < _count; i++) 161 | { 162 | *(_first++) = _value; 163 | } 164 | return _first; 165 | } 166 | 167 | template 168 | typename iterator_traits::difference_type 169 | distance_impl(RandomAccessIterator _first, RandomAccessIterator _last, 170 | traits::true_type) 171 | { 172 | return _last - _first; 173 | } 174 | 175 | template 176 | typename iterator_traits::difference_type 177 | distance_impl(InputIterator _first, InputIterator _last, 178 | traits::false_type) 179 | { 180 | typename iterator_traits::difference_type size = 0; 181 | for (; _first != _last; ++_first, ++size); 182 | return size; 183 | } 184 | 185 | template 186 | typename iterator_traits::difference_type 187 | distance(InputIterator _first, InputIterator _last) 188 | { 189 | return 190 | distance_impl(_first, _last, 191 | traits::is_random_access_iterator::value); 192 | } 193 | 194 | using std::swap; 195 | 196 | template 197 | RandomAccessIterator 198 | _internal_partition(RandomAccessIterator _first, RandomAccessIterator _last) 199 | { 200 | RandomAccessIterator guard = _first; 201 | 202 | while (_first != _last) 203 | { 204 | while (!(*_last < *guard) && _first != _last) _last--; 205 | while (!(*guard < *_first) && _first != _last) _first++; 206 | 207 | if (_first != _last) swap(*_first, *_last); 208 | } 209 | swap(*_first, *guard); 210 | return _first; 211 | } 212 | 213 | template 214 | void 215 | sort(RandomAccessIterator _first, RandomAccessIterator _last) 216 | { 217 | static_assert( 218 | saber::traits::is_random_access_iterator::value, 219 | C8_STAT__TEMPLATE_ARG__ITER__NOT_RANDOM_ACCESS_ITERATOR); 220 | 221 | if (!(_first < _last)) return; 222 | 223 | RandomAccessIterator mid = _internal_partition(_first, _last); 224 | sort(_first, mid-1); 225 | sort(mid+1, _last); 226 | } 227 | 228 | } // namespace saber 229 | 230 | #endif // ALGORITHM_HPP 231 | -------------------------------------------------------------------------------- /include/saber/c8assert.hpp: -------------------------------------------------------------------------------- 1 | #ifndef C8ASSERT_HPP 2 | #define C8ASSERT_HPP 3 | 4 | #include "saber/safe_stl_general.hpp" 5 | 6 | namespace saber 7 | { 8 | #define C8ASSERT(TEST) {if(!(TEST)) stl_panic("Assertion " #TEST " failed.") } 9 | } // namespace saber 10 | 11 | #endif // C8ASSERT_HPP 12 | -------------------------------------------------------------------------------- /include/saber/excalibur.hpp: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma once 3 | #endif 4 | 5 | #ifndef EXCALIBUR_HPP 6 | #define EXCALIBUR_HPP 7 | 8 | #include 9 | #include "saber/safe_stl_general.hpp" 10 | #include "saber/utility.hpp" 11 | 12 | namespace saber 13 | { 14 | 15 | template 16 | void 17 | excalibur(const T* _t) 18 | { 19 | for (size_t i = 0; i < sizeof(T); ++i) 20 | { 21 | if (i % 8 == 0) 22 | { 23 | std::putchar('\n'); 24 | } 25 | 26 | std::printf("%02x ", (unsigned) 27 | (*reinterpret_cast 28 | (const_cast(_t + i)))); 29 | } 30 | std::putchar('\n'); 31 | } 32 | 33 | template 34 | void 35 | avalon(InputIterator _begin, InputIterator _end) 36 | { 37 | for (;_begin != _end; ++_begin) 38 | { 39 | std::cout << *_begin << ' '; 40 | } 41 | std::cout << std::endl; 42 | } 43 | 44 | template 45 | void 46 | lawaxis(T&& _t1, T&& _t2) 47 | { 48 | if (saber::forward(_t1) != std::forward(_t2)) 49 | { 50 | stl_panic("LawAxis error!"); 51 | } 52 | } 53 | 54 | template 55 | void 56 | lawaxis(InputIterator1 _first, InputIterator1 _last, 57 | InputIterator2 _d_first, InputIterator2 _d_last) 58 | { 59 | while (_first != _last && _d_first != _d_last) 60 | { 61 | if (*_first != *_d_first) 62 | { 63 | stl_panic("LawAxis error!"); 64 | } 65 | ++_first; ++_d_first; 66 | } 67 | } 68 | 69 | } // namespace saber 70 | 71 | #endif // EXCALIBUR_HPP 72 | -------------------------------------------------------------------------------- /include/saber/functional.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FUNCTIONAL_HPP 2 | #define FUNCTIONAL_HPP 3 | 4 | // This part is even rawly copied from EA-STL since I don't know much about 5 | // functional library. However, this may be changed soon. 6 | 7 | #include "ssaber/afe_stl_general.hpp" 8 | #include "saber/utility.hpp" 9 | 10 | namespace saber 11 | { 12 | 13 | struct allocator_arg_t {}; 14 | constexpr allocator_arg_t allocator_arg = allocator_arg_t(); 15 | 16 | template 17 | struct unary_function 18 | { 19 | using argument_type = Argument; 20 | using result_type = Result; 21 | }; 22 | 23 | template 24 | struct binary_function 25 | { 26 | using first_argument_type = Argument1; 27 | using second_argument_type = Argument2; 28 | using result_type = Result; 29 | }; 30 | 31 | template 32 | struct less : public binary_function 33 | { 34 | constexpr bool operator() (const T& _lhs, const T& _rhs) const 35 | { return _lhs < _rhs; } 36 | }; 37 | 38 | template<> 39 | struct less 40 | { 41 | template 42 | constexpr auto operator() (A&& _lhs, B&& _rhs) const 43 | -> decltype(saber::forward(_lhs) < saber::forward(_rhs)) 44 | { 45 | return saber::forward(_lhs) < saber::forward(_rhs); 46 | } 47 | }; 48 | 49 | 50 | // just for fun. 51 | template 52 | struct c8_equivalent 53 | { 54 | constexpr bool operator() (const T& _a, const T& _b, 55 | const LessPredicator& _less_pred) const 56 | { return (!_less_pred(_a, _b)) && (!_less_pred(_b, _a)); } 57 | }; 58 | 59 | template <> 60 | struct c8_equivalent 61 | { 62 | template 63 | constexpr auto operator() (A&& _a, B&& _b, 64 | const LessPredicator& _less_pred) const 65 | -> 66 | decltype( (! _less_pred(saber::forward(_a), saber::forward(_b)) ) && 67 | (! _less_pred(saber::forward(_b), saber::forward(_a)) ) ) 68 | { return (!_less_pred(saber::forward(_a), saber::forward(_b))) 69 | && (!_less_pred(saber::forward(_b), saber::forward(_a))); } 70 | }; 71 | 72 | } // namespace saber 73 | 74 | #endif // FUNCTIONAL_HPP 75 | -------------------------------------------------------------------------------- /include/saber/object_pool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OBJECT_POOL_HPP 2 | #define OBJECT_POOL_HPP 3 | 4 | #include "saber/memory.hpp" 5 | #include "saber/utility.hpp" 6 | #include "saber/algorithm.hpp" 7 | #include "saber/vector.hpp" 8 | 9 | namespace saber 10 | { 11 | 12 | template > 13 | class object_pool 14 | { 15 | public: 16 | using value_type = T; 17 | using reference_type = T&; 18 | using const_reference_type = const T&; 19 | using pointer_type = T*; 20 | using const_pointer_type = const T*; 21 | using allocator_type = Allocator; 22 | 23 | object_pool() 24 | { 25 | mem_block *init_block = 26 | allocator_traits::allocate(alloc, 1); 27 | blocks.push_back(init_block); 28 | last_object = reinterpret_cast(init_block); 29 | } 30 | 31 | ~object_pool() 32 | { 33 | for (mem_block* block : blocks) 34 | { 35 | T* storage_begin = reinterpret_cast(block); 36 | T* storage_end = block == blocks.back() ? 37 | last_object : storage_begin + block_size; 38 | destroy(storage_begin, storage_end); 39 | allocator_traits::deallocate(alloc, block, 1); 40 | } 41 | } 42 | 43 | T* store(const T& value) 44 | { 45 | add_block_by_need(); 46 | construct(last_object, value); 47 | last_object++; 48 | return last_object-1; 49 | } 50 | 51 | T* store(T&& value) 52 | { 53 | add_block_by_need(); 54 | construct(last_object, saber::move(value)); 55 | last_object++; 56 | return last_object-1; 57 | } 58 | 59 | private: 60 | void add_block_by_need() 61 | { 62 | if (last_object == (reinterpret_cast(blocks.back())+block_size-1)) 63 | { 64 | mem_block *new_block = 65 | allocator_traits::allocate(alloc, 1); 66 | blocks.push_back(new_block); 67 | last_object = reinterpret_cast(new_block); 68 | } 69 | } 70 | 71 | static constexpr size_t block_size = 4096; 72 | using mem_block = aligned_storage_t; 73 | using block_alloc_type = 74 | typename Allocator:: template rebind::other; 75 | 76 | T* last_object; 77 | 78 | vector blocks; 79 | block_alloc_type alloc; 80 | }; 81 | 82 | } // namespace saber 83 | 84 | #endif // OBJECT_POOL_HPP 85 | -------------------------------------------------------------------------------- /include/saber/optional.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OPTIONAL_HPP 2 | #define OPTIONAL_HPP 3 | 4 | #include "saber/memory.hpp" 5 | #include "saber/c8assert.hpp" 6 | 7 | namespace saber 8 | { 9 | 10 | template 11 | class optional 12 | { 13 | public: 14 | optional() : contains_value(false) {} 15 | optional(optional&& _another) 16 | { 17 | if (_another.is_type()) 18 | { 19 | contains_value = true; 20 | construct(reinterpret_cast(&storage), move(_another.get())); 21 | } 22 | else 23 | { 24 | contains_value = false; 25 | } 26 | } 27 | 28 | template 29 | optional(Args&& ..._args) 30 | { 31 | contains_value = true; 32 | construct(reinterpret_cast(&storage), 33 | saber::forward(_args)...); 34 | } 35 | 36 | ~optional() 37 | { 38 | if (is_type()) destroy_at(reinterpret_cast(&storage)); 39 | } 40 | 41 | T& get() 42 | { 43 | C8ASSERT(is_type()); 44 | return *reinterpret_cast(&storage); 45 | } 46 | 47 | bool is_type() const noexcept { return contains_value; } 48 | 49 | private: 50 | bool contains_value; 51 | aligned_storage_t storage; 52 | }; 53 | 54 | } // namespace saber 55 | 56 | #endif // OPTIONAL_HPP 57 | -------------------------------------------------------------------------------- /include/saber/result.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RESULT_HPP 2 | #define RESULT_HPP 3 | 4 | #include "saber/memory.hpp" 5 | #include "saber/c8assert.hpp" 6 | 7 | #include 8 | 9 | namespace saber 10 | { 11 | 12 | struct type_t {}; 13 | struct err_t {}; 14 | 15 | template 16 | class result 17 | { 18 | public: 19 | result(result&& _another) 20 | { 21 | if (_another.is_type()) 22 | { 23 | contains_value = true; 24 | construct(reinterpret_cast(&storage), move(_another.value())); 25 | } 26 | else 27 | { 28 | contains_value = false; 29 | construct(reinterpret_cast(&storage), move(_another.err())); 30 | } 31 | } 32 | 33 | result(const T& _t) 34 | { 35 | contains_value = true; 36 | construct(reinterpret_cast(&storage), _t); 37 | } 38 | 39 | result(const E& _e) 40 | { 41 | contains_value = false; 42 | construct(reinterpret_cast(&storage), _e); 43 | } 44 | 45 | result(T&& _t) 46 | { 47 | contains_value = true; 48 | construct(reinterpret_cast(&storage), move(_t)); 49 | } 50 | 51 | result(E&& _e) 52 | { 53 | contains_value = false; 54 | construct(reinterpret_cast(&storage), move(_e)); 55 | } 56 | 57 | template 58 | result(type_t, Args&& ..._args) 59 | { 60 | contains_value = true; 61 | construct(reinterpret_cast(&storage), forward(_args)...); 62 | } 63 | 64 | template 65 | result(err_t, Args&& ..._args) 66 | { 67 | contains_value = false; 68 | construct(reinterpret_cast(&storage), forward(_args)...); 69 | } 70 | 71 | ~result() 72 | { 73 | if (is_type()) destroy_at(reinterpret_cast(&storage)); 74 | else destroy_at(reinterpret_cast(&storage)); 75 | } 76 | 77 | bool is_type() const noexcept { return contains_value; } 78 | bool is_err() const noexcept { return !is_type(); } 79 | 80 | T& expect(const char* _desc) 81 | { 82 | if (!is_type()) 83 | { 84 | std::printf("%s", _desc); 85 | std::abort(); 86 | } 87 | return *reinterpret_cast(&storage); 88 | } 89 | 90 | T& unwarp() 91 | { 92 | if (!is_type()) 93 | std::abort(); 94 | return *reinterpret_cast(&storage); 95 | } 96 | 97 | T& value() 98 | { 99 | C8ASSERT(is_type()); 100 | return *reinterpret_cast(&storage); 101 | } 102 | 103 | E& err() 104 | { 105 | C8ASSERT(is_err()); 106 | return *reinterpret_cast(&storage); 107 | } 108 | 109 | private: 110 | static constexpr std::size_t storage_size = 111 | sizeof(T) > sizeof(E) ? sizeof(T) : sizeof(E); 112 | static constexpr std::size_t storage_align = 113 | alignof(T) > alignof(E) ? alignof(T) : alignof(E); 114 | 115 | aligned_storage_t storage; 116 | bool contains_value; 117 | }; 118 | 119 | } // namespace saber 120 | 121 | #endif // RESULT_HPP 122 | -------------------------------------------------------------------------------- /include/saber/saber_traits.hpp: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma once 3 | #endif 4 | 5 | #ifndef SABER_TRAITS_HPP 6 | #define SABER_TRAITS_HPP 7 | 8 | #include 9 | namespace saber 10 | { 11 | namespace traits 12 | { 13 | 14 | using std::true_type; 15 | using std::false_type; 16 | 17 | template struct make_void { typedef void type;}; 18 | template using void_t = typename make_void::type; 19 | 20 | template 21 | struct int2type 22 | { 23 | using value_type = false_type; 24 | }; 25 | 26 | template<> 27 | struct int2type 28 | { 29 | using value_type = true_type; 30 | }; 31 | 32 | template 33 | struct type_equivalent 34 | { 35 | using value_type = false_type; 36 | static constexpr bool value = false; 37 | }; 38 | 39 | template 40 | struct type_equivalent 41 | { 42 | using value_type = true_type; 43 | static constexpr bool value = true; 44 | }; 45 | 46 | } // namespace traits 47 | } // namespace saber 48 | 49 | #endif // SABER_TRAITS_HPP 50 | -------------------------------------------------------------------------------- /include/saber/safe_stl_general.hpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////////////////////// // 2 | 3 | // 藕花香 染檐牙 // 4 | // 惹那诗人 纵步随她 // 5 | // 佩声微 琴声儿退 // 6 | // 斗胆了一池眉叶丹砂 // 7 | 8 | // 画船开 心随她 // 9 | // 谁不作美 偏起风沙 // 10 | // 倚蓬窗 月色轻晃 // 11 | // 偶闻得渔翁一席话 // 12 | 13 | // 试问 // 14 | // 多一份情又怎地 // 15 | // 站在别人的雨季 // 16 | // 淋湿自己 空弹一出戏 // 17 | // 空望他 功成名就又怎地 // 18 | // 豆腐换成金羽衣 // 19 | // 岂不知你已在画里 // 20 | 21 | // 多一份情又怎地 // 22 | // 站在别人的雨季 // 23 | // 淋湿自己 空弹一出戏 // 24 | // 空望他 功成名就又怎地 // 25 | // 豆腐换成金羽衣 // 26 | // 岂不知你已在画里 // 27 | 28 | // 这一搭 莲蓬子落地 几回迷 // 29 | 30 | // //////////////////////////////////////////////////////////////////////// // 31 | 32 | #ifndef SAFE_STL_GENERAL_HPP 33 | #define SAFE_STL_GENERAL_HPP 34 | 35 | #define SAFE_STL_ENABLE_WARNING 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #ifndef Q_UNUSED 44 | #define Q_UNUSED(_VARNAME) ((void)(_VARNAME)); 45 | #endif 46 | 47 | namespace saber 48 | { 49 | 50 | using std::initializer_list; 51 | 52 | FILE*& fp_export(void); 53 | void set_export(FILE* _fp); 54 | 55 | #define stl_panic(_DESC)\ 56 | {\ 57 | std::fprintf(saber::fp_export(), "At file %s, line %d\n", __FILE__, __LINE__);\ 58 | std::fprintf(saber::fp_export(), "STL panic called : %s\n", _DESC);\ 59 | std::fflush(saber::fp_export());\ 60 | std::abort();\ 61 | } 62 | 63 | #ifdef SAFE_STL_ENABLE_WARNING 64 | # define stl_warning(_DESC)\ 65 | {\ 66 | std::fprintf(fp_export(), "At file %s, line %d\n", __FILE__, __LINE__);\ 67 | std::fprintf(fp_export(), "STL warning called : %s\n", _DESC);\ 68 | std::fflush(fp_export());\ 69 | } 70 | #else 71 | # define stl_warning(_DESC) 72 | #endif 73 | 74 | } // namespace saber 75 | 76 | #endif // SAFE_STL_GENERAL_HPP 77 | -------------------------------------------------------------------------------- /include/saber/string.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STRING_HPP 2 | #define STRING_HPP 3 | 4 | #include 5 | #include 6 | #include "saber/memory.hpp" 7 | 8 | namespace saber 9 | { 10 | using std::basic_string; 11 | using std::string; 12 | 13 | using std::char_traits; 14 | 15 | template 16 | string to_string_helper(T&& _value) 17 | { 18 | return saber::forward(_value).to_string(); 19 | } 20 | 21 | inline string to_string_helper(bool b) 22 | { 23 | return b ? "true" : "false"; 24 | } 25 | 26 | inline string to_string_helper(int64_t _number) 27 | { 28 | std::stringstream stream; 29 | stream << _number; 30 | return stream.str(); 31 | } 32 | 33 | inline string to_string_helper(uint64_t _number) 34 | { 35 | std::stringstream stream; 36 | stream << _number; 37 | return stream.str(); 38 | } 39 | 40 | inline string to_string_helper(double _number) 41 | { 42 | std::stringstream stream; 43 | stream << _number; 44 | return stream.str(); 45 | } 46 | 47 | inline string to_string_helper(char _ch) 48 | { 49 | string ret; ret.push_back(_ch); return ret; 50 | } 51 | 52 | inline string to_string_helper(const char* _str) 53 | { 54 | return string(_str); 55 | } 56 | 57 | inline string to_string_helper(string _str) 58 | { 59 | return string(saber::move(_str)); 60 | } 61 | 62 | /* 63 | inline string to_string_helper(const string& _str) 64 | { 65 | return string(_str); 66 | } 67 | */ 68 | 69 | inline string to_string_helper(string&& _str) 70 | { 71 | return string(saber::move(_str)); 72 | } 73 | 74 | 75 | inline void paste_impl(const string&) 76 | { 77 | /// @nattention pass 78 | } 79 | 80 | template 81 | void paste_impl(string& _str, T&& _value, Args&& ..._args) 82 | { 83 | _str += to_string_helper(saber::forward(_value)); 84 | paste_impl(_str, saber::forward(_args)...); 85 | } 86 | 87 | template 88 | string string_paste(Args&& ..._args) 89 | { 90 | string ret = ""; 91 | paste_impl(ret, saber::forward(_args)...); 92 | return ret; 93 | } 94 | 95 | } 96 | 97 | #endif // STRING_HPP 98 | -------------------------------------------------------------------------------- /include/saber/string_pool.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STRING_POOL_HPP 2 | #define STRING_POOL_HPP 3 | 4 | #include "saber/string.hpp" 5 | #include "saber/unordered_map.hpp" 6 | #include "saber/memory.hpp" 7 | 8 | namespace saber 9 | { 10 | 11 | template class string_pool; 12 | 13 | template 14 | class string_view 15 | { 16 | friend class string_pool; 17 | 18 | public: 19 | string_view(const string_view& _another); 20 | ~string_view(); 21 | 22 | const StringType& get() const noexcept; 23 | bool operator== (const string_view& _another) const noexcept; 24 | bool operator!= (const string_view& _another) const noexcept; 25 | string_view& operator= (const string_view& _another) noexcept; 26 | 27 | private: 28 | string_view(const StringType* _str = nullptr, size_t* _refcount = nullptr); 29 | const StringType* str; 30 | size_t* refcount; 31 | }; 32 | 33 | template 34 | class string_pool 35 | { 36 | friend class string_view; 37 | public: 38 | static string_view create_view(const StringType &_string); 39 | static string_view create_view(StringType &&_string); 40 | 41 | private: 42 | static string_pool& get() noexcept; 43 | string_view create_view_impl(const StringType& _string); 44 | string_view create_view_impl(StringType&& _string); 45 | 46 | using set_type = unordered_map; 47 | 48 | string_pool() = default; 49 | set_type string_set; 50 | }; 51 | 52 | 53 | 54 | template 55 | string_view::string_view(const StringType *_str, 56 | size_t *_refcount) : 57 | str(_str), 58 | refcount(_refcount) 59 | {} 60 | 61 | template 62 | string_view::string_view(const string_view& _another) : 63 | str(_another.str), 64 | refcount(_another.refcount) 65 | { 66 | ++(*refcount); 67 | } 68 | 69 | template 70 | string_view::~string_view() 71 | { 72 | --(*refcount); 73 | if (*refcount == 0) 74 | string_pool::get().string_set.erase(*str); 75 | } 76 | 77 | template 78 | const StringType& 79 | string_view::get() const noexcept 80 | { 81 | return *str; 82 | } 83 | 84 | template 85 | bool 86 | string_view::operator== (const string_view& _another) const noexcept 87 | { 88 | return string_pool::get().string_set.find(*str) 89 | == string_pool::get().string_set.find(*(_another.str)); 90 | } 91 | 92 | template 93 | bool 94 | string_view::operator!= (const string_view& _another) const noexcept 95 | { 96 | return ! this->operator==(_another); 97 | } 98 | 99 | template 100 | string_view& 101 | string_view::operator= (const string_view& _another) noexcept 102 | { 103 | --(*refcount); 104 | if (*refcount == 0) 105 | string_pool::get().string_set.erase(*str); 106 | 107 | refcount = _another.refcount; 108 | str = _another.str; 109 | ++(*refcount); 110 | return *this; 111 | } 112 | 113 | 114 | 115 | template 116 | string_pool& 117 | string_pool::get() noexcept 118 | { 119 | static string_pool ret; 120 | return ret; 121 | } 122 | 123 | template 124 | string_view 125 | string_pool::create_view(const StringType &_string) 126 | { 127 | return string_pool::get().create_view_impl(_string); 128 | } 129 | 130 | template 131 | string_view 132 | string_pool::create_view(StringType &&_string) 133 | { 134 | return string_pool::get().create_view_impl( 135 | saber::move(_string)); 136 | } 137 | 138 | template 139 | string_view 140 | string_pool::create_view_impl(const StringType &_string) 141 | { 142 | auto it = string_set.find(_string); 143 | if ( it == string_set.end() ) 144 | it = string_set.insert(std::make_pair(_string, 1)).first; 145 | return string_view(&(it->first), &(it->second)); 146 | } 147 | 148 | template 149 | string_view 150 | string_pool::create_view_impl(StringType &&_string) 151 | { 152 | auto it = string_set.find(_string); 153 | if ( it == string_set.end() ) 154 | it = string_set.insert(std::make_pair(saber::move(_string), 1)).first; 155 | else 156 | ++(it->second); 157 | return string_view(&(it->first), &(it->second)); 158 | } 159 | 160 | 161 | 162 | template 163 | StringType to_string_helper(string_view _view) 164 | { 165 | return _view.get(); 166 | } 167 | 168 | } // namespace saber 169 | 170 | using saber_string = saber::string; 171 | using saber_string_view = saber::string_view; 172 | using saber_string_pool = saber::string_pool; 173 | 174 | struct string_view_hash 175 | { 176 | bool operator() (const saber_string_view& _view)const noexcept 177 | { 178 | return std::hash()(_view.get()); 179 | } 180 | }; 181 | 182 | #endif // STRING_POOL_HPP 183 | -------------------------------------------------------------------------------- /include/saber/strings.defs.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGS_DEFS_H 2 | #define STRINGS_DEFS_H 3 | 4 | #define C8_TEMPLATE_ARG_PREFIX "Template argument" 5 | #define C8_TYPENAME_T_PREFIX "T" 6 | #define C8_TYPENAME_ITERATOR_PREFIX "Iterator" 7 | 8 | #define C8_STAT__TEMPLATE_ARG__T__COPY_CONSTRUCT_ERROR\ 9 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_T_PREFIX " cannot be copy-constructed" 10 | 11 | #define C8_STAT__TEMPLATE_ARG__T__COPY_ASSIGN_ERROR\ 12 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_T_PREFIX " cannot be copy-assigned" 13 | 14 | #define C8_STAT__TEMPLATE_ARG__T__MOVE_ASSIGN_ERROR\ 15 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_T_PREFIX " cannot be move-assigned" 16 | 17 | #define C8_STAT__TEMPLATE_ARG__T__DESTROY_ERROR\ 18 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_T_PREFIX " cannot be destroyed" 19 | 20 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_ITERATOR\ 21 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not an iterator type" 22 | 23 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_INPUT_ITERATOR\ 24 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not an input iterator type" 25 | 26 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_OUTPUT_ITERATOR\ 27 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not an output iterator type" 28 | 29 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_FORWARD_ITERATOR\ 30 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not a forward iterator type" 31 | 32 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_BIDIRECTIONAL_ITERATOR\ 33 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not a bidirectional iterator type" 34 | 35 | #define C8_STAT__TEMPLATE_ARG__ITER__NOT_RANDOM_ACCESS_ITERATOR\ 36 | C8_TEMPLATE_ARG_PREFIX " " C8_TYPENAME_ITERATOR_PREFIX " is not a random-access iterator type" 37 | 38 | 39 | #define C8_DYN__ITER__UNINITIALIZED_ITERATOR\ 40 | "This iterator did not get initialized" 41 | 42 | #define C8_DYN__ITER__OLD_ITERATOR\ 43 | "A manipulating operation has been performed on container object" 44 | 45 | #define C8_DYN__ITER__SUBSCRIPT_OVERFLOW\ 46 | "Accessing an invalid subscript" 47 | 48 | #define C8_DYN__ITER__ITERATOR_OVERFLOW\ 49 | "This iterator is now pointing to an invalid position, for example, end()" 50 | 51 | #define C8_DYN__ITER__DELETED_CONTAINER\ 52 | "Container has been destroyed but left this iterator alone" 53 | 54 | #define C8_DYN__ITER__UNKNOWN_REGION_ITERATOR\ 55 | "This iterator does not come from this container" 56 | 57 | #define C8_DYN__CONT__SPLICE_BETWEEN_UNEQUAL_ALLOC_CONTAINERS\ 58 | "Splicing between two containers which have unequal allocators" 59 | 60 | #define C8_DYN__CONT__CONTAINER_COPY\ 61 | "Copying container" 62 | 63 | #endif // STRINGS_DEFS_H 64 | -------------------------------------------------------------------------------- /include/saber/type_traits.hpp: -------------------------------------------------------------------------------- 1 | #ifndef TYPE_TRAITS_HPP 2 | #define TYPE_TRAITS_HPP 3 | 4 | namespace saber 5 | { 6 | 7 | template 8 | struct remove_reference { using type = T; }; 9 | 10 | template 11 | struct remove_reference { using type = T; }; 12 | 13 | template 14 | struct remove_reference { using type = T; }; 15 | 16 | } // namespace saber 17 | 18 | #endif // TYPE_TRAITS_HPP 19 | -------------------------------------------------------------------------------- /include/saber/unordered_map.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UNORDERED_MAP_HPP 2 | #define UNORDERED_MAP_HPP 3 | 4 | #include 5 | 6 | namespace saber 7 | { 8 | 9 | using std::unordered_map; 10 | using std::unordered_multimap; 11 | 12 | } // namespace saber 13 | 14 | #endif // UNORDERED_MAP_HPP 15 | -------------------------------------------------------------------------------- /include/saber/unordered_set.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UNORDERED_SET_HPP 2 | #define UNORDERED_SET_HPP 3 | 4 | #include 5 | 6 | namespace saber 7 | { 8 | 9 | using std::unordered_set; 10 | using std::unordered_multiset; 11 | 12 | } // namespace saber 13 | 14 | #endif // UNORDERED_SET_HPP 15 | -------------------------------------------------------------------------------- /include/saber/utility.hpp: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_HPP 2 | #define UTILITY_HPP 3 | 4 | #include "saber/type_traits.hpp" 5 | #include 6 | 7 | namespace saber 8 | { 9 | 10 | using std::swap; 11 | using std::pair; 12 | using std::tuple; 13 | 14 | template 15 | constexpr T&& 16 | forward(typename remove_reference::type& _t) noexcept 17 | { 18 | return static_cast(_t); 19 | } 20 | 21 | template 22 | constexpr T&& 23 | forward(typename remove_reference::type&& _t) noexcept 24 | { 25 | return static_cast(_t); 26 | } 27 | 28 | template 29 | constexpr typename remove_reference::type&& 30 | move(T&& _t) noexcept 31 | { 32 | return static_cast::type&&>(_t); 33 | } 34 | 35 | } // namespace saber 36 | 37 | #endif // UTILITY_HPP 38 | -------------------------------------------------------------------------------- /include/we/defs.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #ifndef DEFS_HPP 20 | #define DEFS_HPP 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include "saber/string.hpp" 27 | 28 | using qint64 = std::int64_t; 29 | using qint32 = std::int32_t; 30 | using qint16 = std::int16_t; 31 | using qint8 = std::int8_t; 32 | 33 | using quint64 = std::uint64_t; 34 | using quint32 = std::uint32_t; 35 | using quint16 = std::uint16_t; 36 | using quint8 = std::uint8_t; 37 | 38 | using qptrdiff = std::ptrdiff_t; 39 | 40 | using qchar = signed char; 41 | 42 | using qsizet = size_t; 43 | 44 | using qreal = double; 45 | 46 | struct qcoord 47 | { 48 | quint16 line; 49 | quint16 col; 50 | qcoord(quint16 _line, quint16 _col) : line(_line), col(_col) {} 51 | }; 52 | 53 | template 54 | using qpair = std::pair; 55 | 56 | using std::make_pair; 57 | 58 | template 59 | using qtuple = std::tuple; 60 | 61 | template 62 | constexpr qsizet countof(const ArrayType& _array) 63 | { 64 | return sizeof(_array) / sizeof(_array[0]); 65 | } 66 | 67 | inline saber::string to_string_helper(qcoord _coord) 68 | { 69 | return saber::to_string_helper(quint64(_coord.line)) 70 | + saber::to_string_helper(quint64(_coord.col)); 71 | } 72 | 73 | #define interface class 74 | #define pod_struct struct 75 | #define open_class struct 76 | #define variant union 77 | 78 | #define implements : public 79 | #define make_use_of : public 80 | 81 | #define Q_ON_HOLD(ANYTHING) 82 | 83 | #define COMMENT(COMMENTS) 84 | 85 | #endif // DEFS_HPP 86 | -------------------------------------------------------------------------------- /include/we/file_reader.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | 20 | #ifndef CKX_FILE_READER_HPP 21 | #define CKX_FILE_READER_HPP 22 | 23 | #include 24 | #include 25 | 26 | #include "saber/string.hpp" 27 | #include "we/defs.hpp" 28 | 29 | namespace we 30 | { 31 | namespace detail 32 | { 33 | class we_fp_reader_impl; 34 | class we_istream_reader_impl; 35 | } // namespace detail 36 | 37 | 38 | interface we_file_reader 39 | { 40 | public: 41 | we_file_reader() = default; 42 | virtual ~we_file_reader() = 0; 43 | virtual qchar get_next_char(void) = 0; 44 | 45 | we_file_reader(const we_file_reader& _another) = delete; 46 | we_file_reader* operator= (const we_file_reader& _another) = delete; 47 | }; 48 | 49 | 50 | class we_fp_reader final implements we_file_reader 51 | { 52 | public: 53 | explicit we_fp_reader(std::FILE* _fp); 54 | ~we_fp_reader() override final; 55 | qchar get_next_char() override final; 56 | 57 | we_fp_reader(const we_fp_reader& _another) = delete; 58 | we_fp_reader& operator= (const we_fp_reader& _another) = delete; 59 | 60 | private: 61 | detail::we_fp_reader_impl *impl; 62 | }; 63 | 64 | 65 | class we_istream_reader final implements we_file_reader 66 | { 67 | public: 68 | explicit we_istream_reader(std::istream& _stream); 69 | ~we_istream_reader() override final; 70 | qchar get_next_char() override final; 71 | 72 | we_istream_reader(const we_istream_reader& _another) = delete; 73 | we_istream_reader& operator= (const we_istream_reader& _another) = delete; 74 | 75 | private: 76 | detail::we_istream_reader_impl *impl; 77 | }; 78 | 79 | class we_test_filereader final implements we_file_reader 80 | { 81 | public: 82 | we_test_filereader(saber::string&& _str) : str(saber::move(_str)) {} 83 | ~we_test_filereader() = default; 84 | qchar get_next_char(void) override final 85 | { 86 | pos++; 87 | if (pos-1 < str.size()) return str[pos-1]; 88 | else return static_cast(saber::char_traits::eof()); 89 | } 90 | 91 | private: 92 | qsizet pos = 0; 93 | saber::string str; 94 | }; 95 | 96 | } // namespace ckx 97 | 98 | #endif // CKX_FILE_READER_HPP 99 | -------------------------------------------------------------------------------- /include/we/file_writer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | 20 | #ifndef CKX_FILE_WRITER_HPP 21 | #define CKX_FILE_WRITER_HPP 22 | 23 | #include 24 | #include 25 | 26 | #include "saber/string_pool.hpp" 27 | #include "we/defs.hpp" 28 | 29 | namespace we 30 | { 31 | namespace detail 32 | { 33 | class we_fp_writer_impl; 34 | class we_ostream_writer_impl; 35 | } // namespace detail 36 | 37 | 38 | interface we_file_writer 39 | { 40 | public: 41 | we_file_writer() = default; 42 | virtual ~we_file_writer() = 0; 43 | 44 | virtual void write(qint64 _value) = 0; 45 | virtual void write(quint64 _value) = 0; 46 | virtual void write(qreal _value) = 0; 47 | virtual void write(const qchar* _str) = 0; 48 | virtual void write(const saber_string& _str) = 0; 49 | virtual void write(saber_string_view _str_view) = 0; 50 | virtual void write_whitespace(qsizet _count) = 0; 51 | 52 | we_file_writer(const we::we_file_writer& _another) = delete; 53 | we_file_writer& operator= (const we::we_file_writer& _another) = delete; 54 | }; 55 | 56 | class we_fp_writer final implements we::we_file_writer 57 | { 58 | public: 59 | explicit we_fp_writer(std::FILE* _fp); 60 | ~we_fp_writer() override final; 61 | 62 | void write(qint64 _value) override final; 63 | void write(quint64 _value) override final; 64 | void write(qreal _value) override final; 65 | void write(const qchar* _str) override final; 66 | void write(const saber_string& _str) override final; 67 | void write(saber_string_view _str_view) override final; 68 | void write_whitespace(qsizet _count) override final; 69 | 70 | we_fp_writer(const we::we_fp_writer& _another) = delete; 71 | we_fp_writer& operator= (const we::we_fp_writer& _another) = delete; 72 | 73 | private: 74 | detail::we_fp_writer_impl *impl; 75 | }; 76 | 77 | class we_ostream_writer final implements we::we_file_writer 78 | { 79 | public: 80 | explicit we_ostream_writer(std::ostream& _stream); 81 | ~we_ostream_writer(); 82 | 83 | void write(qint64 _value) override final; 84 | void write(quint64 _value) override final; 85 | void write(qreal _value) override final; 86 | void write(const qchar* _str) override final; 87 | void write(const saber_string& _str) override final; 88 | void write(saber_string_view _str_view) override final; 89 | void write_whitespace(qsizet _count) override final; 90 | 91 | we_ostream_writer(const we_ostream_writer& _another) = delete; 92 | we_ostream_writer& operator= (const we_ostream_writer& _another) = delete; 93 | 94 | private: 95 | detail::we_ostream_writer_impl *impl; 96 | }; 97 | 98 | } // namespace ckx 99 | 100 | #endif // CKX_FILE_WRITER_HPP 101 | -------------------------------------------------------------------------------- /src/driver/main.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/lex/ckx_token_stream.hpp" 2 | #include "frontend/parse/ckx_parser.hpp" 3 | #include "frontend/sema/ckx_sema.hpp" 4 | 5 | int main(int argc, char** argv) 6 | { 7 | using namespace ckx; 8 | using namespace we; 9 | 10 | if (argc != 2) 11 | { 12 | fprintf(stderr, "Usage: ckxc filename\n"); 13 | return -1; 14 | } 15 | 16 | FILE *fp = fopen(argv[1], "r"); 17 | if (fp == nullptr) 18 | { 19 | fprintf(stderr, "File %s not found\n", argv[1]); 20 | return -2; 21 | } 22 | 23 | we_fp_reader reader(fp); 24 | ckx_token_stream stream(reader); 25 | ckx_sema_engine sema; 26 | 27 | ckx_parser().parse(&stream).trans_unit->accept(sema); 28 | we_fp_writer writer(stdout); 29 | sema.test_print(writer); 30 | fclose(fp); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /src/frontend/lex/ckx_operator.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/AST/ckx_operator.hpp" 2 | #include "saber/c8assert.hpp" 3 | 4 | namespace ckx 5 | { 6 | 7 | ckx_op ckx_op_helper::token2unary(ckx_token::type _token) 8 | { 9 | switch (_token) 10 | { 11 | case ckx_token::type::tk_add: return ckx_op::op_unary_positive; 12 | case ckx_token::type::tk_sub: return ckx_op::op_unary_negative; 13 | case ckx_token::type::tk_bit_and: return ckx_op::op_addr; 14 | case ckx_token::type::tk_mul: return ckx_op::op_deref; 15 | case ckx_token::type::tk_bit_not: return ckx_op::op_bit_not; 16 | case ckx_token::type::tk_logic_not: return ckx_op::op_logic_not; 17 | case ckx_token::type::tk_inc: return ckx_op::op_inc; 18 | case ckx_token::type::tk_dec: return ckx_op::op_dec; 19 | 20 | default: return ckx_op::op_undefined; 21 | } 22 | } 23 | 24 | ckx_op ckx_op_helper::token2binary(ckx_token::type _token) 25 | { 26 | switch (_token) 27 | { 28 | case ckx_token::type::tk_add: return ckx_op::op_add; 29 | case ckx_token::type::tk_sub: return ckx_op::op_sub; 30 | case ckx_token::type::tk_mul: return ckx_op::op_mul; 31 | case ckx_token::type::tk_div: return ckx_op::op_div; 32 | case ckx_token::type::tk_mod: return ckx_op::op_mod; 33 | case ckx_token::type::tk_bit_and: return ckx_op::op_bit_and; 34 | case ckx_token::type::tk_bit_or: return ckx_op::op_bit_or; 35 | case ckx_token::type::tk_bit_xor: return ckx_op::op_bit_xor; 36 | case ckx_token::type::tk_logic_and: return ckx_op::op_logic_and; 37 | case ckx_token::type::tk_logic_or: return ckx_op::op_logic_or; 38 | case ckx_token::type::tk_lt: return ckx_op::op_lt; 39 | case ckx_token::type::tk_eq: return ckx_op::op_eq; 40 | case ckx_token::type::tk_gt: return ckx_op::op_gt; 41 | case ckx_token::type::tk_leq: return ckx_op::op_leq; 42 | case ckx_token::type::tk_geq: return ckx_op::op_geq; 43 | case ckx_token::type::tk_neq: return ckx_op::op_neq; 44 | 45 | /// @attention now we treat all assignments as binary operators. 46 | case ckx_token::type::tk_assign: return ckx_op::op_assign; 47 | case ckx_token::type::tk_add_assign: return ckx_op::op_add_assign; 48 | case ckx_token::type::tk_sub_assign: return ckx_op::op_sub_assign; 49 | case ckx_token::type::tk_mul_assign: return ckx_op::op_mul_assign; 50 | case ckx_token::type::tk_div_assign: return ckx_op::op_div_assign; 51 | case ckx_token::type::tk_mod_assign: return ckx_op::op_mod_assign; 52 | 53 | default: return ckx_op::op_undefined; 54 | } 55 | } 56 | 57 | bool ckx_op_helper::is_unary(ckx_op _op) 58 | { 59 | return (_op >= ckx_op::op_unary_positive 60 | && _op <= ckx_op::op_dec); 61 | } 62 | 63 | bool ckx_op_helper::is_binary(ckx_op _op) 64 | { 65 | return (_op >= ckx_op::op_add 66 | && _op <= ckx_op::op_neq); 67 | } 68 | 69 | bool ckx_op_helper::is_assign(ckx_op _op) 70 | { 71 | return (_op >= ckx_op::op_assign 72 | && _op <= ckx_op::op_mod_assign); 73 | } 74 | 75 | bool ckx_op_helper::is_logical(ckx_op _op) 76 | { 77 | return _op == ckx_op::op_logic_and 78 | || _op == ckx_op::op_logic_or 79 | || _op == ckx_op::op_logic_not; 80 | } 81 | 82 | quint8 ckx_op_helper::precedence(ckx_op _op) 83 | { 84 | switch (_op) 85 | { 86 | case ckx_op::op_unary_positive: 87 | case ckx_op::op_unary_negative: 88 | case ckx_op::op_addr: 89 | case ckx_op::op_deref: 90 | case ckx_op::op_bit_not: 91 | case ckx_op::op_logic_not: 92 | case ckx_op::op_inc: 93 | case ckx_op::op_dec: 94 | return 64; 95 | 96 | case ckx_op::op_mul: 97 | case ckx_op::op_div: 98 | case ckx_op::op_mod: 99 | return 60; 100 | 101 | case ckx_op::op_add: 102 | case ckx_op::op_sub: 103 | return 56; 104 | 105 | case ckx_op::op_lt: 106 | case ckx_op::op_leq: 107 | case ckx_op::op_gt: 108 | case ckx_op::op_geq: 109 | return 48; 110 | 111 | case ckx_op::op_eq: 112 | case ckx_op::op_neq: 113 | return 44; 114 | 115 | case ckx_op::op_bit_and: 116 | return 40; 117 | 118 | case ckx_op::op_bit_or: 119 | return 36; 120 | 121 | case ckx_op::op_logic_and: 122 | return 32; 123 | 124 | case ckx_op::op_logic_or: 125 | return 28; 126 | 127 | case ckx_op::op_assign: 128 | case ckx_op::op_add_assign: 129 | case ckx_op::op_sub_assign: 130 | case ckx_op::op_mul_assign: 131 | case ckx_op::op_div_assign: 132 | case ckx_op::op_mod_assign: 133 | return 24; 134 | 135 | default: 136 | C8ASSERT(false); // What the fuck! 137 | } 138 | } 139 | 140 | } // namespace ckx 141 | -------------------------------------------------------------------------------- /src/frontend/lex/ckx_token.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | 20 | #include "frontend/lex/ckx_token.hpp" 21 | #include "saber/memory.hpp" 22 | #include "saber/string_pool.hpp" 23 | #include "saber/c8assert.hpp" 24 | 25 | namespace ckx 26 | { 27 | 28 | ckx_token::ckx_token(ckx_src_rng _rng, type _operator) : 29 | rng(_rng), token_type(_operator) {} 30 | 31 | ckx_token::ckx_token(ckx_src_rng _rng, qint64 _int_literal) : 32 | rng(_rng), token_type(type::tk_vi_literal), v(_int_literal) {} 33 | 34 | ckx_token::ckx_token(ckx_src_rng _rng, quint64 _unsigned_literal) : 35 | rng(_rng), token_type(type::tk_vr_literal), v(_unsigned_literal) {} 36 | 37 | ckx_token::ckx_token(ckx_src_rng _rng, qreal _real_literal) : 38 | rng(_rng), token_type(type::tk_vr_literal), v(_real_literal) {} 39 | 40 | ckx_token::ckx_token(ckx_src_rng _rng, qchar _char_literal) : 41 | rng(_rng), token_type(type::tk_vchar_literal), v(_char_literal) {} 42 | 43 | ckx_token::ckx_token(ckx_src_rng _rng, saber_string_view _id) : 44 | rng(_rng), token_type(type::tk_id), str(_id) {} 45 | 46 | 47 | 48 | saber_string to_string_helper(ckx_token _token) 49 | { 50 | switch (_token.token_type) 51 | { 52 | # define GG2LEX(X, Y) \ 53 | case ckx_token::type::tk_##Y: return X; 54 | # define GGLEX(X, Y) \ 55 | case ckx_token::type::tk_##Y: return X; 56 | # include "frontend/parse/gg.h" 57 | # undef GG2LEX 58 | # undef GGLEX 59 | case ckx_token::type::tk_vi_literal: 60 | return saber::to_string_helper(_token.v.i64); 61 | case ckx_token::type::tk_vr_literal: 62 | return saber::to_string_helper(_token.v.r); 63 | case ckx_token::type::tk_vu_literal: 64 | return saber::to_string_helper(_token.v.u64); 65 | case ckx_token::type::tk_vchar_literal: 66 | return saber::to_string_helper(char(_token.v.ch)); 67 | case ckx_token::type::tk_string_literal: 68 | case ckx_token::type::tk_id: 69 | return saber::to_string_helper(_token.str); 70 | case ckx_token::type::tk_eoi: 71 | return "EOI"; 72 | } 73 | 74 | C8ASSERT(false); 75 | } 76 | 77 | } // namespace ckx; 78 | -------------------------------------------------------------------------------- /src/frontend/parse/ckx_prelexed_type.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #include "frontend/parse/ckx_prelexed_type.hpp" 20 | 21 | namespace ckx 22 | { 23 | /// @note this file is preserved for further changes. 24 | } 25 | -------------------------------------------------------------------------------- /src/frontend/parse/ckx_token_set.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #include "frontend/parse/ckx_token_set.hpp" 20 | 21 | namespace ckx 22 | { 23 | 24 | namespace detail 25 | { 26 | 27 | const ckx_token_set& 28 | ckx_token_sets::first_stmt_set() 29 | { 30 | static ckx_token_set ret = 31 | { 32 | /// @brief elements may appear at the commence of a declaration 33 | ckx_token::type::tk_id, 34 | ckx_token::type::tk_vi8, 35 | ckx_token::type::tk_vi16, 36 | ckx_token::type::tk_vi32, 37 | ckx_token::type::tk_vi64, 38 | ckx_token::type::tk_vu8, 39 | ckx_token::type::tk_vu16, 40 | ckx_token::type::tk_vu32, 41 | ckx_token::type::tk_vu64, 42 | ckx_token::type::tk_vch, 43 | ckx_token::type::tk_vr32, 44 | ckx_token::type::tk_vr64, 45 | 46 | /// @brief elements may appear at the commence of an expression 47 | ckx_token::type::tk_add, 48 | ckx_token::type::tk_sub, 49 | ckx_token::type::tk_mul, 50 | ckx_token::type::tk_bit_and, 51 | ckx_token::type::tk_const_cast, 52 | ckx_token::type::tk_reinterpret_cast, 53 | ckx_token::type::tk_static_cast, 54 | ckx_token::type::tk_ckx_cast, 55 | 56 | /// @brief control-statements 57 | ckx_token::type::tk_if, 58 | ckx_token::type::tk_while, 59 | ckx_token::type::tk_do, 60 | ckx_token::type::tk_for, 61 | ckx_token::type::tk_break, 62 | ckx_token::type::tk_continue, 63 | ckx_token::type::tk_return, 64 | 65 | /// @brief may enter new scope 66 | ckx_token::type::tk_lbrace 67 | }; 68 | return ret; 69 | } 70 | 71 | const ckx_token_set& 72 | ckx_token_sets::first_global_set() 73 | { 74 | static ckx_token_set ret = 75 | { 76 | /// @brief import/export 77 | /// @todo remember to add the two keywords 78 | /// after adding import/export to ckx. 79 | 80 | /// @brief elements may appear at the commence of a declaration 81 | /// identifiers may be typenames. 82 | ckx_token::type::tk_id, 83 | ckx_token::type::tk_vi8, 84 | ckx_token::type::tk_vi16, 85 | ckx_token::type::tk_vi32, 86 | ckx_token::type::tk_vi64, 87 | ckx_token::type::tk_vu8, 88 | ckx_token::type::tk_vu16, 89 | ckx_token::type::tk_vu32, 90 | ckx_token::type::tk_vu64, 91 | ckx_token::type::tk_vch, 92 | ckx_token::type::tk_vr32, 93 | ckx_token::type::tk_vr64, 94 | 95 | /// @brief function 96 | ckx_token::type::tk_function, 97 | 98 | /// @brief new-type statements 99 | ckx_token::type::tk_struct, 100 | ckx_token::type::tk_variant, 101 | ckx_token::type::tk_enum 102 | }; 103 | return ret; 104 | } 105 | 106 | const ckx_token_set& 107 | ckx_token_sets::close_scope_set() 108 | { 109 | static ckx_token_set ret = { ckx_token::type::tk_rbrace }; 110 | return ret; 111 | } 112 | 113 | const ckx_token_set& 114 | ckx_token_sets::close_declarator_set() 115 | { 116 | static ckx_token_set ret = 117 | { 118 | /// @brief usual termination 119 | ckx_token::type::tk_comma, 120 | ckx_token::type::tk_semicolon, 121 | ckx_token::type::tk_id, 122 | 123 | /// @brief any element may appear at next line 124 | /// if the current statement is not closed 125 | 126 | /// @brief elements may appear at the commence of a declaration 127 | ckx_token::type::tk_id, 128 | ckx_token::type::tk_vi8, 129 | ckx_token::type::tk_vi16, 130 | ckx_token::type::tk_vi32, 131 | ckx_token::type::tk_vi64, 132 | ckx_token::type::tk_vu8, 133 | ckx_token::type::tk_vu16, 134 | ckx_token::type::tk_vu32, 135 | ckx_token::type::tk_vu64, 136 | ckx_token::type::tk_vch, 137 | ckx_token::type::tk_vr32, 138 | ckx_token::type::tk_vr64, 139 | 140 | /// @brief elements may appear at the commence of an expression 141 | ckx_token::type::tk_add, 142 | ckx_token::type::tk_sub, 143 | ckx_token::type::tk_mul, 144 | ckx_token::type::tk_bit_and, 145 | ckx_token::type::tk_const_cast, 146 | ckx_token::type::tk_reinterpret_cast, 147 | ckx_token::type::tk_static_cast, 148 | ckx_token::type::tk_ckx_cast, 149 | 150 | /// @brief control-statements 151 | ckx_token::type::tk_if, 152 | ckx_token::type::tk_while, 153 | ckx_token::type::tk_do, 154 | ckx_token::type::tk_for, 155 | ckx_token::type::tk_break, 156 | ckx_token::type::tk_continue, 157 | ckx_token::type::tk_return, 158 | 159 | /// @brief may enter new scope 160 | ckx_token::type::tk_lbrace 161 | }; 162 | return ret; 163 | } 164 | 165 | const ckx_token_set& 166 | ckx_token_sets::close_struct_decl_set() 167 | { 168 | static ckx_token_set ret = 169 | { 170 | ckx_token::type::tk_rbrace, 171 | ckx_token::type::tk_semicolon, 172 | 173 | /// @brief elements may appear at the commence of a declaration 174 | /// @details identifier as typename 175 | ckx_token::type::tk_id, 176 | ckx_token::type::tk_vi8, 177 | ckx_token::type::tk_vi16, 178 | ckx_token::type::tk_vi32, 179 | ckx_token::type::tk_vi64, 180 | ckx_token::type::tk_vu8, 181 | ckx_token::type::tk_vu16, 182 | ckx_token::type::tk_vu32, 183 | ckx_token::type::tk_vu64, 184 | ckx_token::type::tk_vch, 185 | ckx_token::type::tk_vr32, 186 | ckx_token::type::tk_vr64, 187 | }; 188 | 189 | return ret; 190 | } 191 | 192 | } // namespace detail 193 | 194 | } // namespace detail 195 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_context_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/sema/ckx_context_manager.hpp" 2 | 3 | namespace ckx 4 | { 5 | 6 | ckx_context_manager::ckx_context_manager() 7 | { 8 | context_chain.push_back(new ckx_global_context()); 9 | } 10 | 11 | ckx_context_manager::~ckx_context_manager() 12 | { 13 | for (ckx_context *context : context_chain) 14 | delete context; 15 | } 16 | 17 | ckx_func_context* ckx_context_manager::lookup_func_context() 18 | { 19 | for (auto it = context_chain.rbegin(); it != context_chain.rend(); ++it) 20 | if ((*it)->type == ckx_context::context_type::cxt_func) 21 | return static_cast(*it); 22 | return nullptr; 23 | } 24 | 25 | ckx_if_context *ckx_context_manager::lookup_if_context() 26 | { 27 | for (auto it = context_chain.rbegin(); it != context_chain.rend(); ++it) 28 | if ((*it)->type == ckx_context::context_type::cxt_if) 29 | return static_cast(*it); 30 | return nullptr; 31 | } 32 | 33 | void ckx_context_manager::enter_func_context(ckx_func_type *_func_type) 34 | { 35 | context_chain.push_back(new ckx_func_context(_func_type)); 36 | } 37 | 38 | void ckx_context_manager::exit_func_context() 39 | { 40 | C8ASSERT(context_chain.back()->type == ckx_context::context_type::cxt_func); 41 | delete context_chain.back(); 42 | context_chain.pop_back(); 43 | } 44 | 45 | void ckx_context_manager::enter_if_context(ckx_if_context *_if_context) 46 | { 47 | context_chain.push_back(_if_context); 48 | } 49 | 50 | void ckx_context_manager::exit_if_context() 51 | { 52 | C8ASSERT(context_chain.back()->type == ckx_context::context_type::cxt_if); 53 | delete context_chain.back(); 54 | context_chain.pop_back(); 55 | } 56 | 57 | void ckx_context_manager::enter_while_context(ckx_while_context *_while_context) 58 | { 59 | context_chain.push_back(_while_context); 60 | } 61 | 62 | void ckx_context_manager::exit_while_context() 63 | { 64 | C8ASSERT(context_chain.back()->type ==ckx_context::context_type::cxt_while); 65 | delete context_chain.back(); 66 | context_chain.pop_back(); 67 | } 68 | 69 | ckx_context::context_type 70 | ckx_context_manager::current_context_type_intern() const 71 | { 72 | return context_chain.back()->type; 73 | } 74 | 75 | 76 | } // namespace ckx 77 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_env_table.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #include "frontend/sema/ckx_env_table.hpp" 20 | #include "frontend/sema/ckx_func_name_mangler.hpp" 21 | 22 | namespace ckx 23 | { 24 | 25 | bool 26 | ckx_env::lookup(saber_string_view _name) 27 | { 28 | return (lookup_var(_name) != nullptr) 29 | || (lookup_type(_name) != nullptr) 30 | || (lookup_var(_name) != nullptr); 31 | } 32 | 33 | bool 34 | ckx_env::lookup_local(saber_string_view _name) 35 | { 36 | return (lookup_var_local(_name) != nullptr) 37 | || (lookup_type_local(_name) != nullptr) 38 | || (lookup_func_local(_name) != nullptr); 39 | } 40 | 41 | ckx_env_var_entry* 42 | ckx_env::lookup_var(saber_string_view _name) 43 | { 44 | ckx_env *env_iter = this; 45 | while (env_iter != nullptr) 46 | { 47 | ckx_env_var_entry *entry = env_iter->lookup_var_local(_name); 48 | if (entry != nullptr) return entry; 49 | env_iter = env_iter->parent; 50 | } 51 | return nullptr; 52 | } 53 | 54 | ckx_env_type_entry* 55 | ckx_env::lookup_type(saber_string_view _name) 56 | { 57 | ckx_env *env_iter = this; 58 | while (env_iter != nullptr) 59 | { 60 | ckx_env_type_entry *entry = env_iter->lookup_type_local(_name); 61 | if (entry != nullptr) return entry; 62 | env_iter = env_iter->parent; 63 | } 64 | return nullptr; 65 | } 66 | 67 | saber::vector* 68 | ckx_env::lookup_func(saber_string_view _name) 69 | { 70 | ckx_env *env_iter = this; 71 | while (env_iter != nullptr) 72 | { 73 | saber::vector *entry = 74 | env_iter->lookup_func_local(_name); 75 | if (entry != nullptr) return entry; 76 | env_iter = env_iter->parent; 77 | } 78 | return nullptr; 79 | } 80 | 81 | ckx_env_var_entry* 82 | ckx_env::lookup_var_local(saber_string_view _name) 83 | { 84 | auto iter = vars.find(_name); 85 | if (iter != vars.end()) 86 | return &(iter->second); 87 | else 88 | return nullptr; 89 | } 90 | 91 | ckx_env_type_entry* 92 | ckx_env::lookup_type_local(saber_string_view _name) 93 | { 94 | auto iter = types.find(_name); 95 | if (iter != types.end()) 96 | return &(iter->second); 97 | else 98 | return nullptr; 99 | } 100 | 101 | saber::vector* 102 | ckx_env::lookup_func_local(saber_string_view _name) 103 | { 104 | auto iter = funcs.find(_name); 105 | if (iter != funcs.end()) 106 | return &(iter->second); 107 | else 108 | return nullptr; 109 | } 110 | 111 | saber::result 112 | ckx_env::add_var(ckx_src_rng _decl_at, saber_string_view _name, ckx_type* _type) 113 | { 114 | ckx_env_var_entry *entry = lookup_var_local(_name); 115 | if (entry != nullptr) 116 | return saber::result( 117 | saber::err_t(), err_add_var::err_status::conflict, entry); 118 | 119 | auto it = vars.emplace(_name, ckx_env_var_entry(_decl_at, _name, _type)) 120 | .first; 121 | return saber::result( 122 | saber::type_t(), &(it->second)); 123 | } 124 | 125 | saber::result 126 | ckx_env::add_type(ckx_src_rng _decl_at, saber_string_view _name, 127 | ckx_type *_type) 128 | { 129 | ckx_env_type_entry *entry = lookup_type(_name); 130 | if (entry != nullptr) 131 | return saber::result( 132 | saber::err_t(), err_add_type::err_status::conflict, entry); 133 | 134 | auto it = types.emplace(_name, ckx_env_type_entry(_decl_at, _name, _type)) 135 | .first; 136 | return saber::result( 137 | saber::type_t(), &(it->second)); 138 | } 139 | 140 | ckx_env::result_add_func 141 | ckx_env::add_func(ckx_src_rng _decl_at, saber_string_view _name, 142 | ckx_func_type* _type) 143 | { 144 | saber::vector* seen_funcs = lookup_func_local(_name); 145 | if (seen_funcs != nullptr) 146 | { 147 | for (ckx_env_func_entry &func : *seen_funcs) 148 | { 149 | if (func.type->get_param_type_list().size() 150 | != _type->get_param_type_list().size()) 151 | continue; 152 | 153 | bool all_params_same = [&](){ 154 | for (int i=0; i < func.type->get_param_type_list().size(); i++) 155 | if (!func.type->get_param_type_list()[i]->equal_to( 156 | _type->get_param_type_list()[i])) 157 | return false; 158 | return true; 159 | }(); 160 | 161 | if (!all_params_same) 162 | { 163 | seen_funcs->emplace_back( 164 | _decl_at, _name, _type, 165 | ckx_func_name_mangler::std_mangle(_name, _type)); 166 | return result_add_func(result_add_func::add_status::declare, 167 | &(seen_funcs->back())); 168 | } 169 | 170 | if (!func.type->get_return_type()->equal_to( 171 | _type->get_return_type())) 172 | { 173 | return result_add_func( 174 | result_add_func::add_status::conflict, &func); 175 | } 176 | else 177 | { 178 | return result_add_func( 179 | result_add_func::add_status::redeclare, &func); 180 | } 181 | } 182 | } 183 | 184 | auto it = funcs.emplace( 185 | _name, saber::vector{ 186 | ckx_env_func_entry(_decl_at, _name, _type, 187 | ckx_func_name_mangler::std_mangle(_name, _type)) 188 | }).first; 189 | return result_add_func(result_add_func::add_status::declare, 190 | &(it->second[0])); 191 | } 192 | 193 | } // namespace ckx 194 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_func_name_mangler.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/sema/ckx_func_name_mangler.hpp" 2 | #include "we/defs.hpp" 3 | #include 4 | 5 | static saber_string_view main_func = saber_string_pool::create_view("main"); 6 | 7 | namespace ckx 8 | { 9 | 10 | static saber_string qual2str(quint8 qual_bits) 11 | { 12 | saber_string ret; 13 | if (qual_bits & ckx_type::qual_const) ret += "c"; 14 | if (qual_bits & ckx_type::qual_volatile) ret += "v"; 15 | if (qual_bits & ckx_type::qual_restrict) ret += "r"; 16 | return ret; 17 | } 18 | 19 | static saber_string type2str(ckx_type *_type) 20 | { 21 | saber_string qual_str = qual2str(_type->get_qual_bits()); 22 | if (_type->is_basic()) 23 | { 24 | saber_string str; 25 | switch (_type->get_category()) 26 | { 27 | case ckx_type::category::type_vi8: str = "b"; break; 28 | case ckx_type::category::type_vi16: str = "s"; break; 29 | case ckx_type::category::type_vi32: str = "i"; break; 30 | case ckx_type::category::type_vi64: str = "l"; break; 31 | case ckx_type::category::type_vu8: str = "B"; break; 32 | case ckx_type::category::type_vu16: str = "S"; break; 33 | case ckx_type::category::type_vu32: str = "U"; break; 34 | case ckx_type::category::type_vu64: str = "L"; break; 35 | case ckx_type::category::type_vch: str = "K"; break; 36 | case ckx_type::category::type_vr32: str = "F"; break; 37 | case ckx_type::category::type_vr64: str = "D"; break; 38 | case ckx_type::category::type_vnullptr_t: str = "Pz"; break; 39 | case ckx_type::category::type_vbool: str = "Tf"; break; 40 | case ckx_type::category::type_void: str = "N"; break; 41 | default: 42 | C8ASSERT(false); // What the fuck! 43 | } 44 | return qual_str + str; 45 | } 46 | else if (_type->get_category() == ckx_type::category::type_struct) 47 | { 48 | ckx_struct_type *type = static_cast(_type); 49 | return qual_str + "Q" + type->get_name().get(); 50 | } 51 | else if (_type->get_category() == ckx_type::category::type_variant) 52 | { 53 | ckx_variant_type *type = static_cast(_type); 54 | return qual_str + "q" + type->get_name().get(); 55 | } 56 | else if (_type->get_category() == ckx_type::category::type_enum) 57 | { 58 | ckx_enum_type *type = static_cast(_type); 59 | return qual_str + "E" + type->get_name().get(); 60 | } 61 | else if (_type->get_category() == ckx_type::category::type_pointer) 62 | { 63 | ckx_pointer_type *type = static_cast(_type); 64 | return qual_str + "P" + type2str(type->get_pointee()); 65 | } 66 | else if (_type->get_category() == ckx_type::category::type_alias) 67 | { 68 | ckx_type_alias *alias = static_cast(_type); 69 | return qual_str + type2str(alias->get_aliasee()); 70 | } 71 | else 72 | { 73 | C8ASSERT(false); // What the fuck! 74 | } 75 | } 76 | 77 | saber_string_view 78 | ckx_func_name_mangler::std_mangle(saber_string_view _func_name, 79 | ckx_type *_func_type) 80 | { 81 | C8ASSERT(_func_type->get_category() == ckx_type::category::type_function); 82 | if (_func_name == main_func) 83 | return _func_name; 84 | ckx_func_type *func_type = reinterpret_cast(_func_type); 85 | saber_string func_appendix = "_"; 86 | for (ckx_type* type : func_type->get_param_type_list()) 87 | func_appendix += type2str(type); 88 | func_appendix += "_" + type2str(func_type->get_return_type()); 89 | return saber_string_pool::create_view( 90 | saber::string_paste(_func_name, func_appendix)); 91 | } 92 | 93 | saber_string_view 94 | ckx_func_name_mangler::simple_mangle(saber_string_view _func_name) 95 | { 96 | static std::atomic mangle_count {0}; 97 | if (_func_name == main_func) 98 | return _func_name; 99 | return saber_string_pool::create_view( 100 | saber::string_paste(_func_name, mangle_count++)); 101 | } 102 | 103 | saber_string_view 104 | ckx_func_name_mangler::prime(saber_string_view _func_name) 105 | { 106 | return _func_name; 107 | } 108 | 109 | }; 110 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_llvm_type_builder.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/sema/ckx_llvm_type_builder.hpp" 2 | 3 | namespace ckx 4 | { 5 | 6 | faker::llvm_type 7 | ckx_llvm_type_builder::build(ckx_type *_type) 8 | { 9 | static saber_string_view i8str = saber_string_pool::create_view("i8"); 10 | static saber_string_view i16str = saber_string_pool::create_view("i16"); 11 | static saber_string_view i32str = saber_string_pool::create_view("i32"); 12 | static saber_string_view i64str = saber_string_pool::create_view("i64"); 13 | static saber_string_view fstr = saber_string_pool::create_view("float"); 14 | static saber_string_view dstr = saber_string_pool::create_view("double"); 15 | static saber_string_view nullstr = saber_string_pool::create_view("i8*"); 16 | static saber_string_view i1str = saber_string_pool::create_view("i1"); 17 | static saber_string_view voidstr = saber_string_pool::create_view("void"); 18 | 19 | switch (_type->get_category()) 20 | { 21 | case ckx_type::category::type_vi8: 22 | case ckx_type::category::type_vu8: 23 | return i8str; 24 | 25 | case ckx_type::category::type_vi16: 26 | case ckx_type::category::type_vu16: 27 | return i16str; 28 | 29 | case ckx_type::category::type_vi32: 30 | case ckx_type::category::type_vu32: 31 | return i32str; 32 | 33 | case ckx_type::category::type_vi64: 34 | case ckx_type::category::type_vu64: 35 | return i64str; 36 | 37 | /// case ckx_type::category::type_vch: @note not implemented 38 | 39 | case ckx_type::category::type_vr32: 40 | return fstr; 41 | 42 | case ckx_type::category::type_vr64: 43 | return dstr; 44 | 45 | case ckx_type::category::type_vnullptr_t: 46 | return nullstr; 47 | 48 | case ckx_type::category::type_vbool: 49 | return i1str; 50 | 51 | case ckx_type::category::type_void: 52 | return voidstr; 53 | 54 | case ckx_type::category::type_function: 55 | { 56 | ckx_func_type *func_type = static_cast(_type); 57 | saber_string ret = build(func_type->get_return_type()).get() + "("; 58 | for (int i = 0; i < func_type->get_param_type_list().size(); ++i) 59 | { 60 | ret += build(func_type->get_param_type_list()[i]).get(); 61 | if (i != func_type->get_param_type_list().size()-1) 62 | ret += ','; 63 | } 64 | ret += ")"; 65 | return saber_string_pool::create_view(saber::move(ret)); 66 | } 67 | 68 | case ckx_type::category::type_struct: 69 | { 70 | ckx_struct_type *struct_type = static_cast(_type); 71 | return saber_string_pool::create_view( 72 | saber::string_paste( 73 | "%", full_name_for_struct(struct_type->get_name()))); 74 | } 75 | 76 | case ckx_type::category::type_variant: 77 | { 78 | ckx_variant_type *variant_type = 79 | static_cast(_type); 80 | return saber_string_pool::create_view( 81 | saber::string_paste( 82 | "%", full_name_for_variant(variant_type->get_name()))); 83 | } 84 | 85 | case ckx_type::category::type_enum: 86 | return i64str; 87 | 88 | case ckx_type::category::type_pointer: 89 | { 90 | ckx_pointer_type *ptr_type = static_cast(_type); 91 | return saber_string_pool::create_view( 92 | saber::string_paste(build(ptr_type->get_pointee()), "*")); 93 | } 94 | 95 | /// case ckx_type::category::type_array: @note deprecated and to be removed 96 | 97 | case ckx_type::category::type_alias: 98 | { 99 | ckx_type_alias *alias = static_cast(_type); 100 | return build(alias->get_aliasee()); 101 | } 102 | 103 | default: 104 | C8ASSERT(false); 105 | } 106 | } 107 | 108 | saber_string_view 109 | ckx_llvm_type_builder::full_name_for_struct(saber_string_view _origin) 110 | { 111 | return saber_string_pool::create_view( 112 | saber::string_paste("struct.", _origin)); 113 | } 114 | 115 | saber_string_view 116 | ckx_llvm_type_builder::full_name_for_variant(saber_string_view _origin) 117 | { 118 | return saber_string_pool::create_view( 119 | saber::string_paste("union.", _origin)); 120 | } 121 | 122 | } // namespace ckx 123 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_sema_test_suite.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/sema/ckx_sema.hpp" 2 | 3 | namespace ckx 4 | { 5 | 6 | void ckx_sema_engine::test_print(we::we_file_writer &writer) 7 | { 8 | builder.pretty_print(writer); 9 | } 10 | 11 | void ckx_sema_engine::test_enter_scope() 12 | { 13 | enter_scope(); 14 | } 15 | 16 | void ckx_sema_engine::test_leave_scope() 17 | { 18 | leave_scope(); 19 | } 20 | 21 | } // namespace ckx 22 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_translate.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/AST/ckx_ast_node.hpp" 2 | #include "frontend/sema/ckx_sema.hpp" 3 | #include "frontend/sema/ckx_sema_result.hpp" 4 | 5 | namespace ckx 6 | { 7 | 8 | /// @todo this is just for suppressing warnings. 9 | using bwsb = saber::optional; 10 | 11 | void ckx_ast_translation_unit::accept(ckx_sema_engine &_sema) 12 | { 13 | _sema.visit_translation_unit(this); 14 | } 15 | 16 | void ckx_ast_compound_stmt::accept(ckx_sema_engine& _sema) 17 | { 18 | _sema.visit_compound_stmt(this); 19 | } 20 | 21 | void ckx_ast_if_stmt::accept(ckx_sema_engine& _sema) 22 | { 23 | _sema.visit_if_stmt(this); 24 | } 25 | 26 | void ckx_ast_while_stmt::accept(ckx_sema_engine& _sema) 27 | { 28 | _sema.visit_while_stmt(this); 29 | } 30 | 31 | void ckx_ast_do_while_stmt::accept(ckx_sema_engine&) {} 32 | void ckx_ast_for_stmt::accept(ckx_sema_engine&) {} 33 | void ckx_ast_break_stmt::accept(ckx_sema_engine&) {} 34 | void ckx_ast_continue_stmt::accept(ckx_sema_engine&) {} 35 | 36 | void ckx_ast_return_stmt::accept(ckx_sema_engine& _sema) 37 | { 38 | _sema.visit_return_stmt(this); 39 | } 40 | 41 | void ckx_ast_decl_stmt::accept(ckx_sema_engine& _sema) 42 | { 43 | _sema.visit_decl_stmt(this); 44 | } 45 | 46 | void ckx_ast_expr_stmt::accept(ckx_sema_engine& _sema) 47 | { 48 | expr->accept(_sema); 49 | } 50 | 51 | void ckx_ast_func_stmt::accept(ckx_sema_engine& _sema) 52 | { 53 | _sema.visit_func_stmt(this); 54 | } 55 | 56 | void ckx_ast_record_stmt::accept(ckx_sema_engine& _sema) 57 | { 58 | _sema.visit_record_stmt(this); 59 | } 60 | 61 | void ckx_ast_alias_stmt::accept(ckx_sema_engine&) {} 62 | void ckx_ast_enum_stmt::accept(ckx_sema_engine&) {} 63 | 64 | saber::optional 65 | ckx_ast_binary_expr::accept(ckx_sema_engine& _sema) 66 | { 67 | return _sema.visit_binary_expr(this); 68 | } 69 | 70 | saber::optional 71 | ckx_ast_unary_expr::accept(ckx_sema_engine& _sema) 72 | { 73 | return _sema.visit_unary_expr(this); 74 | } 75 | 76 | saber::optional 77 | ckx_ast_subscript_expr::accept(ckx_sema_engine&) { return bwsb(); } 78 | 79 | saber::optional 80 | ckx_ast_invoke_expr::accept(ckx_sema_engine& _sema) 81 | { 82 | return _sema.visit_invoke_expr(this); 83 | } 84 | 85 | saber::optional 86 | ckx_ast_extract_expr::accept(ckx_sema_engine& _sema) 87 | { 88 | return _sema.visit_extract_expr(this); 89 | } 90 | 91 | saber::optional 92 | ckx_ast_enumerator_expr::accept(ckx_sema_engine&) { return bwsb(); } 93 | saber::optional 94 | ckx_ast_cond_expr::accept(ckx_sema_engine&) { return bwsb(); } 95 | 96 | saber::optional 97 | ckx_ast_id_expr::accept(ckx_sema_engine& _sema) 98 | { 99 | return _sema.visit_id_expr(this); 100 | } 101 | 102 | saber::optional 103 | ckx_ast_cast_expr::accept(ckx_sema_engine& _sema) 104 | { 105 | return _sema.visit_cast_expr(this); 106 | } 107 | 108 | saber::optional 109 | ckx_ast_sizeof_expr::accept(ckx_sema_engine&) { return bwsb(); } 110 | 111 | saber::optional 112 | ckx_ast_vi_literal_expr::accept(ckx_sema_engine& _sema) 113 | { 114 | return _sema.visit_vi_literal_node(this); 115 | } 116 | 117 | saber::optional 118 | ckx_ast_vr_literal_expr::accept(ckx_sema_engine& _sema) 119 | { 120 | return _sema.visit_vr_literal_node(this); 121 | } 122 | 123 | saber::optional 124 | ckx_ast_bool_literal_expr::accept(ckx_sema_engine& _sema) 125 | { 126 | return _sema.visit_vbool_literal_expr(this); 127 | } 128 | 129 | saber::optional 130 | ckx_ast_nullptr_expr::accept(ckx_sema_engine& _sema) 131 | { 132 | return _sema.visit_nullptr_expr(this); 133 | } 134 | 135 | saber::optional 136 | ckx_ast_array_expr::accept(ckx_sema_engine&) { return bwsb(); } 137 | 138 | } // namespace ckx 139 | -------------------------------------------------------------------------------- /src/frontend/sema/ckx_type_dump.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/sema/ckx_type.hpp" 2 | 3 | namespace ckx 4 | { 5 | 6 | saber_string ckx_type::qual_to_string() const 7 | { 8 | saber_string ret; 9 | if (qual & qual_const) ret += " const"; 10 | if (qual & qual_volatile) ret += " volatile"; 11 | if (qual & qual_restrict) ret += " restrict"; 12 | return ret; 13 | } 14 | 15 | saber_string 16 | ckx_basic_type::to_string() const 17 | { 18 | struct category_hash 19 | { 20 | bool operator() (category _ctg) const 21 | { 22 | return std::hash()(static_cast(_ctg)); 23 | } 24 | }; 25 | 26 | static saber::unordered_map 27 | typename_string_list 28 | { 29 | {category::type_vi8, "vi8"}, 30 | {category::type_vi16, "vi16"}, 31 | {category::type_vi32, "vi32"}, 32 | {category::type_vi64, "vi64"}, 33 | {category::type_vu8, "vu8"}, 34 | {category::type_vu16, "vu16"}, 35 | {category::type_vu32, "vu32"}, 36 | {category::type_vu64, "vu64"}, 37 | {category::type_vr32, "vr32"}, 38 | {category::type_vr64, "vr64"}, 39 | {category::type_vch, "vch"}, 40 | {category::type_vnullptr_t, "vnptr_t"}, 41 | {category::type_vbool, "vb1"}, 42 | {category::type_void, "void"} 43 | }; 44 | 45 | return typename_string_list.find(type_category)->second + qual_to_string(); 46 | } 47 | 48 | saber_string 49 | ckx_struct_type::to_string() const 50 | { 51 | return "StructType[[" + struct_name.get() + "]]" + qual_to_string(); 52 | } 53 | 54 | saber_string 55 | ckx_variant_type::to_string() const 56 | { 57 | return "VariantType[[" + variant_name.get() + "]]" + qual_to_string(); 58 | } 59 | 60 | saber_string 61 | ckx_enum_type::to_string() const 62 | { 63 | return "EnumType[[" + enum_name.get() + "]]" + qual_to_string(); 64 | } 65 | 66 | saber_string 67 | ckx_func_type::to_string() const 68 | { 69 | saber_string ret = "fn ("; 70 | for (const ckx_type* type : param_type_list) 71 | ret += type->to_string() + saber_string(","); 72 | ret += saber_string(") -> "); 73 | ret += return_type->to_string(); 74 | return ret + qual_to_string(); 75 | } 76 | 77 | saber_string 78 | ckx_pointer_type::to_string() const 79 | { 80 | return target->to_string() + saber_string(" *") + qual_to_string(); 81 | } 82 | 83 | saber_string 84 | ckx_array_type::to_string() const 85 | { 86 | return element_type->to_string() + "[]" + qual_to_string(); 87 | } 88 | 89 | saber_string ckx_type_alias::to_string() const 90 | { 91 | return "AliasTo[[" + origin->to_string() + "]]" + qual_to_string(); 92 | } 93 | 94 | } // namespace ckx 95 | -------------------------------------------------------------------------------- /src/llvm/llvm_ir_builder.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #include "llvm/llvm_ir_builder.hpp" 21 | #include "llvm/llvm_inst_detail.hpp" 22 | #include "llvm/llvm_ir_builder_impl.hpp" 23 | 24 | namespace faker 25 | { 26 | 27 | llvm_ir_builder::llvm_ir_builder() 28 | { 29 | impl = new detail::llvm_ir_builder_impl; 30 | } 31 | 32 | llvm_ir_builder::~llvm_ir_builder() 33 | { 34 | delete impl; 35 | } 36 | 37 | void llvm_ir_builder::pretty_print(we::we_file_writer &_writer) 38 | { 39 | impl->pretty_print(_writer); 40 | } 41 | 42 | void llvm_ir_builder::create_n_enter_func( 43 | llvm_type _return_type, saber_string_view _name, 44 | saber::vector &&_param_type_list, 45 | saber::vector _param_name_list, 46 | llvm_func_attrs _attrs) 47 | { 48 | impl->create_n_enter_func( 49 | _return_type, _name, 50 | saber::move(_param_type_list), saber::move(_param_name_list), _attrs); 51 | } 52 | 53 | void llvm_ir_builder::leave_func() 54 | { 55 | impl->leave_func(); 56 | } 57 | 58 | llvm_instruction *llvm_ir_builder::get_insert_point() 59 | { 60 | return impl->get_insert_point(); 61 | } 62 | 63 | void llvm_ir_builder::set_insert_after(llvm_instruction *_instruction) 64 | { 65 | impl->set_insert_after(_instruction); 66 | } 67 | 68 | llvm_instruction *llvm_ir_builder::create_func_decl( 69 | llvm_type _return_type, saber_string_view _name, 70 | saber::vector &&_param_type_list, 71 | saber::vector _param_name_list, 72 | llvm_func_attrs _attrs) 73 | { 74 | return impl->create_func_decl( 75 | _return_type, _name, 76 | saber::move(_param_type_list), saber::move(_param_name_list), _attrs); 77 | } 78 | 79 | llvm_instruction* 80 | llvm_ir_builder::create_return(llvm_type _type, llvm_value *_value) 81 | { 82 | return impl->create_return(_type, _value); 83 | } 84 | 85 | llvm_instruction* 86 | llvm_ir_builder::create_return_void() 87 | { 88 | return impl->create_return(saber_string_pool::create_view("void"), nullptr); 89 | } 90 | 91 | llvm_instruction* 92 | llvm_ir_builder::create_branch(llvm_label *_label) 93 | { 94 | return impl->create_branch(_label); 95 | } 96 | 97 | llvm_instruction* 98 | llvm_ir_builder::create_cond_branch(llvm_value *_cond, 99 | llvm_label *_true_label, 100 | llvm_label *_false_label) 101 | { 102 | return impl->create_cond_branch(_cond, _true_label, _false_label); 103 | } 104 | 105 | llvm_instruction* 106 | llvm_ir_builder::create_phi(llvm_value *_result, llvm_type _type, 107 | llvm_label *_label1, llvm_value *_val1, 108 | llvm_label *_label2, llvm_value *_val2) 109 | { 110 | return impl->create_phi(_result, _type, _label1, _val1, _label2, _val2); 111 | } 112 | 113 | llvm_instruction* 114 | llvm_ir_builder::create_call(llvm_value *_result, llvm_type _type, 115 | saber_string_view _func_name, 116 | saber::vector && _types, 117 | saber::vector &&_args) 118 | { 119 | return impl->create_call(_result, _type, _func_name, 120 | saber::move(_types), saber::move(_args)); 121 | } 122 | 123 | llvm_label* 124 | llvm_ir_builder::create_label(saber_string_view _name) 125 | { 126 | return impl->create_label(_name); 127 | } 128 | 129 | llvm_label *llvm_ir_builder::create_temporary_label() 130 | { 131 | return impl->create_temporary_label(); 132 | } 133 | 134 | 135 | COMMENT(BEGIN_BLOCK) 136 | # define BINOP(OPCODE) \ 137 | llvm_instruction* \ 138 | llvm_ir_builder::create_##OPCODE(llvm_value *_result, llvm_type _type,\ 139 | llvm_value* _lhs, llvm_value *_rhs) \ 140 | { \ 141 | return impl->create_binary_instruction( \ 142 | _result, llvm_binary_instruction::operator_type::ot_##OPCODE, \ 143 | _type, _lhs, _rhs); \ 144 | } 145 | 146 | # define CASTOP(OPCODE) \ 147 | llvm_instruction* \ 148 | llvm_ir_builder::create_##OPCODE(llvm_value *_result, llvm_type _src_type,\ 149 | llvm_value *_src, llvm_type _dest_type) \ 150 | { \ 151 | return impl->create_cast_instruction( \ 152 | _result, llvm_cast_instruction::operator_type::ot_##OPCODE, \ 153 | _src_type, _src, _dest_type); \ 154 | } 155 | 156 | # define CMPOP(OPCODE) \ 157 | llvm_instruction* \ 158 | llvm_ir_builder::create_##OPCODE(llvm_value *_result, llvm_type _type,\ 159 | llvm_value *_val1, llvm_value *_val2) \ 160 | { \ 161 | return impl->create_cmp_instruction( \ 162 | _result, llvm_cmp_instruction::comparsion_type::ot_##OPCODE, \ 163 | _type, _val1, _val2); \ 164 | } 165 | 166 | # include "llvm/opdef.hpp" 167 | # undef BINOP 168 | # undef CASTOP 169 | # undef CMPOP 170 | COMMENT(END_BLOCK) 171 | 172 | 173 | llvm_instruction* 174 | llvm_ir_builder::create_alloca(llvm_value *_result, 175 | llvm_type _type, quint32 _array_size) 176 | { 177 | return impl->create_alloca(_result, _type, _array_size); 178 | } 179 | 180 | llvm_instruction* 181 | llvm_ir_builder::create_load(llvm_value *_result, 182 | llvm_type _type, llvm_value *_ptr) 183 | { 184 | return impl->create_load(_result, _type, _ptr); 185 | } 186 | 187 | llvm_instruction* 188 | llvm_ir_builder::create_store(llvm_type _type, llvm_value *_src, 189 | llvm_value *_result) 190 | { 191 | return impl->create_store(_type, _src, _result); 192 | } 193 | 194 | llvm_instruction* 195 | llvm_ir_builder::create_extractvalue(llvm_value *_result, llvm_type _type, 196 | llvm_value *_value, llvm_value *_idx) 197 | { 198 | return impl->create_extractvalue(_result, _type, _value, _idx); 199 | } 200 | 201 | llvm_instruction* 202 | llvm_ir_builder::create_getelementptr(llvm_value *_result, 203 | llvm_type _type, llvm_value *_ptr, 204 | llvm_type _ty, llvm_value *_idx) 205 | { 206 | return impl->create_getelementptr(_result, _type, _ptr, _ty, _idx); 207 | } 208 | 209 | llvm_instruction* 210 | llvm_ir_builder::create_getelementptr2(llvm_value *_result, 211 | llvm_type _type, llvm_value *_ptr, 212 | llvm_type _ty1, llvm_value *_idx1, 213 | llvm_type _ty2, llvm_value *_idx2) 214 | { 215 | return impl->create_getelementptr2(_result, _type, _ptr, 216 | _ty1, _idx1, _ty2, _idx2); 217 | } 218 | 219 | llvm_instruction* 220 | llvm_ir_builder::create_udt(saber_string_view _name, 221 | saber::vector &&_fields) 222 | { 223 | return impl->create_udt(_name, saber::move(_fields)); 224 | } 225 | 226 | llvm_value *llvm_ir_builder::create_string_constant(saber_string_view _str) 227 | { 228 | return impl->create_string_constant(_str); 229 | } 230 | 231 | llvm_value *llvm_ir_builder::create_signed_constant(qint64 _i) 232 | { 233 | return impl->create_signed_constant(_i); 234 | } 235 | 236 | llvm_value *llvm_ir_builder::create_unsigned_constant(quint64 _u) 237 | { 238 | return impl->create_unsigned_constant(_u); 239 | } 240 | 241 | llvm_value *llvm_ir_builder::create_floating_constant(qreal _r) 242 | { 243 | return impl->create_floating_constant(_r); 244 | } 245 | 246 | llvm_value *llvm_ir_builder::create_bool_constant(bool _b) 247 | { 248 | return impl->create_bool_constant(_b); 249 | } 250 | 251 | llvm_value *llvm_ir_builder::create_null() 252 | { 253 | return impl->create_null(); 254 | } 255 | 256 | llvm_value *llvm_ir_builder::create_temporary_var() 257 | { 258 | return impl->create_temporary_var(); 259 | } 260 | 261 | llvm_value *llvm_ir_builder::create_named_var(saber_string_view _name) 262 | { 263 | return impl->create_named_var(_name); 264 | } 265 | 266 | 267 | } // namespace faker 268 | 269 | -------------------------------------------------------------------------------- /src/llvm/llvm_value.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | [[ The self-written "Faker" LLVM Builder part ]] 4 | Copyright (C) 2017 CousinZe 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU Affero General Public License as published 8 | by the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU Affero General Public License for more details. 15 | 16 | You should have received a copy of the GNU Affero General Public License 17 | along with this program. If not, see http://www.gnu.org/licenses/. 18 | */ 19 | 20 | #include "llvm/llvm_value_detail.hpp" 21 | 22 | namespace faker 23 | { 24 | 25 | llvm_value::~llvm_value() {} 26 | 27 | 28 | llvm_constant::llvm_constant(qint64 _val) : 29 | type(constant_type::ct_int) 30 | { 31 | v.i = _val; 32 | } 33 | 34 | llvm_constant::llvm_constant(quint64 _val) : 35 | type(constant_type::ct_uint) 36 | { 37 | v.u = _val; 38 | } 39 | 40 | llvm_constant::llvm_constant(qreal _val) : 41 | type(constant_type::ct_real) 42 | { 43 | v.r = _val; 44 | } 45 | 46 | llvm_constant::llvm_constant(decltype(nullptr)) : 47 | type(constant_type::ct_nullptr) 48 | { 49 | } 50 | 51 | llvm_constant::llvm_constant(bool _val) : 52 | type(constant_type::ct_bool) 53 | { 54 | v.b = _val; 55 | } 56 | 57 | llvm_constant::llvm_constant(saber_string_view _val) : 58 | type(constant_type::ct_string), 59 | str(_val) 60 | { 61 | } 62 | 63 | saber_string_view llvm_constant::to_string() 64 | { 65 | switch (type) 66 | { 67 | case constant_type::ct_bool: 68 | return saber_string_pool::create_view(saber::string_paste(v.b)); 69 | case constant_type::ct_int: 70 | return saber_string_pool::create_view(saber::string_paste(v.i)); 71 | case constant_type::ct_uint: 72 | return saber_string_pool::create_view(saber::string_paste(v.u)); 73 | case constant_type::ct_real: 74 | return saber_string_pool::create_view(saber::string_paste(v.r)); 75 | case constant_type::ct_string: 76 | return str; 77 | case constant_type::ct_nullptr: 78 | return saber_string_pool::create_view("null"); 79 | } 80 | } 81 | 82 | llvm_global::llvm_global(saber_string_view _name) : 83 | name(_name) {} 84 | 85 | saber_string_view llvm_global::to_string() 86 | { return saber_string_pool::create_view(""); } 87 | 88 | llvm_variable::llvm_variable(saber_string_view _name) : 89 | name(_name) {} 90 | 91 | saber_string_view llvm_variable::to_string() 92 | { 93 | return saber_string_pool::create_view( 94 | saber::string_paste("%", name)); 95 | } 96 | 97 | saber_string_view llvm_null::to_string() 98 | { 99 | return saber_string_pool::create_view("null"); 100 | } 101 | 102 | } // namespace faker 103 | -------------------------------------------------------------------------------- /src/llvm/main_as_test.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/llvm_ir_builder.hpp" 2 | #include 3 | 4 | int main() 5 | { 6 | /// @todo We are about to use `main` function for test 7 | /// (since I no more want to open individual projects) 8 | using namespace faker; 9 | using namespace std; 10 | using namespace we; 11 | 12 | saber_string_view llvm_i32_type = saber_string_pool::create_view("i32"); 13 | saber_string_view name_a = saber_string_pool::create_view("a"); 14 | saber_string_view name_b = saber_string_pool::create_view("b"); 15 | saber_string_view name_foo = saber_string_pool::create_view("foo"); 16 | saber_string_view name_bar = saber_string_pool::create_view("bar"); 17 | saber_string_view name_baz = saber_string_pool::create_view("baz"); 18 | llvm_func_attrs default_c_attrs = 19 | llvm_func_attrs(true, llvm_func_attrs::it_default); 20 | 21 | we_fp_writer stdwriter(stdout); 22 | 23 | { 24 | llvm_ir_builder builder; 25 | builder.create_n_enter_func(llvm_i32_type, 26 | saber_string_pool::create_view("add"), 27 | saber::vector{ 28 | llvm_i32_type, 29 | llvm_i32_type 30 | }, 31 | saber::vector{ 32 | saber_string_pool::create_view("a"), 33 | saber_string_pool::create_view("b"), 34 | }, 35 | default_c_attrs); 36 | llvm_value *temp_var_1 = builder.create_temporary_var(); 37 | llvm_value *arg_a = builder.create_named_var( 38 | saber_string_pool::create_view("a")); 39 | llvm_value *arg_b = builder.create_named_var( 40 | saber_string_pool::create_view("b")); 41 | builder.create_add(temp_var_1, llvm_i32_type, arg_a, arg_b); 42 | builder.create_return(llvm_i32_type, temp_var_1); 43 | builder.leave_func(); 44 | 45 | builder.pretty_print(stdwriter); 46 | } 47 | 48 | { 49 | llvm_ir_builder builder; 50 | 51 | builder.create_n_enter_func(llvm_i32_type, 52 | name_foo, 53 | saber::vector{llvm_i32_type}, 54 | saber::vector{name_bar}, 55 | default_c_attrs); 56 | llvm_value *arg_bar = builder.create_named_var(name_bar); 57 | llvm_value *zero = builder.create_signed_constant(0); 58 | llvm_value *temp_cmp_result = builder.create_temporary_var(); 59 | llvm_instruction* cond_expr_inst = builder.create_icmp_slt( 60 | temp_cmp_result, 61 | llvm_i32_type, arg_bar, zero); 62 | llvm_label * true_label = builder.create_temporary_label(); 63 | builder.create_return(llvm_i32_type, arg_bar); 64 | llvm_label * false_label = builder.create_temporary_label(); 65 | builder.create_return(llvm_i32_type, zero); 66 | builder.set_insert_after(cond_expr_inst); 67 | builder.create_cond_branch(temp_cmp_result, true_label, false_label); 68 | builder.leave_func(); 69 | 70 | builder.pretty_print(stdwriter); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/saber/safe_stl_general.cpp: -------------------------------------------------------------------------------- 1 | #include "saber/safe_stl_general.hpp" 2 | 3 | namespace saber 4 | { 5 | 6 | static FILE *fp = stderr; 7 | 8 | FILE *& fp_export(void) 9 | { 10 | return fp; 11 | } 12 | 13 | void set_export(FILE *_fp) 14 | { 15 | fp_export() = _fp; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/we/file_reader.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | 20 | #include "we/file_reader.hpp" 21 | #include 22 | 23 | namespace we 24 | { 25 | 26 | we_file_reader::~we_file_reader() {} 27 | 28 | namespace detail 29 | { 30 | 31 | class we_fp_reader_impl 32 | { 33 | public: 34 | explicit we_fp_reader_impl(std::FILE* _fp); 35 | ~we_fp_reader_impl() = default; 36 | 37 | inline qchar get_next_char_impl(); 38 | 39 | private: 40 | std::FILE *fp; 41 | }; 42 | 43 | 44 | class we_istream_reader_impl 45 | { 46 | public: 47 | explicit we_istream_reader_impl(std::istream& _stream); 48 | ~we_istream_reader_impl() = default; 49 | 50 | inline qchar get_next_char_impl(); 51 | 52 | private: 53 | std::istream& stream; 54 | }; 55 | 56 | } // namespace detail 57 | 58 | we_fp_reader::we_fp_reader(FILE *_fp) 59 | { 60 | this->impl = new detail::we_fp_reader_impl(_fp); 61 | } 62 | 63 | we_fp_reader::~we_fp_reader() 64 | { 65 | delete this->impl; 66 | } 67 | 68 | qchar we_fp_reader::get_next_char() 69 | { 70 | return this->impl->get_next_char_impl(); 71 | } 72 | 73 | 74 | we_istream_reader::we_istream_reader(std::istream &_stream) 75 | { 76 | this->impl = new detail::we_istream_reader_impl(_stream); 77 | } 78 | 79 | we_istream_reader::~we_istream_reader() 80 | { 81 | delete this->impl; 82 | } 83 | 84 | qchar we_istream_reader::get_next_char() 85 | { 86 | return this->impl->get_next_char_impl(); 87 | } 88 | 89 | namespace detail 90 | { 91 | 92 | we_fp_reader_impl::we_fp_reader_impl(FILE *_fp) : fp(_fp) {} 93 | 94 | inline qchar we_fp_reader_impl::get_next_char_impl() 95 | { 96 | qchar ret; 97 | if (~std::fscanf(fp, "%c", &ret)) return ret; 98 | else return static_cast(std::char_traits::eof()); 99 | } 100 | 101 | 102 | we_istream_reader_impl::we_istream_reader_impl(std::istream &_stream) : 103 | stream(_stream) 104 | {} 105 | 106 | inline qchar we_istream_reader_impl::get_next_char_impl() 107 | { 108 | qchar ch; 109 | return stream >> ch ? ch : 110 | static_cast(std::char_traits::eof()); 111 | } 112 | 113 | 114 | } // namespace detail 115 | 116 | } // namespace ckx 117 | -------------------------------------------------------------------------------- /src/we/file_writer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #include "we/file_writer.hpp" 20 | #include 21 | #include 22 | #include "saber/utility.hpp" 23 | 24 | namespace we 25 | { 26 | 27 | namespace detail 28 | { 29 | class we_fp_writer_impl 30 | { 31 | public: 32 | explicit we_fp_writer_impl(std::FILE* _fp); 33 | ~we_fp_writer_impl() = default; 34 | 35 | inline void write_impl(qint64 _value); 36 | inline void write_impl(quint64 _value); 37 | inline void write_impl(qreal _value); 38 | inline void write_impl(const qchar* _str); 39 | inline void write_impl(const saber_string& _str); 40 | inline void write_impl(saber_string_view _str_view); 41 | inline void write_whitespace_impl(qsizet _count); 42 | 43 | private: 44 | std::FILE* fp; 45 | }; 46 | 47 | class we_ostream_writer_impl 48 | { 49 | public: 50 | explicit we_ostream_writer_impl(std::ostream &_stream); 51 | ~we_ostream_writer_impl() = default; 52 | 53 | template inline void write_impl(AnyType&& _any_v); 54 | inline void write_impl(saber_string_view _str); 55 | inline void write_whitespace_impl(qsizet _count); 56 | 57 | private: 58 | std::ostream& stream; 59 | }; 60 | 61 | } // namespace detail 62 | 63 | 64 | we_file_writer::~we_file_writer() 65 | {} 66 | 67 | 68 | we_fp_writer::we_fp_writer(std::FILE *_fp) 69 | { 70 | impl = new detail::we_fp_writer_impl(_fp); 71 | } 72 | 73 | we_fp_writer::~we_fp_writer() 74 | { 75 | delete impl; 76 | } 77 | 78 | void we_fp_writer::write(qint64 _value) 79 | { 80 | impl->write_impl(qint64(_value)); 81 | } 82 | 83 | void we_fp_writer::write(quint64 _value) 84 | { 85 | impl->write_impl(quint64(_value)); 86 | } 87 | 88 | void we_fp_writer::write(qreal _value) 89 | { 90 | impl->write_impl(_value); 91 | } 92 | 93 | void we_fp_writer::write(const qchar *_str) 94 | { 95 | impl->write_impl(_str); 96 | } 97 | 98 | void we_fp_writer::write(const saber_string &_str) 99 | { 100 | impl->write_impl(_str); 101 | } 102 | 103 | void we_fp_writer::write(saber_string_view _str_view) 104 | { 105 | impl->write_impl(_str_view); 106 | } 107 | 108 | void we_fp_writer::write_whitespace(qsizet _count) 109 | { 110 | impl->write_whitespace_impl(_count); 111 | } 112 | 113 | 114 | we_ostream_writer::we_ostream_writer(std::ostream &_stream) 115 | { 116 | impl = new detail::we_ostream_writer_impl(_stream); 117 | } 118 | 119 | we_ostream_writer::~we_ostream_writer() 120 | { 121 | delete impl; 122 | } 123 | 124 | void we_ostream_writer::write(qint64 _value) 125 | { 126 | impl->write_impl(qint64(_value)); 127 | } 128 | 129 | void we_ostream_writer::write(quint64 _value) 130 | { 131 | impl->write_impl(quint64(_value)); 132 | } 133 | 134 | void we_ostream_writer::write(qreal _value) 135 | { 136 | impl->write_impl(_value); 137 | } 138 | 139 | void we_ostream_writer::write(const qchar *_str) 140 | { 141 | impl->write_impl(_str); 142 | } 143 | 144 | void we_ostream_writer::write(const saber_string &_str) 145 | { 146 | impl->write_impl(_str); 147 | } 148 | 149 | void we_ostream_writer::write(saber_string_view _str_view) 150 | { 151 | impl->write_impl(_str_view); 152 | } 153 | 154 | void we_ostream_writer::write_whitespace(qsizet _count) 155 | { 156 | impl->write_whitespace_impl(_count); 157 | } 158 | 159 | 160 | namespace detail 161 | { 162 | 163 | we_fp_writer_impl::we_fp_writer_impl(std::FILE *_fp) : 164 | fp(_fp) 165 | {} 166 | 167 | inline void we_fp_writer_impl::write_impl(qint64 _value) 168 | { 169 | std::fprintf(fp, "%" PRId64, _value); 170 | } 171 | 172 | inline void we_fp_writer_impl::write_impl(quint64 _value) 173 | { 174 | std::fprintf(fp, "%" PRIu64, _value); 175 | } 176 | 177 | inline void we_fp_writer_impl::write_impl(qreal _value) 178 | { 179 | std::fprintf(fp, "%lf", _value); 180 | } 181 | 182 | inline void we_fp_writer_impl::write_impl(const qchar *_str) 183 | { 184 | std::fprintf(fp, "%s", _str); 185 | } 186 | 187 | inline void we_fp_writer_impl::write_impl(const saber_string &_str) 188 | { 189 | std::fprintf(fp, "%s", _str.c_str()); 190 | } 191 | 192 | inline void we_fp_writer_impl::write_impl(saber_string_view _str_view) 193 | { 194 | std::fprintf(fp, "%s", _str_view.get().c_str()); 195 | } 196 | 197 | inline void we_fp_writer_impl::write_whitespace_impl(qsizet _count) 198 | { 199 | for (qsizet i = 0; i < _count; i++) std::fputc(' ', fp); 200 | } 201 | 202 | 203 | we_ostream_writer_impl::we_ostream_writer_impl(std::ostream &_stream) : 204 | stream(_stream) 205 | {} 206 | 207 | template 208 | inline void we_ostream_writer_impl::write_impl(AnyType&& _any_v) 209 | { 210 | stream << saber::forward(_any_v); 211 | } 212 | 213 | inline void we_ostream_writer_impl::write_impl(saber_string_view _str_view) 214 | { 215 | stream << _str_view.get(); 216 | } 217 | 218 | inline void we_ostream_writer_impl::write_whitespace_impl(qsizet _count) 219 | { 220 | for (qsizet i = 0; i < _count; i++) stream.put(' '); 221 | } 222 | 223 | } // namespace detail 224 | 225 | } // namespace ckx 226 | -------------------------------------------------------------------------------- /test-codeship: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/parse/test_parse_decl/test_decl.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Affero General Public License for more details. 13 | 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see http://www.gnu.org/licenses/. 16 | */ 17 | 18 | /// @note This file contains a MANUAL test. Debuggers should read the log 19 | /// themselves and manually detect bugs. 20 | 21 | #include "frontend/parse/ckx_parser_impl.hpp" 22 | #include "saber/memory.hpp" 23 | 24 | using namespace ckx; 25 | 26 | class ckx_test_filereader final implements we::we_file_reader 27 | { 28 | public: 29 | ckx_test_filereader(saber_string&& _str) : str(saber::move(_str)) {} 30 | ~ckx_test_filereader() = default; 31 | qchar get_next_char(void) override final 32 | { 33 | pos++; 34 | if (pos-1 < str.size()) return str[pos-1]; 35 | else return static_cast(saber::char_traits::eof()); 36 | } 37 | 38 | private: 39 | qsizet pos = 0; 40 | saber_string str; 41 | }; 42 | 43 | 44 | 45 | class ckx_parser_impl_test final : 46 | public detail::ckx_parser_impl 47 | { 48 | using base = detail::ckx_parser_impl; 49 | 50 | public: 51 | void test(); 52 | void test_array_decl(); 53 | 54 | private: 55 | void initialize_test(); 56 | void cleanup_test(); 57 | }; 58 | 59 | 60 | 61 | int main() 62 | { 63 | ckx_parser_impl_test test; 64 | test.test(); 65 | test.test_array_decl(); 66 | return 0; 67 | } 68 | 69 | 70 | void 71 | ckx_parser_impl_test::test() 72 | { 73 | we::we_fp_writer writer { stdout }; 74 | 75 | { 76 | ckx_test_filereader reader {"vi8 a, b;"}; 77 | base::token_stream = new ckx_token_stream(reader); 78 | initialize_test(); 79 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 80 | decl->ast_dump(writer, 0); 81 | delete decl; 82 | 83 | assert(base::error_list.empty()); 84 | assert(base::warn_list.empty()); 85 | cleanup_test(); 86 | } 87 | 88 | { 89 | ckx_test_filereader reader {"vi8 * const array;"}; 90 | base::token_stream = new ckx_token_stream(reader); 91 | initialize_test(); 92 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 93 | decl->ast_dump(writer, 0); 94 | delete decl; 95 | 96 | assert(base::error_list.empty()); 97 | assert(base::warn_list.empty()); 98 | cleanup_test(); 99 | } 100 | 101 | { 102 | ckx_test_filereader reader {"vr32 a = 5+2, b = a*3+2;"}; 103 | base::token_stream = new ckx_token_stream(reader); 104 | initialize_test(); 105 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 106 | decl->ast_dump(writer, 0); 107 | delete decl; 108 | 109 | assert(base::error_list.empty()); 110 | assert(base::warn_list.empty()); 111 | cleanup_test(); 112 | } 113 | 114 | { 115 | ckx_test_filereader reader {"student const * pcstudent;"}; 116 | base::token_stream = new ckx_token_stream(reader); 117 | initialize_test(); 118 | base::typename_table.add_typename( 119 | saber_string_pool::create_view("student")); 120 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 121 | decl->ast_dump(writer, 0); 122 | delete decl; 123 | 124 | assert(base::error_list.empty()); 125 | assert(base::warn_list.empty()); 126 | cleanup_test(); 127 | } 128 | 129 | { 130 | ckx_test_filereader reader {"vnptr_t p = nullptr;"}; 131 | base::token_stream = new ckx_token_stream(reader); 132 | initialize_test(); 133 | base::typename_table.add_typename( 134 | saber_string_pool::create_view("student")); 135 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 136 | decl->ast_dump(writer, 0); 137 | delete decl; 138 | 139 | assert(base::error_list.empty()); 140 | assert(base::warn_list.empty()); 141 | cleanup_test(); 142 | } 143 | 144 | { 145 | ckx_test_filereader reader {"vb1 n = true;"}; 146 | base::token_stream = new ckx_token_stream(reader); 147 | initialize_test(); 148 | base::typename_table.add_typename( 149 | saber_string_pool::create_view("student")); 150 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 151 | decl->ast_dump(writer, 0); 152 | delete decl; 153 | 154 | assert(base::error_list.empty()); 155 | assert(base::warn_list.empty()); 156 | cleanup_test(); 157 | } 158 | } 159 | 160 | 161 | void ckx_parser_impl_test::test_array_decl() 162 | { 163 | we::we_fp_writer writer { stdout }; 164 | 165 | { 166 | ckx_test_filereader reader { "vi8[] array = vi8[](5){1, 2, 3, 4, 5};" }; 167 | base::token_stream = new ckx_token_stream(reader); 168 | initialize_test(); 169 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 170 | decl->ast_dump(writer, 0); 171 | delete decl; 172 | 173 | assert(base::error_list.empty()); 174 | assert(base::warn_list.empty()); 175 | cleanup_test(); 176 | } 177 | 178 | { 179 | ckx_test_filereader reader { "vi8[] array = vi8[]()(bptr, bptr+5);"}; 180 | base::token_stream = new ckx_token_stream(reader); 181 | initialize_test(); 182 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 183 | decl->ast_dump(writer, 0); 184 | delete decl; 185 | 186 | assert(base::error_list.empty()); 187 | assert(base::warn_list.empty()); 188 | cleanup_test(); 189 | } 190 | 191 | { 192 | ckx_test_filereader reader { "vi8[] array = vi8[](5)(bptr);"}; 193 | base::token_stream = new ckx_token_stream(reader); 194 | initialize_test(); 195 | ckx_ast_decl_stmt *decl = base::parse_decl_stmt(); 196 | decl->ast_dump(writer, 0); 197 | delete decl; 198 | 199 | assert(base::error_list.empty()); 200 | assert(base::warn_list.empty()); 201 | cleanup_test(); 202 | } 203 | } 204 | 205 | 206 | void 207 | ckx_parser_impl_test::initialize_test() 208 | { 209 | } 210 | 211 | 212 | void 213 | ckx_parser_impl_test::cleanup_test() 214 | { 215 | base::typename_table.cleanup(); 216 | delete base::token_stream; 217 | } 218 | -------------------------------------------------------------------------------- /test/parse/test_parse_func/test_func.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Affero General Public License for more details. 13 | 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see http://www.gnu.org/licenses/. 16 | */ 17 | 18 | /// @note This file contains a MANUAL test. Debuggers should read the log 19 | /// themselves and manually detect bugs. 20 | 21 | #include "frontend/parse/ckx_parser_impl.hpp" 22 | #include "saber/memory.hpp" 23 | #include "saber/c8assert.hpp" 24 | 25 | using namespace ckx; 26 | 27 | class ckx_test_filereader final implements we::we_file_reader 28 | { 29 | public: 30 | ckx_test_filereader(saber_string&& _str) : str(saber::move(_str)) {} 31 | ~ckx_test_filereader() = default; 32 | qchar get_next_char(void) override final 33 | { 34 | pos++; 35 | if (pos-1 < str.size()) return str[pos-1]; 36 | else return static_cast(saber::char_traits::eof()); 37 | } 38 | 39 | private: 40 | qsizet pos = 0; 41 | saber_string str; 42 | }; 43 | 44 | 45 | class ckx_parser_impl_test final : 46 | public detail::ckx_parser_impl 47 | { 48 | using base = detail::ckx_parser_impl; 49 | 50 | public: 51 | void test_parse_func_decl(); 52 | void test_parse_func_def(); 53 | 54 | private: 55 | void initialize_test(); 56 | void cleanup_test(); 57 | }; 58 | 59 | 60 | 61 | int main() 62 | { 63 | ckx_parser_impl_test test; 64 | test.test_parse_func_decl(); 65 | test.test_parse_func_def(); 66 | return 0; 67 | } 68 | 69 | 70 | 71 | void 72 | ckx_parser_impl_test::test_parse_func_decl() 73 | { 74 | we::we_fp_writer writer { stdout }; 75 | 76 | { 77 | ckx_test_filereader reader 78 | { "fn add (vi8 a, vi8 b) : vi8;" }; 79 | base::token_stream = new ckx_token_stream(reader); 80 | initialize_test(); 81 | 82 | ckx_ast_func_stmt *func = base::parse_func_stmt(); 83 | func->ast_dump(writer, 0); 84 | delete func; 85 | 86 | C8ASSERT(base::error_list.empty()); 87 | C8ASSERT(base::warn_list.empty()); 88 | cleanup_test(); 89 | base::token_stream = nullptr; 90 | } 91 | 92 | { 93 | ckx_test_filereader reader 94 | { "fn heap_alloc (vu32 sz) : vi8*;" }; 95 | base::token_stream = new ckx_token_stream(reader); 96 | initialize_test(); 97 | 98 | ckx_ast_func_stmt *func = base::parse_func_stmt(); 99 | func->ast_dump(writer, 0); 100 | delete func; 101 | 102 | C8ASSERT(base::error_list.empty()); 103 | C8ASSERT(base::warn_list.empty()); 104 | cleanup_test(); 105 | base::token_stream = nullptr; 106 | } 107 | 108 | { 109 | ckx_test_filereader reader 110 | { "fn CreateStudent (vi8 const * name,\n" 111 | " vi8 chinese,\n" 112 | " vi8 math) : Student* const;" }; 113 | base::token_stream = new ckx_token_stream(reader); 114 | initialize_test(); 115 | base::typename_table.add_typename( 116 | saber_string_pool::create_view("Student")); 117 | 118 | ckx_ast_func_stmt *func = base::parse_func_stmt(); 119 | func->ast_dump(writer, 0); 120 | delete func; 121 | 122 | C8ASSERT(base::error_list.empty()); 123 | C8ASSERT(base::warn_list.empty()); 124 | cleanup_test(); 125 | base::token_stream = nullptr; 126 | } 127 | 128 | { 129 | ckx_test_filereader reader { "fn main(): vi32;" }; 130 | base::token_stream = new ckx_token_stream(reader); 131 | initialize_test(); 132 | base::typename_table.add_typename( 133 | saber_string_pool::create_view("Student")); 134 | 135 | ckx_ast_func_stmt *func = base::parse_func_stmt(); 136 | func->ast_dump(writer, 0); 137 | delete func; 138 | 139 | C8ASSERT(base::error_list.empty()); 140 | C8ASSERT(base::warn_list.empty()); 141 | cleanup_test(); 142 | base::token_stream = nullptr; 143 | } 144 | } 145 | 146 | 147 | void 148 | ckx_parser_impl_test::test_parse_func_def() 149 | { 150 | we::we_fp_writer writer { stdout }; 151 | 152 | { 153 | const char* str = 154 | R"cpp( 155 | fn fibonacci(vu64 n) : vu64 156 | { 157 | if (n == 0) return 0; 158 | if (n == 1) return 1; 159 | return fibonacci(n-1) + fibonacci(n-2); 160 | } 161 | )cpp"; 162 | 163 | ckx_test_filereader reader { str }; 164 | base::token_stream = new ckx_token_stream(reader); 165 | initialize_test(); 166 | base::typename_table.add_typename( 167 | saber_string_pool::create_view("Student")); 168 | 169 | ckx_ast_func_stmt *func = base::parse_func_stmt(); 170 | func->ast_dump(writer, 0); 171 | delete func; 172 | 173 | C8ASSERT(base::error_list.empty()); 174 | C8ASSERT(base::warn_list.empty()); 175 | cleanup_test(); 176 | base::token_stream = nullptr; 177 | } 178 | } 179 | 180 | 181 | void 182 | ckx_parser_impl_test::initialize_test() 183 | { 184 | } 185 | 186 | 187 | void 188 | ckx_parser_impl_test::cleanup_test() 189 | { 190 | base::typename_table.cleanup(); 191 | delete base::token_stream; 192 | } 193 | -------------------------------------------------------------------------------- /test/parse/test_parse_udt/test_udt.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Affero General Public License for more details. 13 | 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see http://www.gnu.org/licenses/. 16 | */ 17 | 18 | /// @note This file contains a MANUAL test. Debuggers should read the log 19 | /// themselves and manually detect bugs. 20 | 21 | #include "frontend/parse/ckx_parser_impl.hpp" 22 | #include "saber/memory.hpp" 23 | #include "saber/c8assert.hpp" 24 | 25 | using namespace ckx; 26 | 27 | class ckx_test_filereader final implements we::we_file_reader 28 | { 29 | public: 30 | ckx_test_filereader(saber_string&& _str) : str(saber::move(_str)) {} 31 | ~ckx_test_filereader() = default; 32 | qchar get_next_char(void) override final 33 | { 34 | pos++; 35 | if (pos-1 < str.size()) return str[pos-1]; 36 | else return static_cast(saber::char_traits::eof()); 37 | } 38 | 39 | private: 40 | qsizet pos = 0; 41 | saber_string str; 42 | }; 43 | 44 | 45 | class ckx_parser_impl_test final : 46 | public detail::ckx_parser_impl 47 | { 48 | using base = detail::ckx_parser_impl; 49 | 50 | public: 51 | void test_parse_struct(); 52 | /// @note we are not about to deal with variant type 53 | /// since the processing of variant is identical with struct 54 | /// void test_parse_variant(); 55 | void test_parse_enum(); 56 | void test_parse_alias(); 57 | 58 | private: 59 | void initialize_test(); 60 | void cleanup_test(); 61 | }; 62 | 63 | 64 | 65 | int main() 66 | { 67 | ckx_parser_impl_test test; 68 | test.test_parse_struct(); 69 | test.test_parse_enum(); 70 | test.test_parse_alias(); 71 | 72 | return 0; 73 | } 74 | 75 | 76 | 77 | void 78 | ckx_parser_impl_test::test_parse_struct() 79 | { 80 | we::we_fp_writer writer { stdout }; 81 | 82 | { 83 | const char* str = 84 | R"noip( 85 | struct student { 86 | vi8 const* name; 87 | vu8 chinese, math, english; 88 | } 89 | )noip"; 90 | 91 | ckx_test_filereader reader { str }; 92 | base::token_stream = new ckx_token_stream(reader); 93 | initialize_test(); 94 | ckx_ast_record_stmt *stmt = base::parse_record_stmt(); 95 | stmt->ast_dump(writer, 0); 96 | delete stmt; 97 | C8ASSERT(base::error_list.empty()); 98 | C8ASSERT(base::warn_list.empty()); 99 | cleanup_test(); 100 | } 101 | 102 | { 103 | const char* str = 104 | R"noip( 105 | struct listNode { 106 | vi8 * const data; 107 | listNode * next; 108 | } 109 | )noip"; 110 | 111 | ckx_test_filereader reader { str }; 112 | base::token_stream = new ckx_token_stream(reader); 113 | initialize_test(); 114 | ckx_ast_record_stmt *stmt = base::parse_record_stmt(); 115 | stmt->ast_dump(writer, 0); 116 | delete stmt; 117 | C8ASSERT(base::error_list.empty()); 118 | C8ASSERT(base::warn_list.empty()); 119 | cleanup_test(); 120 | } 121 | } 122 | 123 | 124 | void 125 | ckx_parser_impl_test::test_parse_enum() 126 | { 127 | we::we_fp_writer writer { stdout }; 128 | 129 | { 130 | const char* str = 131 | R"noip( 132 | enum color { 133 | red = 1, 134 | yellow = 2, 135 | blue = 3 136 | } 137 | )noip"; 138 | ckx_test_filereader reader { str }; 139 | base::token_stream = new ckx_token_stream(reader); 140 | initialize_test(); 141 | ckx_ast_enum_stmt *stmt = base::parse_enum_stmt(); 142 | stmt->ast_dump(writer, 0); 143 | delete stmt; 144 | 145 | C8ASSERT(base::error_list.empty()); 146 | C8ASSERT(base::warn_list.empty()); 147 | cleanup_test(); 148 | } 149 | } 150 | 151 | 152 | void 153 | ckx_parser_impl_test::test_parse_alias() 154 | { 155 | we::we_fp_writer writer { stdout }; 156 | 157 | { 158 | ckx_test_filereader reader { "alias pcvi8 = vi8 const *;" }; 159 | base::token_stream = new ckx_token_stream(reader); 160 | initialize_test(); 161 | ckx_ast_alias_stmt *stmt = base::parse_alias_stmt(); 162 | stmt->ast_dump(writer, 0); 163 | delete stmt; 164 | C8ASSERT(base::error_list.empty()); 165 | C8ASSERT(base::warn_list.empty()); 166 | cleanup_test(); 167 | } 168 | } 169 | 170 | 171 | void 172 | ckx_parser_impl_test::initialize_test() 173 | { 174 | } 175 | 176 | 177 | void 178 | ckx_parser_impl_test::cleanup_test() 179 | { 180 | base::typename_table.cleanup(); 181 | delete base::token_stream; 182 | } 183 | -------------------------------------------------------------------------------- /test/parse/test_parser/test_parser.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | The Opensource Compiler CKX -- for my honey ChenKX 3 | Copyright (C) 2017 CousinZe 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU Affero General Public License as published 7 | by the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU Affero General Public License for more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with this program. If not, see http://www.gnu.org/licenses/. 17 | */ 18 | 19 | #include "frontend/parse/ckx_parser_impl.hpp" 20 | #include "saber/memory.hpp" 21 | #include "saber/c8assert.hpp" 22 | 23 | #include 24 | 25 | int main(int argc, const char* argv[]) 26 | { 27 | using namespace ckx; 28 | 29 | if (argc != 2) 30 | { 31 | std::printf("Requires input file.\n"); 32 | return -1; 33 | } 34 | 35 | std::FILE* fp = std::fopen(argv[1], "r"); 36 | if (fp == nullptr) 37 | { 38 | std::printf("File not found.\n"); 39 | return -1; 40 | } 41 | 42 | we::we_fp_reader reader(fp); 43 | we::we_fp_writer writer(stdout); 44 | ckx_token_stream *stream = new ckx_token_stream(reader); 45 | 46 | ckx_parser parser; 47 | auto parse_result = parser.parse(stream); 48 | parse_result.trans_unit->ast_dump(writer, 0); 49 | 50 | for (auto &error : parse_result.error_list) 51 | { 52 | std::printf("At (%hu,%hu):", error.rng.begin_line, error.rng.begin_col); 53 | std::printf("Error -- %s \n", error.desc.get().c_str()); 54 | } 55 | 56 | delete stream; 57 | 58 | std::fclose(fp); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /test/sema/test1.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/lex/ckx_token_stream.hpp" 2 | #include "frontend/parse/ckx_parser.hpp" 3 | #include "frontend/sema/ckx_sema.hpp" 4 | #include "saber/string_pool.hpp" 5 | 6 | saber_string str = 7 | R"cc( 8 | 9 | fn heap_alloc(vi64 size): vnptr_t; 10 | fn heap_free(void* ptr): void; 11 | 12 | fn input(vi8* ptr): void; 13 | fn print(vi8 number): void; 14 | 15 | fn main(): vi32 { 16 | vi8 *array = heap_alloc(4); 17 | input(array); 18 | input(array + 1); 19 | input(array + 2); 20 | *(array+3) = *(array+1) * *(array+2) + *(array); 21 | print(*array+3); 22 | return 0; 23 | } 24 | 25 | )cc"; 26 | 27 | int main() 28 | { 29 | using namespace ckx; 30 | using namespace we; 31 | 32 | we_test_filereader reader1(saber::move(str)); 33 | ckx_token_stream stream1(reader1); 34 | 35 | ckx_parser parser1; 36 | ckx_parser::parse_result parse_result = parser1.parse(&stream1); 37 | 38 | ckx_sema_engine engine; 39 | parse_result.trans_unit->accept(engine); 40 | 41 | we_fp_writer writer(stdout); 42 | engine.test_print(writer); 43 | } 44 | -------------------------------------------------------------------------------- /test/sema/test2.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/lex/ckx_token_stream.hpp" 2 | #include "frontend/parse/ckx_parser.hpp" 3 | #include "frontend/sema/ckx_sema.hpp" 4 | #include "saber/string_pool.hpp" 5 | 6 | saber_string str = 7 | R"cc( 8 | 9 | struct s { vi8 a; vi16 b, c; s* d; } 10 | 11 | fn one(): vi32 { 12 | return 1; 13 | } 14 | 15 | fn foo(vi8 a, vi8 b): vi8; 16 | fn bar(vi16 a, vi8* const b): void; 17 | fn baz(s s1): void; 18 | 19 | fn main(vi8 argc, vi8** argv): vi32 { 20 | vi8 c; 21 | vi32 a = 5, b = 65536; 22 | vi8 d = 0; 23 | s s1; 24 | return d; 25 | } 26 | 27 | )cc"; 28 | 29 | int main() 30 | { 31 | using namespace ckx; 32 | using namespace we; 33 | 34 | we_test_filereader reader1(saber::move(str)); 35 | ckx_token_stream stream1(reader1); 36 | 37 | ckx_parser parser1; 38 | ckx_parser::parse_result parse_result = parser1.parse(&stream1); 39 | 40 | ckx_sema_engine engine; 41 | parse_result.trans_unit->accept(engine); 42 | 43 | we_fp_writer writer(stdout); 44 | engine.test_print(writer); 45 | } 46 | -------------------------------------------------------------------------------- /test/sema/test3.cpp: -------------------------------------------------------------------------------- 1 | #include "frontend/lex/ckx_token_stream.hpp" 2 | #include "frontend/parse/ckx_parser.hpp" 3 | #include "frontend/sema/ckx_sema.hpp" 4 | #include "saber/string_pool.hpp" 5 | 6 | saber_string str = 7 | R"cc( 8 | 9 | fn add(vr64 a, vr64 b): vr64; 10 | fn add(vi64 a, vi64 b): vi64; 11 | fn print(vr64 number): vr64; 12 | fn print(vi64 number): vi64; 13 | fn print(vi8 number): vi8; 14 | fn input(vi32 *p): vi32; 15 | fn input(vr64 *p): vr64; 16 | 17 | fn heap_alloc(): vi8*; 18 | 19 | fn main(): vi32 { 20 | vr64 a, b; 21 | input(&a); 22 | input(&b); 23 | print(add(a, b)); 24 | vi32 c, d; 25 | input(&c); 26 | input(&d); 27 | print(add(c, d)); 28 | vi8* e = heap_alloc(); 29 | (*e) = 5; 30 | print(*e); 31 | print(*heap_alloc()); 32 | return 0; 33 | } 34 | 35 | )cc"; 36 | 37 | int main() 38 | { 39 | using namespace ckx; 40 | using namespace we; 41 | 42 | we_test_filereader reader1(saber::move(str)); 43 | ckx_token_stream stream1(reader1); 44 | 45 | ckx_parser parser1; 46 | ckx_parser::parse_result parse_result = parser1.parse(&stream1); 47 | 48 | ckx_sema_engine engine; 49 | parse_result.trans_unit->accept(engine); 50 | 51 | we_fp_writer writer(stdout); 52 | engine.test_print(writer); 53 | } 54 | --------------------------------------------------------------------------------