├── .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 | [](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