├── .circleci └── config.yml ├── .clang-format ├── .github └── workflows │ └── html-validate.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── ast ├── .gitignore ├── CMakeLists.txt ├── ast.h ├── ast │ ├── ast_const.h │ ├── ast_enum.h │ ├── ast_expr.h │ ├── ast_stmts.h │ ├── ast_struct.h │ ├── ast_subr.h │ ├── ast_types.h │ └── ast_var.h ├── ast_declare.h ├── sd_inttype.h ├── test │ ├── CMakeLists.txt │ ├── test_str_ast.c │ └── test_str_ast.h ├── util │ ├── copy_ast.c │ ├── copy_ast.h │ ├── equals_ast.c │ ├── equals_ast.h │ ├── free_ast.c │ ├── free_ast.h │ ├── str_ast.c │ └── str_ast.h └── visitor │ ├── visitor.c │ └── visitor.h ├── check-format.sh ├── compiler ├── .gitignore ├── CMakeLists.txt ├── Makefile ├── main │ ├── CMakeLists.txt │ ├── analyzer │ │ ├── annotation │ │ │ ├── annotation_analyzer.c │ │ │ └── annotation_analyzer.h │ │ ├── data │ │ │ ├── data_analyzer.c │ │ │ └── data_analyzer.h │ │ ├── dead │ │ │ ├── dead.h │ │ │ ├── dead_analyzer.c │ │ │ └── dead_analyzer.h │ │ ├── fn │ │ │ ├── fn_analyzer.c │ │ │ └── fn_analyzer.h │ │ ├── halts │ │ │ ├── halt_analyzer.c │ │ │ ├── halt_analyzer.h │ │ │ └── halts.h │ │ └── lv │ │ │ ├── lv_analyzer.c │ │ │ └── lv_analyzer.h │ ├── avr_code_gen │ │ ├── cg_avr.c │ │ ├── cg_avr.h │ │ ├── cg_avr_basic_block.c │ │ ├── cg_avr_basic_block.h │ │ ├── cg_avr_single_function.c │ │ ├── cg_avr_single_function.h │ │ ├── cg_avr_single_tac.c │ │ ├── cg_avr_single_tac.h │ │ └── compile_ir │ │ │ ├── compile_tac.h │ │ │ ├── compile_tac_binary_op.c │ │ │ ├── compile_tac_call.c │ │ │ ├── compile_tac_const_value.c │ │ │ ├── compile_tac_copy.c │ │ │ ├── compile_tac_goto.c │ │ │ ├── compile_tac_if_cmp_goto.c │ │ │ ├── compile_tac_if_goto.c │ │ │ ├── compile_tac_label.c │ │ │ ├── compile_tac_load.c │ │ │ ├── compile_tac_load_local_addr.c │ │ │ ├── compile_tac_nop.c │ │ │ ├── compile_tac_param.c │ │ │ ├── compile_tac_return.c │ │ │ ├── compile_tac_setup_sp.c │ │ │ ├── compile_tac_setup_stackframe.c │ │ │ ├── compile_tac_store.c │ │ │ ├── compile_tac_store_local.c │ │ │ └── compile_tac_unary_op.c │ ├── basic_block │ │ ├── basicblock.c │ │ ├── basicblock.h │ │ ├── basicblock_printer.c │ │ └── basicblock_printer.h │ ├── cli │ │ ├── flags │ │ │ ├── all_flags.c │ │ │ ├── all_flags.h │ │ │ ├── flag.h │ │ │ ├── flags.c │ │ │ ├── flags.h │ │ │ ├── validate_flags.c │ │ │ └── validate_flags.h │ │ └── main.c │ ├── compiler.c │ ├── compiler.h │ ├── derefll │ │ ├── derefll.c │ │ └── derefll.h │ ├── gen_tac │ │ ├── gen_tac.c │ │ ├── gen_tac.h │ │ ├── gen_tac_address_of.c │ │ ├── gen_tac_assignstmt.c │ │ ├── gen_tac_call.c │ │ ├── gen_tac_const_data.c │ │ ├── gen_tac_constvalue.c │ │ ├── gen_tac_deref.c │ │ ├── gen_tac_expr.c │ │ ├── gen_tac_forstmt.c │ │ ├── gen_tac_ifstmt.c │ │ ├── gen_tac_retstmt.c │ │ ├── gen_tac_simplevar.c │ │ ├── gen_tac_stmt.c │ │ ├── gen_tac_term.c │ │ ├── gen_tac_unopterm.c │ │ ├── gen_tac_variable.c │ │ ├── gen_tac_whilestmt.c │ │ ├── helper_gen_tac_derefll.c │ │ └── helper_gen_tac_derefll.h │ ├── liveness │ │ ├── liveness.c │ │ └── liveness.h │ ├── typechecker │ │ ├── _tc.h │ │ ├── tc_address_of.c │ │ ├── tc_assignstmt.c │ │ ├── tc_deref.c │ │ ├── tc_expr.c │ │ ├── tc_forstmt.c │ │ ├── tc_ifstmt.c │ │ ├── tc_local_var_decl_stmt.c │ │ ├── tc_method.c │ │ ├── tc_methodcall.c │ │ ├── tc_range.c │ │ ├── tc_retstmt.c │ │ ├── tc_simplevar.c │ │ ├── tc_stmts.c │ │ ├── tc_term.c │ │ ├── tc_unopterm.c │ │ ├── tc_var.c │ │ ├── tc_whilestmt.c │ │ ├── tcctx.h │ │ ├── type_contains │ │ │ ├── tc_arraytype_contains.c │ │ │ ├── tc_basictype_contains.c │ │ │ ├── tc_pointertype_contains.c │ │ │ ├── tc_primitivetype_contains.c │ │ │ ├── tc_simpletype_contains.c │ │ │ ├── tc_structtype_contains.c │ │ │ ├── tc_subrtype_contains.c │ │ │ ├── tc_type_contains.c │ │ │ └── tc_type_contains.h │ │ ├── typecheck.c │ │ ├── typecheck.h │ │ └── util │ │ │ ├── tc_errors.c │ │ │ ├── tc_errors.h │ │ │ ├── tc_utils.c │ │ │ └── tc_utils.h │ ├── typeinference │ │ ├── infer_in_context.c │ │ ├── typeinfer.c │ │ ├── typeinfer.h │ │ ├── typeinfer_address_of.c │ │ ├── typeinfer_const.c │ │ ├── typeinfer_deref.c │ │ ├── typeinfer_expr.c │ │ ├── typeinfer_lvalue.c │ │ ├── typeinfer_methodcall.c │ │ ├── typeinfer_simplevar.c │ │ ├── typeinfer_term.c │ │ ├── typeinfer_var.c │ │ └── util │ │ │ ├── type_str.c │ │ │ └── type_str.h │ ├── util │ │ ├── ctx.c │ │ ├── ctx.h │ │ ├── fileutils │ │ │ ├── fileutils.c │ │ │ └── fileutils.h │ │ ├── fill_tables.c │ │ └── fill_tables.h │ └── x86_code_gen │ │ ├── allocate_registers_x86.c │ │ ├── allocate_registers_x86.h │ │ ├── cg_x86.c │ │ ├── cg_x86.h │ │ ├── cg_x86_basic_block.c │ │ ├── cg_x86_basic_block.h │ │ ├── cg_x86_single_function.c │ │ ├── cg_x86_single_function.h │ │ ├── cg_x86_single_tac.c │ │ ├── cg_x86_single_tac.h │ │ ├── compile_ir │ │ ├── compile_tac.h │ │ ├── compile_tac_binary_op.c │ │ ├── compile_tac_call.c │ │ ├── compile_tac_const_data.c │ │ ├── compile_tac_const_value.c │ │ ├── compile_tac_copy.c │ │ ├── compile_tac_goto.c │ │ ├── compile_tac_icall.c │ │ ├── compile_tac_if_cmp_goto.c │ │ ├── compile_tac_if_goto.c │ │ ├── compile_tac_label.c │ │ ├── compile_tac_load.c │ │ ├── compile_tac_load_function_ptr.c │ │ ├── compile_tac_load_local_addr.c │ │ ├── compile_tac_nop.c │ │ ├── compile_tac_param.c │ │ ├── compile_tac_return.c │ │ ├── compile_tac_setup_stackframe.c │ │ ├── compile_tac_store.c │ │ ├── compile_tac_store_local.c │ │ └── compile_tac_unary_op.c │ │ └── syscalls │ │ ├── syscalls.c │ │ ├── syscalls.h │ │ └── table.c └── test │ ├── CMakeLists.txt │ ├── avr_code_gen │ ├── compile_ir │ │ ├── test_compile_tac.h │ │ ├── test_compile_tac_binary_op.c │ │ ├── test_compile_tac_call.c │ │ ├── test_compile_tac_const_value.c │ │ ├── test_compile_tac_copy.c │ │ ├── test_compile_tac_goto.c │ │ ├── test_compile_tac_if_cmp_goto.c │ │ ├── test_compile_tac_if_goto.c │ │ ├── test_compile_tac_load.c │ │ ├── test_compile_tac_nop.c │ │ ├── test_compile_tac_param.c │ │ ├── test_compile_tac_return.c │ │ ├── test_compile_tac_setup_sp.c │ │ ├── test_compile_tac_setup_stackframe.c │ │ ├── test_compile_tac_store.c │ │ └── test_compile_tac_unary_op.c │ ├── test_avr_code_gen.c │ ├── test_avr_code_gen.h │ ├── test_avr_code_gen_util.c │ ├── test_avr_code_gen_util.h │ └── timer │ │ ├── test_avr_code_gen_timer.c │ │ └── test_avr_code_gen_timer.h │ ├── gen_tac │ ├── test_gen_tac.c │ ├── test_gen_tac.h │ ├── test_gen_tac_assignstmt.c │ ├── test_gen_tac_call.c │ ├── test_gen_tac_deref.c │ ├── test_gen_tac_expr.c │ ├── test_gen_tac_forstmt.c │ ├── test_gen_tac_ifstmt.c │ ├── test_gen_tac_simplevar.c │ ├── test_gen_tac_structdecl.c │ ├── test_gen_tac_variable.c │ ├── test_gen_tac_whilestmt.c │ └── util │ │ └── test_gen_tac_util.c │ ├── libvmcu_utils │ ├── libvmcu_utils.c │ └── libvmcu_utils.h │ ├── liveness │ ├── test_liveness.c │ ├── test_liveness.h │ ├── test_liveness_def.c │ ├── test_liveness_in.c │ ├── test_liveness_out.c │ └── test_liveness_use.c │ ├── test.c │ ├── testcases.c │ ├── typechecker │ ├── test-src │ │ ├── all_errors.dg │ │ ├── assign_primitive.dg │ │ ├── binop_type_mismatch.dg │ │ ├── condition_requires_bool.dg │ │ ├── impure_called_in_pure.dg │ │ ├── index_not_found.dg │ │ ├── local_var_not_a_subroutine.dg │ │ ├── no_return_stmt.dg │ │ ├── range_requires_int.dg │ │ ├── subr_not_found.dg │ │ ├── switch_case_type_mismatch.dg │ │ ├── switch_requires_primitive.dg │ │ ├── too_many_indices.dg │ │ ├── var_not_found.dg │ │ ├── wrong_number_of_args.dg │ │ ├── wrong_op_unop.dg │ │ ├── wrong_return_type.dg │ │ └── wrong_type_of_arg.dg │ ├── test_typechecker.c │ ├── test_typechecker.h │ ├── test_typechecker_util.c │ └── test_typechecker_util.h │ ├── typeinference │ ├── test-src │ │ ├── infer_type_call_with_array_access.dg │ │ ├── infer_type_call_with_struct_member_access.dg │ │ ├── infer_type_expr.dg │ │ ├── infer_type_expr_multiple_terms.dg │ │ ├── infer_type_ptr_arithmetic.dg │ │ ├── infer_type_return_type_subroutine.dg │ │ ├── infer_type_simplevar_no_indices.dg │ │ ├── infer_type_simplevar_with_indices.dg │ │ ├── infer_type_term.dg │ │ ├── infer_type_type_param.dg │ │ ├── infer_type_unopterm.dg │ │ └── infer_type_var_with_member_access.dg │ ├── test_typeinference.c │ ├── test_typeinference.h │ ├── test_typeinference_util.c │ └── test_typeinference_util.h │ └── x86_code_gen │ ├── compile_ir │ ├── test_compile_tac.h │ ├── test_compile_tac_binary_op.c │ ├── test_compile_tac_call.c │ ├── test_compile_tac_const_value.c │ ├── test_compile_tac_copy.c │ ├── test_compile_tac_goto.c │ ├── test_compile_tac_if_cmp_goto.c │ ├── test_compile_tac_if_goto.c │ ├── test_compile_tac_load.c │ ├── test_compile_tac_nop.c │ ├── test_compile_tac_param.c │ ├── test_compile_tac_return.c │ ├── test_compile_tac_store.c │ ├── test_compile_tac_store_local.c │ └── test_compile_tac_unary_op.c │ ├── fake_lvst.c │ ├── fake_lvst.h │ ├── test_x86_code_gen.c │ ├── test_x86_code_gen.h │ ├── test_x86_code_gen_util.c │ └── test_x86_code_gen_util.h ├── dependencies ├── .gitignore └── Makefile ├── docs ├── _headers ├── css │ └── style.css ├── googlec8c33fc0ae3784b9.html ├── html │ ├── annotations.html │ ├── architecture.html │ ├── avr-backend.html │ ├── calling-convention.html │ ├── contributing.html │ ├── controlflow.html │ ├── editor-support.html │ ├── grammar.html │ ├── local-var-typeinference.html │ ├── operators.html │ ├── optimizer.html │ ├── primitives.html │ ├── project-goals.html │ ├── rat.html │ ├── skeleton.html │ ├── stdlib.html │ ├── structs.html │ ├── subroutines.html │ └── tac.html ├── img │ ├── dragon-logo.svg │ ├── favicon.ico │ ├── rat-x86.svg │ ├── rat.svg │ └── transpiler.svg └── index.html ├── examples ├── .gitignore ├── Makefile ├── array │ ├── array.dg │ └── array2.dg ├── assert_examples.sh ├── enum │ ├── enum_hex_value │ │ ├── enum_hex_value.dg │ │ └── enum_hex_value.exitcode │ └── simple_enum │ │ ├── simple_enum.dg │ │ └── simple_enum.exitcode ├── externc │ ├── Makefile │ ├── caller.dg │ ├── f1.c │ ├── params │ │ ├── Makefile │ │ └── caller_params.dg │ └── return-value │ │ ├── Makefile │ │ └── caller.dg ├── ifstatement │ ├── false.dg │ ├── false.exitcode │ ├── true.dg │ └── true.exitcode ├── led_blink_no_timer │ ├── Makefile │ └── led_blink_no_timer.dg ├── led_blink_timer │ ├── Makefile │ └── led_blink.dg ├── local_variables │ ├── simple.dg │ └── simple.exitcode ├── loops │ ├── forloop │ │ ├── forloop.dg │ │ └── forloop.exitcode │ └── whileloop │ │ ├── whileloop.dg │ │ └── whileloop.exitcode ├── mathematics │ ├── div │ │ ├── div.dg │ │ └── div.exitcode │ ├── div_int │ │ ├── div_int.dg │ │ └── div_int.exitcode │ ├── fibonacci_11.dg │ ├── fibonacci_11.exitcode │ ├── fibonacci_3.dg │ ├── fibonacci_3.exitcode │ ├── fibonacci_4.dg │ ├── fibonacci_4.exitcode │ ├── fibonacci_5.dg │ ├── fibonacci_5.exitcode │ ├── fibonacci_6.dg │ ├── fibonacci_6.exitcode │ └── modulus │ │ ├── mod.dg │ │ └── mod.exitcode ├── methodCalls │ ├── 3-deep │ │ ├── 3deep.dg │ │ └── 3deep.exitcode │ ├── add │ │ ├── add_16.dg │ │ ├── add_16.exitcode │ │ ├── add_32.dg │ │ ├── add_32.exitcode │ │ ├── add_64.dg │ │ ├── add_64.exitcode │ │ ├── add_8.dg │ │ └── add_8.exitcode │ ├── call_as_arg │ │ ├── call_as_arg.dg │ │ └── call_as_arg.exitcode │ ├── function_ptr │ │ ├── function_ptr.dg │ │ └── function_ptr.exitcode │ ├── function_ptr_with_arg │ │ ├── function_ptr_with_arg.dg │ │ └── function_ptr_with_arg.exitcode │ ├── pass_function_ptr │ │ ├── pass_function_ptr.dg │ │ └── pass_function_ptr.exitcode │ └── recursion │ │ ├── recursion.dg │ │ └── recursion.exitcode ├── octal │ ├── octal_notation.dg │ └── octal_notation.exitcode ├── other │ └── everything.dg ├── pointer_type │ ├── address_of_deref │ │ ├── address_of_deref.dg │ │ └── address_of_deref.exitcode │ ├── deref_assignment │ │ ├── deref_assignment.dg │ │ └── deref_assignment.exitcode │ ├── deref_of_address │ │ ├── deref_of_address.dg │ │ └── deref_of_address.exitcode │ ├── deref_once │ │ ├── deref_pointer.dg │ │ └── deref_pointer.exitcode │ ├── pass_to_function │ │ ├── pass_to_function.dg │ │ └── pass_to_function.exitcode │ ├── pass_to_function_deref_assign │ │ ├── pass_to_function_deref_assign.dg │ │ └── pass_to_function_deref_assign.exitcode │ ├── pass_to_function_twice │ │ ├── pass_to_function_twice.dg │ │ └── pass_to_function_twice.exitcode │ └── twice │ │ ├── deref_twice.dg │ │ └── deref_twice.exitcode ├── portb │ ├── Makefile │ └── test_portb.dg ├── stdlib │ ├── base │ │ ├── allocator │ │ │ ├── alloc_0_bytes │ │ │ │ ├── alloc_0_bytes.dg │ │ │ │ ├── alloc_0_bytes.exitcode │ │ │ │ └── alloc_0_bytes.stdlib │ │ │ ├── calloc_test │ │ │ │ ├── calloc_test.dg │ │ │ │ ├── calloc_test.exitcode │ │ │ │ ├── calloc_test.stdlib │ │ │ │ └── calloc_test.stdout │ │ │ ├── loop_test │ │ │ │ ├── loop_test.dg │ │ │ │ ├── loop_test.exitcode │ │ │ │ └── loop_test.stdlib │ │ │ ├── memcpy_test │ │ │ │ ├── memcpy_test.dg │ │ │ │ ├── memcpy_test.exitcode │ │ │ │ ├── memcpy_test.stdlib │ │ │ │ └── memcpy_test.stdout │ │ │ ├── no_overlap │ │ │ │ ├── no_overlap.dg │ │ │ │ ├── no_overlap.exitcode │ │ │ │ └── no_overlap.stdlib │ │ │ ├── realloc_test │ │ │ │ ├── realloc_test.dg │ │ │ │ ├── realloc_test.exitcode │ │ │ │ └── realloc_test.stdlib │ │ │ └── use_allocator │ │ │ │ ├── use_allocator.dg │ │ │ │ ├── use_allocator.exitcode │ │ │ │ └── use_allocator.stdlib │ │ ├── string │ │ │ ├── streq │ │ │ │ ├── test_streq.dg │ │ │ │ ├── test_streq.exitcode │ │ │ │ └── test_streq.stdlib │ │ │ └── strlen │ │ │ │ ├── test_strlen.dg │ │ │ │ ├── test_strlen.exitcode │ │ │ │ └── test_strlen.stdlib │ │ ├── test_string.dg │ │ ├── test_string.stdlib │ │ └── test_string.stdout │ ├── draw │ │ ├── svg │ │ │ ├── test_svg.dg │ │ │ ├── test_svg.exitcode │ │ │ ├── test_svg.stdlib │ │ │ └── test_svg.stdout │ │ ├── testdraw.dg │ │ ├── testdraw.stdlib │ │ └── testdraw.stdout │ └── syscalls │ │ ├── exit │ │ ├── exit.dg │ │ ├── exit.exitcode │ │ └── exit.stdlib │ │ ├── mmap │ │ ├── use_mmap.dg │ │ ├── use_mmap.exitcode │ │ └── use_mmap.stdlib │ │ ├── read_file │ │ ├── read_file.dg │ │ ├── read_file.stdlib │ │ └── read_file.stdout │ │ ├── write │ │ ├── write_stdout.dg │ │ ├── write_stdout.exitcode │ │ ├── write_stdout.stdlib │ │ └── write_stdout.stdout │ │ ├── write_file │ │ ├── write_file.dg │ │ ├── write_file.exitcode │ │ └── write_file.stdlib │ │ └── write_string │ │ ├── write_string.dg │ │ ├── write_string.exitcode │ │ ├── write_string.stdlib │ │ └── write_string.stdout ├── struct │ ├── nested │ │ ├── nested.dg │ │ └── nested.exitcode │ ├── struct_and_array │ │ ├── struct_and_array.dg │ │ ├── struct_and_array.exitcode │ │ └── struct_and_array.stdlib │ ├── struct_on_heap │ │ ├── struct_on_heap.dg │ │ ├── struct_on_heap.exitcode │ │ ├── struct_on_heap.stdlib │ │ └── struct_on_heap.stdout │ ├── struct_on_stack │ │ ├── one_member.dg │ │ ├── one_member.exitcode │ │ ├── two_member.dg │ │ └── two_member.exitcode │ └── very_nested │ │ ├── very_nested.dg │ │ └── very_nested.exitcode ├── tc_err.dg ├── typeinference │ └── localvartypeinference.dg └── usart │ ├── Makefile │ └── main.dg ├── format-code.sh ├── ibuffer ├── CMakeLists.txt ├── ibuffer.c ├── ibuffer_avr.h ├── ibuffer_write.c ├── ibuffer_write.h ├── ibuffer_x86.h ├── ikey.h └── mnem.c ├── lexer ├── .gitignore ├── CMakeLists.txt ├── src │ ├── CMakeLists.txt │ ├── driver.c │ ├── driver.h │ ├── lexer.c │ ├── lexer.h │ ├── lexer_flags.h │ ├── lexer_main.c │ └── lexer_main.h └── test │ ├── CMakeLists.txt │ ├── lexer_test_utils.c │ ├── lexer_test_utils.h │ ├── test.c │ ├── test.h │ └── testcases │ ├── tests_comments.c │ ├── tests_const.c │ ├── tests_keywords.c │ ├── tests_mixed.c │ ├── tests_operators.c │ └── tests_other.c ├── parser ├── .gitignore ├── CMakeLists.txt ├── main │ ├── CMakeLists.txt │ ├── astnodes │ │ ├── EnumDecl.c │ │ ├── EnumDecl.h │ │ ├── EnumMember.c │ │ ├── EnumMember.h │ │ ├── Identifier.c │ │ ├── Identifier.h │ │ ├── Namespace.c │ │ ├── Namespace.h │ │ ├── Range.c │ │ ├── Range.h │ │ ├── StmtBlock.c │ │ ├── StmtBlock.h │ │ ├── const │ │ │ ├── ConstValue.c │ │ │ ├── ConstValue.h │ │ │ ├── IntConst.c │ │ │ ├── IntConst.h │ │ │ ├── StringConst.c │ │ │ └── StringConst.h │ │ ├── expr │ │ │ ├── AddressOf.c │ │ │ ├── AddressOf.h │ │ │ ├── Deref.c │ │ │ ├── Deref.h │ │ │ ├── Expr.c │ │ │ ├── Expr.h │ │ │ ├── LValue.c │ │ │ ├── LValue.h │ │ │ ├── Op.c │ │ │ ├── Op.h │ │ │ ├── Term.c │ │ │ ├── Term.h │ │ │ ├── UnOpTerm.c │ │ │ └── UnOpTerm.h │ │ ├── statements │ │ │ ├── AssignStmt.c │ │ │ ├── AssignStmt.h │ │ │ ├── Call.c │ │ │ ├── Call.h │ │ │ ├── ForStmt.c │ │ │ ├── ForStmt.h │ │ │ ├── IfStmt.c │ │ │ ├── IfStmt.h │ │ │ ├── LocalVarDeclStmt.c │ │ │ ├── LocalVarDeclStmt.h │ │ │ ├── RetStmt.c │ │ │ ├── RetStmt.h │ │ │ ├── Stmt.c │ │ │ ├── Stmt.h │ │ │ ├── WhileStmt.c │ │ │ └── WhileStmt.h │ │ ├── struct │ │ │ ├── StructDecl.c │ │ │ ├── StructDecl.h │ │ │ ├── StructMember.c │ │ │ └── StructMember.h │ │ ├── subr │ │ │ ├── DeclArg.c │ │ │ ├── DeclArg.h │ │ │ ├── Method.c │ │ │ ├── Method.h │ │ │ ├── MethodDecl.c │ │ │ └── MethodDecl.h │ │ ├── types │ │ │ ├── ArrayType.c │ │ │ ├── ArrayType.h │ │ │ ├── BasicType.c │ │ │ ├── BasicType.h │ │ │ ├── PointerType.c │ │ │ ├── PointerType.h │ │ │ ├── PrimitiveType.c │ │ │ ├── PrimitiveType.h │ │ │ ├── SimpleType.c │ │ │ ├── SimpleType.h │ │ │ ├── StructType.c │ │ │ ├── StructType.h │ │ │ ├── SubrType.c │ │ │ ├── SubrType.h │ │ │ ├── Type.c │ │ │ ├── Type.h │ │ │ ├── TypeParam.c │ │ │ └── TypeParam.h │ │ └── var │ │ │ ├── SimpleVar.c │ │ │ ├── SimpleVar.h │ │ │ ├── Variable.c │ │ │ └── Variable.h │ └── util │ │ ├── parse_astnode.c │ │ ├── parse_astnode.h │ │ ├── parser.c │ │ └── parser.h ├── spec │ ├── proposed_grammar_changes.txt │ └── thought_about_grammar.txt └── test │ ├── CMakeLists.txt │ ├── astnodes │ ├── NamespaceTest.c │ ├── NamespaceTest.h │ ├── RangeTest.c │ ├── RangeTest.h │ ├── StmtBlockTest.c │ ├── StmtBlockTest.h │ ├── const │ │ ├── ConstValueTest.c │ │ └── ConstValueTest.h │ ├── expr │ │ ├── AddressOfTest.c │ │ ├── DerefTest.c │ │ ├── ExprTest.c │ │ ├── ParseExprTests.h │ │ ├── TermTest.c │ │ └── UnOpTermTest.c │ ├── statements │ │ ├── AssignStmtTest.c │ │ ├── AssignStmtTest.h │ │ ├── CallTest.c │ │ ├── CallTest.h │ │ ├── CaseStmtTest.c │ │ ├── CaseStmtTest.h │ │ ├── ForStmtTest.c │ │ ├── ForStmtTest.h │ │ ├── IfStmtTest.c │ │ ├── IfStmtTest.h │ │ ├── RetStmtTest.c │ │ ├── RetStmtTest.h │ │ ├── StmtTest.c │ │ ├── StmtTest.h │ │ ├── WhileStmtTest.c │ │ └── WhileStmtTest.h │ ├── struct │ │ ├── StructDeclTest.c │ │ ├── StructDeclTest.h │ │ ├── StructMemberTest.c │ │ └── StructMemberTest.h │ ├── subr │ │ ├── DeclArgTest.c │ │ ├── DeclArgTest.h │ │ ├── MethodTest.c │ │ └── MethodTest.h │ ├── types │ │ ├── BasicTypeTest.c │ │ ├── ParseTypeTests.h │ │ ├── PointerTypeTest.c │ │ ├── SimpleTypeTest.c │ │ ├── StructTypeTest.c │ │ └── SubrTypeTest.c │ └── var │ │ ├── SimpleVarTest.c │ │ ├── SimpleVarTest.h │ │ ├── VariableTest.c │ │ └── VariableTest.h │ ├── commandline │ ├── ParserTest.c │ └── test.h │ ├── test_parser_util.c │ └── test_parser_util.h ├── rat ├── .gitignore ├── CMakeLists.txt ├── _struct.h ├── rat.c ├── rat.h ├── rat_avr.c ├── rat_x86.c ├── rat_x86.h ├── register.h └── test │ ├── CMakeLists.txt │ ├── test.c │ └── test.h ├── spec ├── coding-style.txt └── types │ ├── generics.txt │ └── transiently-typed.txt ├── stdlib ├── .gitignore ├── Makefile ├── avr │ ├── atmega328p.dg │ ├── portb.dg │ ├── timer0.dg │ └── usart.dg ├── base │ ├── allocator.dg │ ├── assert.dg │ ├── math.dg │ ├── polynomial.dg │ ├── primes.dg │ └── string.dg ├── collections │ ├── array.dg │ ├── arraylist.dg │ ├── linkedlist.dg │ ├── set.dg │ └── stack.dg ├── draw │ ├── ppm.dg │ └── svg.dg ├── syscalls │ └── syscalls.dg └── tests │ ├── test_math.dg │ └── test_primes.dg ├── syntax-tools ├── batcat │ └── install.sh ├── geany │ ├── README.txt │ └── filetypes.smalldragon.conf ├── micro │ ├── HOWTO.txt │ └── smalldragon.yaml ├── sublime-text │ ├── .gitignore │ ├── dragon.sublime-syntax │ └── install.sh ├── syntaxfiles.txt └── vim │ ├── dotvimrc-append.txt │ ├── ftdetect │ └── dg.vim │ ├── install.sh │ └── syntax │ └── dg.vim ├── tables ├── CMakeLists.txt ├── cc │ ├── cc.c │ └── cc.h ├── data │ ├── data.c │ └── data.h ├── enum │ ├── enum_table.c │ └── enum_table.h ├── lvst │ ├── lvst.c │ └── lvst.h ├── sst │ ├── sst.c │ ├── sst.h │ ├── sst_fill.c │ ├── sst_fill.h │ ├── sst_print.c │ └── sst_print.h ├── stst │ ├── stst.c │ ├── stst.h │ ├── stst_print.c │ └── stst_print.h ├── symtable │ ├── symtable.c │ └── symtable.h └── test │ ├── CMakeLists.txt │ ├── test.c │ └── test.h ├── tac ├── CMakeLists.txt ├── _struct.h ├── tac.c ├── tac.h ├── tac_ctor.c ├── tac_ctor.h ├── tac_str.c ├── tacbuffer.c ├── tacbuffer.h ├── tacbuffer_optimize.c └── test │ ├── CMakeLists.txt │ ├── test.h │ ├── test_tac.c │ └── test_tacbuffer.c ├── token ├── CMakeLists.txt ├── TokenKeys.h ├── list │ ├── TokenList.c │ └── TokenList.h ├── test │ ├── CMakeLists.txt │ ├── test.h │ └── testcases │ │ └── tests_tokenlist.c └── token │ ├── token.c │ └── token.h └── util ├── CMakeLists.txt └── status ├── status.c └── status.h /.github/workflows/html-validate.yml: -------------------------------------------------------------------------------- 1 | name: W3CValidation 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'docs/**' 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | validate: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v4 17 | 18 | - name: HTML5Validator 19 | uses: Cyb3r-Jak3/html5validator-action@v7.2.0 20 | with: 21 | root: docs/ 22 | blacklist: "googlec8c33fc0ae3784b9.html" 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | *.o 3 | *.obj 4 | *.tokens 5 | *.asm 6 | *.hex 7 | *.bin 8 | .file.dg 9 | ./main 10 | a.out 11 | .idea/ 12 | cmake-build-debug/ 13 | 14 | *.dot 15 | *.png 16 | 17 | # register allocation table dump 18 | *.rat 19 | 20 | # LVST table dump 21 | *.lvst 22 | 23 | tags 24 | 25 | # build folder 26 | build/ 27 | 28 | .cache/ 29 | 30 | # local TODO file 31 | TODO 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10.2) 2 | project(smalldragon-toplevel C) 3 | 4 | set(CMAKE_C_STANDARD 11) 5 | set(CMAKE_VERBOSE_MAKEFILE ON) 6 | 7 | # for clang tooling support 8 | # such as language server when editing 9 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 10 | 11 | add_compile_options("-g" "-march=native" "-Wall" "-Wextra" "-Werror") 12 | 13 | # this helps to provide the correct flags to include 14 | # debug symbols at every step so that we get 15 | # line numbers and sources in valgrind and other tools 16 | set(CMAKE_BUILD_TYPE Debug) 17 | 18 | #purpose of this file is so that CLion will recognize 19 | #the whole project 20 | 21 | add_subdirectory(util/) 22 | add_subdirectory(token/) 23 | add_subdirectory(ast/) 24 | add_subdirectory(ibuffer/) 25 | 26 | add_subdirectory(tables/) 27 | add_subdirectory(rat/) 28 | add_subdirectory(tac/) 29 | 30 | add_subdirectory(lexer/) 31 | add_subdirectory(parser/) 32 | add_subdirectory(compiler/) 33 | -------------------------------------------------------------------------------- /ast/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | tests 3 | -------------------------------------------------------------------------------- /ast/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-ast" STATIC 3 | util/copy_ast.c 4 | util/equals_ast.c 5 | util/free_ast.c 6 | util/str_ast.c 7 | visitor/visitor.c 8 | ) 9 | 10 | 11 | target_link_libraries("sd-ast" sd-util) 12 | 13 | target_include_directories("sd-ast" PUBLIC "..") 14 | 15 | add_subdirectory(test) 16 | -------------------------------------------------------------------------------- /ast/ast/ast_const.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../ast_declare.h" 6 | 7 | struct ConstValue { 8 | struct ASTNode super; 9 | 10 | union { 11 | bool m1_bool_const; 12 | int32_t m2_int_const; 13 | char m3_char_const; 14 | uint32_t m5_hex_const; 15 | //6 means binconst, saved in hex const 16 | } ptr; 17 | 18 | uint8_t kind; // 1 .. 6 19 | }; 20 | 21 | struct StringConst { 22 | struct ASTNode super; 23 | char* value; 24 | }; 25 | -------------------------------------------------------------------------------- /ast/ast/ast_enum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../ast_declare.h" 4 | 5 | struct EnumDecl { 6 | struct ASTNode super; 7 | 8 | // must be all uppercase (underscores are ok) 9 | char* name; 10 | 11 | struct EnumMember** members; 12 | uint16_t count_members; 13 | }; 14 | 15 | struct EnumMember { 16 | struct ASTNode super; 17 | 18 | char* name; 19 | struct ConstValue* value; 20 | }; 21 | -------------------------------------------------------------------------------- /ast/ast/ast_struct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../ast_declare.h" 4 | 5 | struct StructDecl { 6 | struct ASTNode super; 7 | 8 | // TODO: should be 'StructType' ? 9 | struct SimpleType* type; //the type(and name) 10 | 11 | struct StructMember** members; 12 | uint16_t count_members; 13 | }; 14 | 15 | struct StructMember { 16 | struct ASTNode super; 17 | 18 | struct Type* type; 19 | char* name; 20 | }; 21 | -------------------------------------------------------------------------------- /ast/ast/ast_subr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../ast_declare.h" 6 | 7 | struct DeclArg { 8 | struct ASTNode super; 9 | 10 | struct Type* type; 11 | bool has_name; 12 | char* name; 13 | }; 14 | 15 | struct MethodDecl { 16 | struct ASTNode super; 17 | 18 | struct Type* return_type; 19 | char* name; 20 | 21 | bool is_public; 22 | bool has_side_effects; 23 | 24 | uint8_t count_args; 25 | struct DeclArg** args; 26 | }; 27 | 28 | struct Method { 29 | struct ASTNode super; 30 | 31 | struct MethodDecl* decl; 32 | 33 | struct StmtBlock* block; 34 | }; 35 | -------------------------------------------------------------------------------- /ast/ast/ast_var.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../ast_declare.h" 4 | 5 | struct Variable { 6 | struct ASTNode super; 7 | 8 | struct SimpleVar* simple_var; 9 | struct Variable* member_access; //may be NULL 10 | }; 11 | struct SimpleVar { 12 | struct ASTNode super; 13 | 14 | char* name; 15 | 16 | uint8_t count_indices; 17 | struct Expr** indices; 18 | }; 19 | -------------------------------------------------------------------------------- /ast/sd_inttype.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum INTTYPE { 4 | 5 | NONE = -1, 6 | 7 | INT8, 8 | INT16, 9 | INT32, 10 | INT64, 11 | 12 | UINT8, 13 | UINT16, 14 | UINT32, 15 | UINT64, 16 | 17 | INT, 18 | UINT, 19 | 20 | INTTYPE_END, 21 | }; 22 | -------------------------------------------------------------------------------- /ast/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-ast-test" 3 | test_str_ast.c 4 | ) 5 | 6 | target_link_libraries("sd-ast-test" sd-util) 7 | target_include_directories("sd-ast-test" PUBLIC "../..") 8 | -------------------------------------------------------------------------------- /ast/test/test_str_ast.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //const 4 | void test_ast_str_binconst(); 5 | void test_ast_str_intconst(); 6 | void test_ast_str_charconst(); 7 | void test_ast_str_hexconst(); 8 | 9 | //expr 10 | void test_ast_str_expr(); 11 | void test_ast_str_op(); 12 | void test_ast_str_unopterm(); 13 | void test_ast_str_term(); 14 | 15 | //struct 16 | void test_ast_str_structdecl(); 17 | void test_ast_str_structmember(); 18 | 19 | //types 20 | void test_ast_str_type(); 21 | void test_ast_str_basictype(); 22 | void test_ast_str_simpletype(); 23 | void test_ast_str_primitivetype(); 24 | void test_ast_str_subrype(); 25 | void test_ast_str_structtype(); 26 | void test_ast_str_typeparam(); 27 | void test_ast_str_arraytype(); 28 | void test_ast_str_pointertype(); 29 | -------------------------------------------------------------------------------- /ast/util/equals_ast.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../ast_declare.h" 5 | 6 | /* the functions in this file are currently implemented 7 | * on an as-needed basis 8 | */ 9 | 10 | //NOTE: all these subroutines accept NULL 11 | //as an argument 12 | 13 | bool eq_type(struct Type* a, struct Type* b); 14 | 15 | bool eq_subrtype(struct SubrType* a, struct SubrType* b); 16 | 17 | bool eq_typeparam(struct TypeParam* a, struct TypeParam* b); 18 | 19 | bool eq_simpletype(struct SimpleType* a, struct SimpleType* b); 20 | 21 | bool eq_structtype(struct StructType* a, struct StructType* b); 22 | 23 | bool eq_primitivetype(struct PrimitiveType* a, struct PrimitiveType* b); 24 | 25 | bool eq_basictype(struct BasicType* a, struct BasicType* b); 26 | 27 | bool eq_arraytype(struct ArrayType* a, struct ArrayType* b); 28 | 29 | bool eq_pointertype(struct PointerType* a, struct PointerType* b); 30 | -------------------------------------------------------------------------------- /check-format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | ./format-code.sh 6 | 7 | format_exit_code=$? 8 | 9 | if [ $format_exit_code -ne 0 ]; then 10 | exit 1 11 | fi 12 | 13 | dirty=$(git ls-files --modified) 14 | 15 | if [ "$dirty" ]; then 16 | echo "check-format has failed" 17 | echo "$dirty" 18 | 19 | echo "diff:" 20 | diff=$(git diff) 21 | echo "$diff" 22 | 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /compiler/.gitignore: -------------------------------------------------------------------------------- 1 | sdg 2 | sd 3 | smalldragon 4 | *.o 5 | .file.* 6 | *.bin 7 | -------------------------------------------------------------------------------- /compiler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(main) 3 | add_subdirectory(test) 4 | -------------------------------------------------------------------------------- /compiler/Makefile: -------------------------------------------------------------------------------- 1 | 2 | clean: 3 | rm -f sd 4 | rm -f .*.dg .*.asm .*.hex .*.obj .*.cof 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /compiler/main/analyzer/annotation/annotation_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* this Transpiler-Analyzer Module 4 | * can look for various Annotations 5 | * and provide Errors, Notes and Warnings 6 | * regarding those Annotations in their Context. 7 | */ 8 | 9 | struct AST; 10 | struct ST; 11 | 12 | void analyze_annotations(struct ST* st, struct AST* ast); 13 | -------------------------------------------------------------------------------- /compiler/main/analyzer/data/data_analyzer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ast/ast.h" 6 | 7 | #include "tables/symtable/symtable.h" 8 | #include "tables/data/data.h" 9 | 10 | #include "data_analyzer.h" 11 | 12 | #include "ast/visitor/visitor.h" 13 | 14 | static void data_visitor(void* node, enum NODE_TYPE type, void* arg); 15 | 16 | void analyze_data(struct ST* st, struct AST* ast) { 17 | 18 | visit_ast(ast, data_visitor, st->data); 19 | } 20 | 21 | static void data_visitor(void* node, enum NODE_TYPE type, void* arg) { 22 | 23 | struct DataTable* data = (struct DataTable*)arg; 24 | 25 | if (type != NODE_STRINGCONST) { return; } 26 | 27 | struct StringConst* sc = (struct StringConst*)node; 28 | 29 | data_insert(data, sc->value); 30 | } 31 | -------------------------------------------------------------------------------- /compiler/main/analyzer/data/data_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // This analyzer module visits the AST 4 | // to look for StringConst instances 5 | // and adds them to DataTable 6 | 7 | struct ST; 8 | struct AST; 9 | 10 | void analyze_data(struct ST* st, struct AST* ast); 11 | -------------------------------------------------------------------------------- /compiler/main/analyzer/dead/dead.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum DEAD { 4 | 5 | DEAD_ISLIVE, 6 | DEAD_ISDEAD, 7 | DEAD_UNKNOWN 8 | }; 9 | -------------------------------------------------------------------------------- /compiler/main/analyzer/dead/dead_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* This is the dead code analyzer 4 | * it looks for functions not reachable from 5 | * main. If there is no main, all functions 6 | * are assumed to be live. 7 | */ 8 | 9 | #include "compiler/main/util/ctx.h" 10 | 11 | struct AST; 12 | 13 | // @returns false on error 14 | bool analyze_dead_code(struct Ctx* ctx, struct AST* ast); 15 | -------------------------------------------------------------------------------- /compiler/main/analyzer/fn/fn_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct ST; 4 | struct AST; 5 | 6 | /* the function analyzer is responsible for finding 7 | * both callees and callers for all functions in a given 8 | * program. 9 | */ 10 | 11 | /* the output of the analysis is stored in the SST, 12 | * in the SSTLine for a given function. 13 | */ 14 | 15 | void analyze_functions(struct ST* st, struct AST* ast); 16 | -------------------------------------------------------------------------------- /compiler/main/analyzer/halts/halt_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* this Analyzer Module 4 | * can performa a termination analysis for 5 | * functions. The results, for each function are: 6 | * 7 | * - Terminates 8 | * - Will never Terminate 9 | * - Unknown 10 | * 11 | */ 12 | 13 | void analyze_termination(struct ST* st); 14 | -------------------------------------------------------------------------------- /compiler/main/analyzer/halts/halts.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * for some subroutines it is desired that they 5 | * never terminate, except when the process is killed 6 | * externally (Ctrl-C), SIGKILL, ... 7 | * That would be the case for a web server main loop 8 | * in some cases. 9 | * 10 | * for other subroutines, it is desired that they will 11 | * terminate in all cases. 12 | * 13 | * for some subroutines, we cannot know their 14 | * halting behavior 15 | * 16 | * for other subroutines their halting behavior 17 | * depends on user input. 18 | * 19 | * This enum is designed to be able to represent those 20 | * c_types_util of (non-)termination behavior. 21 | */ 22 | 23 | enum HALTS { 24 | 25 | HALTS_ALWAYS, 26 | HALTS_NEVER, 27 | HALTS_UNKNOWN 28 | }; 29 | -------------------------------------------------------------------------------- /compiler/main/analyzer/lv/lv_analyzer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* this Transpiler-Analyzer Module 4 | * can discover the local variables of a function, 5 | * aswell as use the type inference Module to discover 6 | * their c_types_util. The results are then put into the LVST 7 | */ 8 | 9 | struct ST; 10 | struct Method; 11 | 12 | void lvst_fill(struct Method* subr, struct ST* st); 13 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/cg_avr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Flags; 6 | struct Ctx; 7 | struct AST; 8 | struct IBuffer; 9 | 10 | void emit_call_main_endloop(struct IBuffer* ibu); 11 | 12 | //void emit_setup_stack_pointer_avr(FILE* fout); 13 | 14 | bool compile_and_write_avr(struct AST* ast, struct Ctx* ctx); 15 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/cg_avr_basic_block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "tables/symtable/symtable.h" 8 | #include "ast/ast_declare.h" 9 | #include "util/ctx.h" 10 | #include "basic_block/basicblock.h" 11 | 12 | struct IBuffer; 13 | 14 | bool emit_asm_avr_basic_block(struct BasicBlock* block, struct Ctx* ctx, struct IBuffer* ibu); 15 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/cg_avr_single_function.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Method; 7 | struct Ctx; 8 | struct IBuffer; 9 | 10 | void emit_create_stack_frame(uint32_t stack_frame_size, FILE* fout); 11 | 12 | bool compile_and_write_avr_single_function(struct Method* m, struct Ctx* ctx, struct IBuffer* ibu); 13 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/cg_avr_single_tac.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Ctx; 6 | struct IBuffer; 7 | 8 | bool emit_asm_avr_single_tac(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu); 9 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_const_value.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rat/rat.h" 5 | 6 | #include "tac/tac.h" 7 | #include "avr_code_gen/compile_ir/compile_tac.h" 8 | 9 | void compile_tac_const_value(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 10 | 11 | //for TAC_CONST_VALUE there should have been a higher 12 | //reg allocated for it's destination tmp 13 | 14 | const int reg = rat_get_register(rat, tac_dest(tac)); 15 | 16 | //change to unsigned value here, for shifting 17 | const uint16_t value = tac_const_value(tac); 18 | 19 | char c[60]; 20 | sprintf(c, "TAC_CONST_VALUE %d (0x%x)", value, value); 21 | 22 | avr_ldi(reg, (value & 0xff), c); 23 | 24 | if (rat_is_wide(rat, tac_dest(tac))) { 25 | 26 | avr_ldi((reg + 1), ((value >> 8) & 0xff), c); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_copy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rat/rat.h" 6 | #include "tac/tac.h" 7 | #include "util/ctx.h" 8 | #include "avr_code_gen/compile_ir/compile_tac.h" 9 | 10 | void compile_tac_copy(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 11 | 12 | const int reg_src = rat_get_register(rat, tac_arg1(tac)); 13 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 14 | 15 | avr_mov(reg_dest, reg_src, "TAC_COPY"); 16 | 17 | if (rat_is_wide(rat, tac_arg1(tac))) 18 | avr_mov(reg_dest + 1, reg_src + 1, "TAC_COPY"); 19 | } 20 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "avr_code_gen/compile_ir/compile_tac.h" 5 | 6 | void compile_tac_goto(struct TAC* tac, struct IBuffer* ibu) { 7 | 8 | char str[32]; 9 | sprintf(str, "L%d", tac_label_index(tac)); 10 | 11 | avr_jmp(str); 12 | 13 | // cannot use rjmp, as it has only a limited range (+/- 2K words) 14 | // TODO: check if 'jmp' instruction is available on the target mcu. 15 | } 16 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_if_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rat/rat.h" 5 | #include "tac/tac.h" 6 | #include "avr_code_gen/compile_ir/compile_tac.h" 7 | 8 | void compile_tac_if_goto(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 9 | 10 | char* c = "TAC_IF_GOTO"; 11 | 12 | const int reg = rat_get_register(rat, tac_arg1(tac)); 13 | char str[32]; 14 | sprintf(str, "L%d", tac_label_index(tac)); 15 | 16 | char tmp_label[32]; 17 | sprintf(tmp_label, "L%d", make_label()); 18 | 19 | avr_tst(reg, c); //test if r%d is zero 20 | 21 | avr_breq(tmp_label, c); 22 | avr_jmp(str); 23 | avr_label(tmp_label); 24 | 25 | // brne(str, c); 26 | // we cannot use brne since it can only branch +/- 64 words 27 | // from the instruction pointer 28 | 29 | // since a bool is only ever 1 byte 30 | // there is no case for wide argument 31 | } 32 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_label.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tables/sst/sst.h" 4 | #include "tables/stst/stst.h" 5 | #include "tables/lvst/lvst.h" 6 | #include "tables/symtable/symtable.h" 7 | 8 | #include "tac/tacbuffer.h" 9 | #include "tac/tac.h" 10 | #include "avr_code_gen/compile_ir/compile_tac.h" 11 | 12 | void compile_tac_label(struct TAC* tac, struct IBuffer* ibu, struct Ctx* ctx) { 13 | 14 | char* s; 15 | 16 | if (tac_kind(tac) == TAC_LABEL_INDEXED) { 17 | char str[32]; 18 | sprintf(str, "L%d", tac_label_index(tac)); 19 | s = (char*)&str; 20 | } 21 | 22 | if (tac_kind(tac) == TAC_LABEL_FUNCTION) { 23 | 24 | //in case of tests, sst may not be filled 25 | char* function_name = "main"; 26 | 27 | if ((size_t)tac_dest(tac) < sst_size(ctx_tables(ctx)->sst)) { 28 | 29 | function_name = sst_at(ctx_tables(ctx)->sst, tac_dest(tac))->name; 30 | } 31 | 32 | s = function_name; 33 | } 34 | 35 | avr_label(s); 36 | } 37 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "rat/rat.h" 7 | #include "tac/tac.h" 8 | #include "util/ctx.h" 9 | #include "avr_code_gen/compile_ir/compile_tac.h" 10 | 11 | void compile_tac_load(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 12 | 13 | char* c = "TAC_LOAD"; 14 | 15 | //tdest = [targ1] 16 | 17 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 18 | 19 | const int reg_src = rat_get_register(rat, tac_arg1(tac)); 20 | 21 | avr_mov(XL, reg_src, c); 22 | 23 | if (rat_is_wide(rat, tac_arg1(tac))) 24 | avr_mov(XH, reg_src + 1, c); 25 | else 26 | avr_ldi(XH, 0, c); 27 | 28 | const uint8_t width = tac_load_store_width(tac); 29 | 30 | assert(width <= 2); 31 | assert(width >= 1); 32 | 33 | if (width == 2) { 34 | 35 | // what if we want to load a 16 bit value? 36 | avr_ldXpostInc(reg_dest, c); 37 | avr_ldX(reg_dest + 1, c); 38 | } else { 39 | avr_ldX(reg_dest, c); 40 | 41 | if (rat_is_wide(rat, tac_dest(tac))) { 42 | avr_clr(reg_dest + 1, c); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_nop.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "avr_code_gen/compile_ir/compile_tac.h" 4 | 5 | void compile_tac_nop(struct IBuffer* ibu) { 6 | 7 | avr_nop("TAC_NOP"); 8 | } 9 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_param.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rat/rat.h" 6 | 7 | #include "tac/tac.h" 8 | #include "avr_code_gen/compile_ir/compile_tac.h" 9 | 10 | void compile_tac_param(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 11 | 12 | char* c = "TAC_PARAM"; 13 | 14 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 15 | 16 | assert(tac_const_value(tac) % 8 == 0); 17 | assert(tac_const_value(tac) <= 64); 18 | 19 | if (tac_const_value(tac) == 16) { 20 | // this means it's a 16 bit parameter 21 | // so we must push twice 22 | 23 | //TODO: ensure that the temporary has the correct width in RAT 24 | //assert(rat_is_wide(rat, tac->dest)); 25 | 26 | if (rat_is_wide(rat, tac_dest(tac))) { 27 | avr_push(reg_dest + 1, c); 28 | } else { 29 | avr_ldi(rat_scratch_reg(rat), 0, c); 30 | avr_push(rat_scratch_reg(rat), c); 31 | } 32 | } 33 | 34 | avr_push(reg_dest, c); 35 | } 36 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_return.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rat/rat.h" 5 | #include "tac/tacbuffer.h" 6 | #include "tac/tac.h" 7 | #include "avr_code_gen/compile_ir/compile_tac.h" 8 | 9 | #include "tables/sst/sst.h" 10 | #include "tables/stst/stst.h" 11 | #include "tables/lvst/lvst.h" 12 | #include "tables/symtable/symtable.h" 13 | 14 | #include "util/ctx.h" 15 | 16 | void compile_tac_return(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu) { 17 | 18 | char* c = "TAC_RETURN"; 19 | 20 | //destroy the stackframe 21 | for (size_t k = 0; k < lvst_stack_frame_size_avr(ctx_tables(ctx)->lvst); k++) { 22 | 23 | avr_pop(0, "destroy frame"); 24 | //pop r0 ; destroy frame 25 | } 26 | 27 | //find out if tac->dest is a wide (16 bit) temporary 28 | 29 | int reg = rat_get_register(rat, tac_dest(tac)); 30 | 31 | avr_mov(0, reg, c); 32 | 33 | if (rat_is_wide(rat, tac_dest(tac))) { 34 | avr_mov(1, reg + 1, c); 35 | } 36 | 37 | avr_ret(c); 38 | } 39 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_setup_sp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "rat/rat.h" 5 | #include "avr_code_gen/compile_ir/compile_tac.h" 6 | 7 | #include "compile_tac.h" 8 | 9 | void compile_tac_setup_sp(struct RAT* rat, struct IBuffer* ibu) { 10 | 11 | //initialize Stack Pointer 12 | char* comment = "setup SP"; 13 | 14 | const int RAT_SCRATCH_REG = rat_scratch_reg(rat); 15 | 16 | avr_ldi(RAT_SCRATCH_REG, high(RAMEND), comment); 17 | avr_out(SPH, RAT_SCRATCH_REG, comment); 18 | avr_ldi(RAT_SCRATCH_REG, low(RAMEND), comment); 19 | avr_out(SPL, RAT_SCRATCH_REG, comment); 20 | } 21 | -------------------------------------------------------------------------------- /compiler/main/avr_code_gen/compile_ir/compile_tac_setup_stackframe.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "avr_code_gen/compile_ir/compile_tac.h" 5 | 6 | void compile_tac_setup_stackframe(struct TAC* tac, struct IBuffer* ibu) { 7 | 8 | const int stack_frame_size = tac_const_value(tac); 9 | 10 | //push onto the stack to create the stack frame 11 | for (int k = 0; k < stack_frame_size; k++) { 12 | //push r0 ;create frame 13 | avr_push(0, "create stackframe"); 14 | //it is irrelevant what we push here 15 | } 16 | 17 | //load base pointer Y 18 | avr_in(YL, SPL, "load frame pointer Y"); 19 | avr_in(YH, SPH, "load frame pointer Y"); 20 | } 21 | -------------------------------------------------------------------------------- /compiler/main/basic_block/basicblock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "tac/tac.h" 6 | 7 | struct BasicBlock { 8 | 9 | uint32_t index; 10 | 11 | struct TACBuffer* buffer; 12 | 13 | //pointers to branch destination 14 | struct BasicBlock* branch_1; //may be NULL //this is the true branch for conditionals 15 | struct BasicBlock* branch_2; //may be NULL //this is the false / default branch 16 | 17 | bool visited_assign_registers; 18 | bool visited_emit_asm; 19 | }; 20 | 21 | struct BasicBlock* basicblock_ctor(uint32_t index); 22 | void basicblock_dtor(struct BasicBlock* block); 23 | 24 | void basicblock_print(struct BasicBlock* block, struct Ctx* ctx); 25 | 26 | // @returns NULL on error; 27 | struct BasicBlock** basicblock_create_graph(struct TACBuffer* buffer, char* function_name, int* nblocks, struct Ctx* ctx); 28 | -------------------------------------------------------------------------------- /compiler/main/basic_block/basicblock_printer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void write_dot_file_from_graph(struct BasicBlock** blocks, uint32_t count, char* function_name, struct Ctx* ctx); 4 | -------------------------------------------------------------------------------- /compiler/main/cli/flags/all_flags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "flag.h" 9 | 10 | extern struct Flag all_flags[]; 11 | 12 | size_t all_flags_count(); 13 | -------------------------------------------------------------------------------- /compiler/main/cli/flags/flag.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Flag { 7 | // e.g. -avr 8 | char* name; 9 | 10 | char* description; 11 | 12 | bool has_arg; 13 | 14 | // can be NULL 15 | // if set, points into argv 16 | char* arg; 17 | 18 | // can be NULL 19 | // only set if 'has_arg == true' 20 | char* arg_default_value; 21 | 22 | // should be false in the flags array 23 | bool is_set; 24 | }; 25 | -------------------------------------------------------------------------------- /compiler/main/cli/flags/validate_flags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // @returns true on successful validation 6 | bool validate_flags(struct Flags* flags); 7 | -------------------------------------------------------------------------------- /compiler/main/compiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Flags; 6 | 7 | bool compile(struct Flags* flags); 8 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/gen_tac_address_of.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "tac/tac.h" 5 | #include "tac/tacbuffer.h" 6 | 7 | #include "gen_tac.h" 8 | 9 | bool tac_address_of(struct TACBuffer* buffer, struct AddressOf* ao, struct Ctx* ctx) { 10 | 11 | return tac_term_addr(buffer, ao->term, ctx); 12 | } 13 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/gen_tac_const_data.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tables/symtable/symtable.h" 4 | #include "tac/tac.h" 5 | #include "tac/tacbuffer.h" 6 | #include "gen_tac.h" 7 | 8 | #include "tables/data/data.h" 9 | 10 | bool tac_const_data(struct TACBuffer* buffer, struct StringConst* str, struct Ctx* ctx) { 11 | 12 | const int32_t offset = data_string_offset(ctx_tables(ctx)->data, str->value); 13 | 14 | if (offset < 0) { 15 | fprintf(stderr, "%s:%s: could not find offset of '%s' in data table\n", __FILE__, __func__, str->value); 16 | return false; 17 | } 18 | 19 | tacbuffer_append( 20 | buffer, 21 | makeTACConstData(str->super.line_num, make_temp(), offset)); 22 | 23 | return true; 24 | } 25 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/gen_tac_constvalue.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "tac/tacbuffer.h" 5 | #include "gen_tac.h" 6 | #include "tables/enum/enum_table.h" 7 | 8 | void tac_constvalue(struct TACBuffer* buffer, struct ConstValue* c) { 9 | 10 | tacbuffer_append( 11 | buffer, 12 | makeTACConst(c->super.line_num, make_temp(), int_value_from_const(c))); 13 | } 14 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/gen_tac_deref.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "tac/tac.h" 5 | #include "tac/tacbuffer.h" 6 | 7 | #include "gen_tac.h" 8 | 9 | bool tac_deref(struct TACBuffer* buffer, struct Deref* d, struct Ctx* ctx) { 10 | 11 | tac_term(buffer, d->term, ctx); 12 | 13 | const uint32_t dest = make_temp(); 14 | 15 | struct TAC* last = tacbuffer_get_last(buffer); 16 | 17 | const uint32_t width = tac_load_store_width(last); 18 | 19 | tacbuffer_append(buffer, makeTACLoad(d->super.line_num, dest, tacbuffer_last_dest(buffer), width)); 20 | 21 | return true; 22 | } 23 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/gen_tac_retstmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "tac/tacbuffer.h" 5 | 6 | #include "gen_tac.h" 7 | 8 | bool tac_retstmt(struct TACBuffer* buffer, struct RetStmt* r, struct Ctx* ctx) { 9 | 10 | if (r->return_value != NULL) { 11 | if (!tac_expr(buffer, r->return_value, ctx)) { 12 | return false; 13 | } 14 | } 15 | 16 | struct TAC* t = makeTACReturn(r->super.line_num, tacbuffer_last_dest(buffer)); 17 | 18 | tacbuffer_append(buffer, t); 19 | 20 | return true; 21 | } 22 | -------------------------------------------------------------------------------- /compiler/main/gen_tac/helper_gen_tac_derefll.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TACBuffer; 4 | struct DerefLL; 5 | struct Type; 6 | struct Ctx; 7 | 8 | void tac_derefll_single(struct TACBuffer* buffer, struct DerefLL* dll, struct Type* prev_type, struct Ctx* ctx); 9 | -------------------------------------------------------------------------------- /compiler/main/typechecker/tc_deref.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | //AST Includes 4 | #include "ast/ast.h" 5 | #include "ast/util/str_ast.h" 6 | 7 | //Table Includes 8 | #include "tables/symtable/symtable.h" 9 | 10 | //Typechecker Includes 11 | #include "_tc.h" 12 | #include "typechecker/util/tc_errors.h" 13 | #include "tcctx.h" 14 | 15 | #include "typeinference/typeinfer.h" 16 | #include 17 | 18 | bool tc_deref(struct Deref* d, struct TCCtx* tcctx) { 19 | 20 | // check that we can deref whatever it is 21 | struct Type* type = infer_type_term(tcctx->st, d->term); 22 | 23 | // has to be pointer type or array type 24 | if (!type->array_type && !type->pointer_type) { 25 | char* str_t1 = str_type(type); 26 | 27 | char* snippet = str_deref(d); 28 | 29 | char* msg; 30 | 31 | asprintf(&msg, "\tcannot deref type:%s", str_t1); 32 | 33 | error_snippet_and_msg(tcctx, snippet, msg, TC_ERR_CANNOT_DEREF_THIS); 34 | 35 | free(snippet); 36 | free(msg); 37 | 38 | return false; 39 | } 40 | 41 | // TODO: handle type param 42 | 43 | return tc_term(d->term, tcctx); 44 | } 45 | -------------------------------------------------------------------------------- /compiler/main/typechecker/tc_forstmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //AST Includes 5 | #include "ast/ast.h" 6 | #include "ast/util/str_ast.h" 7 | 8 | //Typeinference Includes 9 | #include "compiler/main/typeinference/typeinfer.h" 10 | 11 | //Typechecker Includes 12 | #include "_tc.h" 13 | #include "typechecker/util/tc_errors.h" 14 | #include "typechecker/util/tc_utils.h" 15 | #include "tcctx.h" 16 | 17 | bool tc_forstmt(struct ForStmt* f, struct TCCtx* tcctx) { 18 | 19 | if (tcctx->debug) { 20 | printf("[debug] typecheck for stmt\n"); 21 | } 22 | 23 | tcctx->current_line_num = f->super.line_num; 24 | 25 | if (!tc_range(f->range, tcctx)) { return false; } 26 | 27 | tcctx->depth_inside_loop++; 28 | bool is_ok = tc_stmtblock(f->block, tcctx, false); 29 | tcctx->depth_inside_loop--; 30 | 31 | return is_ok; 32 | } 33 | -------------------------------------------------------------------------------- /compiler/main/typechecker/tc_local_var_decl_stmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | //AST Includes 7 | #include "ast/ast.h" 8 | #include "ast/util/str_ast.h" 9 | #include "ast/util/equals_ast.h" 10 | 11 | //Table Includes 12 | #include "tables/symtable/symtable.h" 13 | 14 | //Typeinference Includes 15 | #include "compiler/main/typeinference/typeinfer.h" 16 | 17 | //Typechecker Includes 18 | #include "_tc.h" 19 | #include "typechecker/util/tc_errors.h" 20 | #include "typechecker/util/tc_utils.h" 21 | #include "typecheck.h" 22 | #include "tcctx.h" 23 | 24 | bool tc_local_var_decl_stmt(struct LocalVarDeclStmt* a, struct TCCtx* tcctx) { 25 | 26 | if (tcctx->debug) { 27 | printf("[debug] typecheck local var decl stmt\n"); 28 | } 29 | 30 | tcctx->current_line_num = a->super.line_num; 31 | 32 | return true; 33 | } 34 | -------------------------------------------------------------------------------- /compiler/main/typechecker/tc_method.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | 5 | #include "analyzer/lv/lv_analyzer.h" 6 | 7 | //Table Includes 8 | #include "tables/lvst/lvst.h" 9 | #include "tables/symtable/symtable.h" 10 | 11 | //Typechecker Includes 12 | #include "_tc.h" 13 | #include "typecheck.h" 14 | #include "tcctx.h" 15 | 16 | bool tc_method(struct Method* m, struct TCCtx* tcctx) { 17 | 18 | if (tcctx->debug) { 19 | printf("[debug] typecheck method: %s\n", m->decl->name); 20 | } 21 | 22 | tcctx->current_line_num = m->super.line_num; 23 | 24 | tcctx->current_fn = m; 25 | 26 | lvst_clear(tcctx->st->lvst); 27 | lvst_fill(m, tcctx->st); 28 | 29 | const bool tc_ok = tc_stmtblock(m->block, tcctx, true); 30 | 31 | if (tcctx->debug && !tc_ok) { 32 | char* lvst_filename = NULL; 33 | asprintf(&lvst_filename, "%s.lvst", m->decl->name); 34 | 35 | if (!lvst_filename) { 36 | fprintf(stderr, "could not allocate filename for lvst\n"); 37 | return false; 38 | } 39 | 40 | lvst_print_filename(tcctx->st->lvst, lvst_filename); 41 | free(lvst_filename); 42 | } 43 | 44 | return tc_ok; 45 | } 46 | -------------------------------------------------------------------------------- /compiler/main/typechecker/tc_range.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //AST Includes 6 | #include "ast/ast.h" 7 | #include "ast/util/str_ast.h" 8 | 9 | //Typeinference Includes 10 | #include "compiler/main/typeinference/typeinfer.h" 11 | 12 | //Typechecker Includes 13 | #include "_tc.h" 14 | #include "typechecker/util/tc_errors.h" 15 | #include "typechecker/util/tc_utils.h" 16 | #include "typecheck.h" 17 | #include "tcctx.h" 18 | 19 | struct Range; 20 | 21 | bool tc_range(struct Range* r, struct TCCtx* tcctx) { 22 | 23 | tcctx->current_line_num = r->super.line_num; 24 | 25 | struct Type* t1 = infer_type_expr(tcctx->st, r->start); 26 | struct Type* t2 = infer_type_expr(tcctx->st, r->end); 27 | 28 | if (!is_integer_type(t1) || !is_integer_type(t2)) { 29 | 30 | char* snippet = str_range(r); 31 | 32 | error_snippet(tcctx, snippet, TC_ERR_RANGE_REQUIRES_INT); 33 | 34 | free(snippet); 35 | 36 | return false; 37 | } 38 | 39 | return true; 40 | } 41 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_arraytype_contains.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ast/ast.h" 4 | 5 | #include "tc_type_contains.h" 6 | 7 | bool tc_arraytype_contains(struct ArrayType* expect, struct ArrayType* actual) { 8 | return tc_type_contains(expect->element_type, actual->element_type); 9 | } 10 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_basictype_contains.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ast/ast.h" 5 | 6 | #include "tc_type_contains.h" 7 | 8 | bool tc_basictype_contains(struct BasicType* expect, struct Type* actual) { 9 | 10 | if (expect == NULL || actual == NULL) { 11 | return NULL; 12 | } 13 | 14 | if (expect->simple_type != NULL) { 15 | return tc_simpletype_contains(expect->simple_type, actual); 16 | } 17 | 18 | struct BasicType* actual_bt = actual->basic_type; 19 | 20 | if (actual_bt == NULL) { 21 | return false; 22 | } 23 | 24 | if (expect->subr_type != NULL && actual_bt->subr_type != NULL) { 25 | return tc_subrtype_contains(expect->subr_type, actual_bt->subr_type); 26 | } 27 | 28 | return false; 29 | } 30 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_pointertype_contains.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ast/ast.h" 5 | #include "ast/util/equals_ast.h" 6 | #include "typechecker/util/tc_utils.h" 7 | 8 | #include "tc_type_contains.h" 9 | 10 | bool tc_pointer_type_contains(struct PointerType* expect, struct Type* actual) { 11 | 12 | // integers can be used as pointers 13 | if (actual->pointer_type == NULL) { 14 | 15 | if (actual->array_type != NULL) { 16 | return eq_type(expect->element_type, actual->array_type->element_type); 17 | } 18 | 19 | return is_integer_type(actual); 20 | } 21 | 22 | struct PointerType* apt = actual->pointer_type; 23 | 24 | // pointers of same underlying type can be assigned to each other 25 | return tc_type_contains(expect->element_type, apt->element_type); 26 | } 27 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_structtype_contains.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ast/ast.h" 5 | 6 | #include "tc_type_contains.h" 7 | 8 | bool tc_structtype_contains(struct StructType* expect, struct StructType* actual) { 9 | 10 | if (strcmp(expect->type_name, actual->type_name) != 0) { return false; } 11 | 12 | return true; 13 | } 14 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_subrtype_contains.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "ast/ast.h" 4 | 5 | #include "tc_type_contains.h" 6 | 7 | bool tc_subrtype_contains(struct SubrType* expect, struct SubrType* actual) { 8 | 9 | if (!tc_type_contains(expect->return_type, actual->return_type)) { return false; } 10 | if (actual->has_side_effects && !expect->has_side_effects) { return false; } 11 | 12 | if (expect->count_arg_types != actual->count_arg_types) { return false; } 13 | 14 | for (int i = 0; i < expect->count_arg_types; ++i) { 15 | struct Type* ei = expect->arg_types[i]; 16 | struct Type* ai = actual->arg_types[i]; 17 | if (!tc_type_contains(ei, ai)) { return false; } 18 | } 19 | return true; 20 | } 21 | -------------------------------------------------------------------------------- /compiler/main/typechecker/type_contains/tc_type_contains.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ast/ast_declare.h" 5 | 6 | //determines if the 'expect' type does contain the 'actual' type, 7 | //e.g. uint32 contains uint16 8 | //e.g. List contains List 9 | bool tc_type_contains(struct Type* expect, struct Type* actual); 10 | 11 | bool tc_basictype_contains(struct BasicType* expect, struct Type* actual); 12 | bool tc_arraytype_contains(struct ArrayType* expect, struct ArrayType* actual); 13 | bool tc_simpletype_contains(struct SimpleType* expect, struct Type* actual); 14 | bool tc_subrtype_contains(struct SubrType* expect, struct SubrType* actual); 15 | bool tc_structtype_contains(struct StructType* expect, struct StructType* actual); 16 | bool tc_primitivetype_contains(struct PrimitiveType* expect, struct Type* actual); 17 | bool tc_pointer_type_contains(struct PointerType* expect, struct Type* actual); 18 | -------------------------------------------------------------------------------- /compiler/main/typechecker/typecheck.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct AST; 4 | struct ST; 5 | #include "tcctx.h" 6 | 7 | #include "util/ctx.h" 8 | 9 | /* This Module provides Facilities 10 | * for typechecking smalldragon Programs. 11 | * 12 | * The AST Visitor is not used here because 13 | * it does not guarantee a particular visiting order 14 | * for nodes on the same level of depth in the AST. 15 | * 16 | * For typechecking, the order is very important 17 | * however, as the following example shows: 18 | * 19 | * uint8 k = 3 + myfunction; 20 | * 21 | * here we should typecheck the right-hand side 22 | * of the assignment first, before 23 | * typechecking the assignment itself, 24 | * because the type inference would have problems 25 | * inferring the type of '3 + myfunction' 26 | */ 27 | 28 | // @returns NULL on error 29 | struct TCError* typecheck_ast(struct AST* ast, struct Ctx* ctx, bool print_errors); 30 | -------------------------------------------------------------------------------- /compiler/main/typechecker/util/tc_errors.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TCCtx; 4 | enum TC_ERR_KIND; 5 | 6 | void error(struct TCCtx* tcctx, char* msg, enum TC_ERR_KIND err_kind); 7 | 8 | void error_snippet(struct TCCtx* tcctx, char* snippet, enum TC_ERR_KIND err_kind); 9 | 10 | void error_snippet_and_msg(struct TCCtx* tcctx, char* snippet, char* msg, enum TC_ERR_KIND err_kind); 11 | -------------------------------------------------------------------------------- /compiler/main/typechecker/util/tc_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ast/ast_declare.h" 7 | 8 | char* tc_get_underlying_struct_name(struct Type* t); 9 | 10 | bool is_primitive_type(struct Type* type); 11 | 12 | bool is_integer_type(struct Type* type); 13 | 14 | bool is_bool_type(struct Type* type); 15 | 16 | bool is_char_type(struct Type* type); 17 | 18 | bool is_pointer_type(struct Type* type); 19 | 20 | uint32_t max_indices_allowed(struct Type* type); 21 | -------------------------------------------------------------------------------- /compiler/main/typeinference/typeinfer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ast/ast.h" 6 | #include "ast/util/str_ast.h" 7 | #include "typeinference/typeinfer.h" 8 | 9 | static char* ERR_NO_ARRAYTYPE = "Expected an ArrayType\n"; 10 | 11 | static void print_error(char* msg) { 12 | fprintf(stderr, "[Typeinference][Error] %s", msg); 13 | } 14 | 15 | struct Type* unwrap_indices(struct Type* t, uint32_t count) { 16 | 17 | assert(t); 18 | 19 | uint32_t index_count = count; 20 | 21 | struct Type* res = t; 22 | 23 | while (index_count > 0) { 24 | if (!(res = unwrap(res))) { 25 | return NULL; 26 | } 27 | index_count--; 28 | } 29 | 30 | return res; 31 | } 32 | 33 | struct Type* unwrap(struct Type* t) { 34 | 35 | if (t->array_type == NULL) { 36 | print_error(ERR_NO_ARRAYTYPE); 37 | char* s = str_type(t); 38 | fprintf(stderr, "instance: %s\n", s); 39 | free(s); 40 | return NULL; 41 | } 42 | 43 | return t->array_type->element_type; 44 | } 45 | -------------------------------------------------------------------------------- /compiler/main/typeinference/typeinfer_address_of.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ast/ast.h" 6 | #include "ast/util/copy_ast.h" 7 | 8 | #include "typeinference/typeinfer.h" 9 | 10 | #include "tables/symtable/symtable.h" 11 | 12 | struct Type* infer_type_address_of(struct ST* st, struct AddressOf* ao) { 13 | 14 | struct Type* t = infer_type_term(st, ao->term); 15 | 16 | struct PointerType* pt = make(PointerType); 17 | pt->element_type = copy_type(t); 18 | 19 | struct Type* res = make(Type); 20 | 21 | res->basic_type = NULL; 22 | res->type_param = NULL; 23 | res->array_type = NULL; 24 | res->pointer_type = pt; 25 | 26 | st_register_inferred_type(st, res); 27 | 28 | return res; 29 | } 30 | -------------------------------------------------------------------------------- /compiler/main/typeinference/typeinfer_deref.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ast/ast.h" 7 | 8 | #include "typeinference/typeinfer.h" 9 | #include "typeinference/util/type_str.h" 10 | 11 | #include "tables/symtable/symtable.h" 12 | 13 | struct Type* infer_type_deref(struct ST* st, struct Deref* d) { 14 | 15 | struct Type* t = infer_type_term(st, d->term); 16 | 17 | // can only deref pointer types and array types 18 | assert(t->pointer_type || t->array_type); 19 | 20 | if (t->pointer_type) { 21 | return t->pointer_type->element_type; 22 | } else { 23 | return t->array_type->element_type; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /compiler/main/typeinference/typeinfer_lvalue.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ast/ast.h" 7 | 8 | #include "typeinference/typeinfer.h" 9 | #include "typeinference/util/type_str.h" 10 | 11 | #include "tables/symtable/symtable.h" 12 | 13 | struct Type* infer_type_lvalue(struct ST* st, struct LValue* lv) { 14 | 15 | if (lv->deref) { 16 | return infer_type_deref(st, lv->deref); 17 | } 18 | if (lv->var) { 19 | return infer_type_variable(st, lv->var); 20 | } 21 | return NULL; 22 | } 23 | -------------------------------------------------------------------------------- /compiler/main/typeinference/typeinfer_var.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ast/ast.h" 6 | 7 | #include "typeinference/typeinfer.h" 8 | 9 | #include "tables/symtable/symtable.h" 10 | #include "tables/stst/stst.h" 11 | 12 | struct Type* infer_type_variable(struct ST* st, struct Variable* v) { 13 | 14 | struct Type* typeOfVar = infer_type_simplevar(st, v->simple_var); 15 | 16 | if (typeOfVar == NULL) { 17 | return NULL; 18 | } 19 | 20 | if (v->member_access == NULL) { return typeOfVar; } 21 | 22 | struct MemberAccess ma = { 23 | .structType = typeOfVar, 24 | .member = v->member_access}; 25 | 26 | return infer_in_context(st, &ma); 27 | } 28 | -------------------------------------------------------------------------------- /compiler/main/typeinference/util/type_str.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ast/ast.h" 4 | 5 | struct Type* typeFromStrPrimitive(struct ST* st, char* typeName); 6 | 7 | struct Type* typeFromStrArray(struct ST* st, char* typeName); 8 | 9 | // [1] 10 | /* register the pointer in SymbolTable 'st' 11 | * so it can manage that memory, 12 | * as this pointer is not part of the AST Tree 13 | */ 14 | void registerInferredType(struct ST* st, struct Type* t); 15 | -------------------------------------------------------------------------------- /compiler/main/util/ctx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ast/ast.h" 8 | 9 | struct ST; 10 | struct Ctx; 11 | struct Flags; 12 | 13 | struct Ctx* ctx_ctor(struct Flags* flags, struct ST* tables); 14 | void ctx_dtor(struct Ctx* ctx); 15 | 16 | struct Flags* ctx_flags(struct Ctx* ctx); 17 | struct ST* ctx_tables(struct Ctx* ctx); 18 | 19 | //loop compilation related 20 | void ctx_enter_loop(struct Ctx* ctx, uint32_t label_start, uint32_t label_end); 21 | 22 | // @returns false on error 23 | bool ctx_exit_loop(struct Ctx* ctx); 24 | 25 | // @returns < 0 on error 26 | int32_t ctx_get_label_loop_start(struct Ctx* ctx); 27 | 28 | // @returns < 0 on error 29 | int32_t ctx_get_label_loop_end(struct Ctx* ctx); 30 | -------------------------------------------------------------------------------- /compiler/main/util/fileutils/fileutils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "cli/flags/flags.h" 4 | 5 | bool check_filenames_lowercase(struct Flags* flags); 6 | -------------------------------------------------------------------------------- /compiler/main/util/fill_tables.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct AST; 6 | struct Ctx; 7 | 8 | bool fill_tables(struct AST* ast, struct Ctx* ctx); 9 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/allocate_registers_x86.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "util/ctx.h" 6 | #include "rat/rat.h" 7 | #include "basic_block/basicblock.h" 8 | 9 | struct IBuffer; 10 | struct Liveness; 11 | 12 | // @returns false on error 13 | bool allocate_registers_basicblocks(struct BasicBlock** graph, size_t nblocks, struct RAT* rat, struct ST* st, struct Liveness* live); 14 | 15 | // @returns false on error 16 | bool allocate_registers(struct TACBuffer* b, struct RAT* rat, struct ST* st, struct Liveness* live); 17 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/cg_x86.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Flags; 6 | struct Ctx; 7 | struct AST; 8 | struct IBuffer; 9 | 10 | void emit_call_main_endloop_x86(struct IBuffer* ibu); 11 | 12 | bool compile_and_write_x86(struct AST* ast, struct Ctx* ctx); 13 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/cg_x86_basic_block.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "util/ctx.h" 6 | #include "rat/rat.h" 7 | #include "basic_block/basicblock.h" 8 | 9 | struct IBuffer; 10 | 11 | // @returns false on error 12 | bool emit_asm_x86_basic_block(struct BasicBlock* block, struct Ctx* ctx, struct IBuffer* ibu, struct RAT* rat, char* current_function_name); 13 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/cg_x86_single_function.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct Method; 8 | struct Ctx; 9 | struct IBuffer; 10 | 11 | void emit_create_stack_frame(uint32_t stack_frame_size, FILE* fout); 12 | 13 | // @returns false on error 14 | bool compile_and_write_x86_single_function(struct Method* m, struct Ctx* ctx, struct IBuffer* ibu); 15 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/cg_x86_single_tac.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Ctx; 6 | struct IBuffer; 7 | struct RAT; 8 | struct TAC; 9 | 10 | bool emit_asm_x86_single_tac(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu, char* current_function_name); 11 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_const_data.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "rat/rat.h" 9 | 10 | #include "tables/symtable/symtable.h" 11 | #include "tac/tac.h" 12 | #include "x86_code_gen/compile_ir/compile_tac.h" 13 | 14 | void compile_tac_const_data_x86(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu) { 15 | 16 | const int reg = rat_get_register(rat, tac_dest(tac)); 17 | 18 | const uint64_t offset = tac_const_value(tac); 19 | 20 | struct DataTable* data_table = ctx_tables(ctx)->data; 21 | 22 | char* symbol = data_symbol(data_table, offset); 23 | 24 | assert(symbol != NULL); 25 | 26 | char* c; 27 | asprintf(&c, "TAC_CONST_DATA %s", symbol); 28 | 29 | mov_const_symbol(reg, symbol, c); 30 | 31 | free(c); 32 | } 33 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_const_value.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "rat/rat.h" 8 | 9 | #include "tac/tac.h" 10 | #include "x86_code_gen/compile_ir/compile_tac.h" 11 | 12 | void compile_tac_const_value_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 13 | 14 | const int reg = rat_get_register(rat, tac_dest(tac)); 15 | 16 | const uint64_t value = tac_const_value(tac); 17 | 18 | char* c; 19 | asprintf(&c, "TAC_CONST_VALUE %lu (0x%lx)", value, value); 20 | 21 | mov_const(reg, (value & 0xffffffff), c); 22 | 23 | free(c); 24 | } 25 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_copy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rat/rat.h" 6 | #include "tac/tac.h" 7 | #include "util/ctx.h" 8 | #include "x86_code_gen/compile_ir/compile_tac.h" 9 | 10 | void compile_tac_copy_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 11 | 12 | const int reg_src = rat_get_register(rat, tac_arg1(tac)); 13 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 14 | 15 | mov_regs(reg_dest, reg_src, "TAC_COPY"); 16 | } 17 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tac/tac.h" 4 | #include "x86_code_gen/compile_ir/compile_tac.h" 5 | 6 | void compile_tac_goto_x86(struct TAC* tac, struct IBuffer* ibu) { 7 | 8 | char str[32]; 9 | sprintf(str, "L%d", tac_label_index(tac)); 10 | 11 | jmp(str, "TAC_GOTO"); 12 | } 13 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_icall.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ibuffer/ibuffer_x86.h" 5 | #include "rat/rat_x86.h" 6 | #include "tables/sst/sst.h" 7 | #include "rat/rat.h" 8 | #include "tables/lvst/lvst.h" 9 | #include "tables/symtable/symtable.h" 10 | 11 | #include "tac/tac.h" 12 | 13 | #include "compile_tac.h" 14 | 15 | void compile_tac_icall_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu, struct Ctx* ctx, char* current_function_name) { 16 | 17 | (void)current_function_name; 18 | (void)ctx; 19 | 20 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 21 | char* c = "TAC_ICALL"; 22 | 23 | const int reg_arg1 = rat_get_register(rat, tac_arg1(tac)); 24 | 25 | icall(reg_arg1, c); 26 | 27 | mov_regs(reg_dest, SD_REG_RAX, c); 28 | } 29 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_if_cmp_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rat/rat.h" 6 | #include "tac/tac.h" 7 | #include "x86_code_gen/compile_ir/compile_tac.h" 8 | 9 | void compile_tac_if_cmp_goto_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 10 | 11 | char* c = "TAC_IF_CMP_GOTO"; 12 | 13 | const int reg1 = rat_get_register(rat, tac_dest(tac)); 14 | const int reg2 = rat_get_register(rat, tac_arg1(tac)); 15 | 16 | cmp(reg1, reg2, c); 17 | 18 | char str[64]; 19 | sprintf(str, "L%d", tac_label_index(tac)); 20 | 21 | switch (tac_op(tac)) { 22 | case TAC_OP_CMP_EQ: je(str, c); break; 23 | case TAC_OP_CMP_NEQ: jne(str, c); break; 24 | case TAC_OP_CMP_GE: jge(str, c); break; 25 | case TAC_OP_CMP_LT: jl(str, c); break; 26 | default: break; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_if_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rat/rat.h" 5 | #include "tac/tac.h" 6 | #include "x86_code_gen/compile_ir/compile_tac.h" 7 | 8 | void compile_tac_if_goto_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 9 | 10 | char* c = "TAC_IF_GOTO"; 11 | 12 | const int reg = rat_get_register(rat, tac_arg1(tac)); 13 | char str[32]; 14 | sprintf(str, "L%d", tac_label_index(tac)); 15 | 16 | //test if r%d is zero 17 | const int rscratch = rat_scratch_reg(rat); 18 | 19 | mov_const(rscratch, 0, c); 20 | cmp(rscratch, reg, c); 21 | jne(str, c); 22 | 23 | // since a bool is only ever 1 byte 24 | // there is no case for wide argument 25 | } 26 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_label.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "tables/sst/sst.h" 5 | #include "tables/stst/stst.h" 6 | #include "tables/lvst/lvst.h" 7 | #include "tables/symtable/symtable.h" 8 | 9 | #include "tac/tacbuffer.h" 10 | #include "tac/tac.h" 11 | #include "x86_code_gen/compile_ir/compile_tac.h" 12 | 13 | bool compile_tac_label_x86(struct TAC* tac, struct IBuffer* ibu, struct Ctx* ctx) { 14 | 15 | char* s; 16 | 17 | if (tac_kind(tac) == TAC_LABEL_INDEXED) { 18 | char str[32]; 19 | sprintf(str, "L%d", tac_label_index(tac)); 20 | s = (char*)&str; 21 | } 22 | 23 | if (tac_kind(tac) == TAC_LABEL_FUNCTION) { 24 | 25 | char* function_name; 26 | 27 | if (tac_dest(tac) < (int32_t)sst_size(ctx_tables(ctx)->sst)) { 28 | 29 | function_name = sst_at(ctx_tables(ctx)->sst, tac_dest(tac))->name; 30 | } else { 31 | fprintf(stderr, "index %d out of bounds in sst\n", tac_dest(tac)); 32 | return false; 33 | } 34 | 35 | s = function_name; 36 | } 37 | 38 | label(s); 39 | 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_load.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "rat/rat.h" 4 | #include "tac/tac.h" 5 | #include "util/ctx.h" 6 | #include "x86_code_gen/compile_ir/compile_tac.h" 7 | 8 | void compile_tac_load_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 9 | 10 | char* c = "TAC_LOAD"; 11 | 12 | //tdest = [targ1] 13 | 14 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 15 | 16 | const int reg_src = rat_get_register(rat, tac_arg1(tac)); 17 | 18 | const uint8_t width = tac_load_store_width(tac); 19 | 20 | if (width < 4) { 21 | // movzx: zero-extend the upper bytes of dest register 22 | movzx_load_width(reg_dest, reg_src, width, c); 23 | } else { 24 | // in case of 32-bit source, 25 | // a mov should automatically zero out the upper bytes of dest register 26 | mov_load_width(reg_dest, reg_src, width, c); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_load_function_ptr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ibuffer/ibuffer_x86.h" 6 | #include "rat/rat.h" 7 | #include "tac/tac.h" 8 | #include "util/ctx.h" 9 | 10 | #include "tables/symtable/symtable.h" 11 | #include "tables/lvst/lvst.h" 12 | 13 | #include "x86_code_gen/compile_ir/compile_tac.h" 14 | 15 | void compile_tac_load_function_ptr_x86(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu) { 16 | 17 | char* c = "TAC_LOAD_FUNCTION_PTR"; 18 | 19 | struct SST* sst = ctx_tables(ctx)->sst; 20 | 21 | char* name = sst_at(sst, tac_arg1(tac))->name; 22 | 23 | const int rdest = rat_get_register(rat, tac_dest(tac)); 24 | 25 | mov_const_symbol(rdest, name, c); 26 | } 27 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_load_local_addr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ibuffer/ibuffer_x86.h" 6 | #include "rat/rat.h" 7 | #include "tac/tac.h" 8 | #include "util/ctx.h" 9 | 10 | #include "tables/symtable/symtable.h" 11 | #include "tables/lvst/lvst.h" 12 | 13 | #include "x86_code_gen/compile_ir/compile_tac.h" 14 | 15 | void compile_tac_load_local_addr_x86(struct RAT* rat, struct TAC* tac, struct Ctx* ctx, struct IBuffer* ibu) { 16 | 17 | char* c = "TAC_LOAD_LOCAL_ADDR"; 18 | 19 | char* name = lvst_at(ctx_tables(ctx)->lvst, tac_arg1(tac))->name; 20 | 21 | // In x86-64, arguments are passed in registers, but we do save 22 | // them into the stack frame when the stack frame is setup. 23 | // So each variable, no matter if arg or local, should have an address. 24 | 25 | const int rdest = rat_get_register(rat, tac_dest(tac)); 26 | 27 | const ssize_t offset = lvst_stack_frame_offset_x86(ctx_tables(ctx)->lvst, name); 28 | 29 | mov_const(rdest, -offset, c); 30 | 31 | add(rdest, rat_base_ptr(rat), c); 32 | } 33 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_nop.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "x86_code_gen/compile_ir/compile_tac.h" 4 | 5 | void compile_tac_nop_x86(struct IBuffer* ibu) { 6 | 7 | nop("TAC_NOP"); 8 | } 9 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_param.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "rat/rat.h" 4 | #include "rat/rat_x86.h" 5 | 6 | #include "tac/tac.h" 7 | #include "x86_code_gen/compile_ir/compile_tac.h" 8 | 9 | void compile_tac_param_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 10 | 11 | const char* c = "TAC_PARAM"; 12 | 13 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 14 | 15 | const bool is_syscall = tac_param_is_syscall(tac); 16 | 17 | const enum SD_REGISTER param_reg = rat_param_reg_x86(tac_param_index(tac), is_syscall); 18 | 19 | mov_regs(param_reg, reg_dest, c); 20 | } 21 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_store.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "rat/rat.h" 6 | #include "tac/tac.h" 7 | #include "util/ctx.h" 8 | #include "x86_code_gen/compile_ir/compile_tac.h" 9 | 10 | void compile_tac_store_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 11 | 12 | char* c = "TAC_STORE"; 13 | 14 | const int reg_dest = rat_get_register(rat, tac_dest(tac)); 15 | 16 | const int reg_src = rat_get_register(rat, tac_arg1(tac)); 17 | 18 | mov_store_width(reg_dest, reg_src, tac_load_store_width(tac), c); 19 | } 20 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/compile_ir/compile_tac_unary_op.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rat/rat.h" 5 | #include "tac/tac.h" 6 | #include "x86_code_gen/compile_ir/compile_tac.h" 7 | #include "ibuffer/ibuffer_x86.h" 8 | 9 | void compile_tac_unary_op_x86(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { 10 | 11 | int reg_src = rat_get_register(rat, tac_arg1(tac)); 12 | 13 | int reg_dest = rat_get_register(rat, tac_dest(tac)); 14 | 15 | char* c = "TAC_UNARY_OP"; 16 | 17 | switch (tac_op(tac)) { 18 | 19 | case TAC_OP_UNARY_NOT: 20 | cmp_const(reg_src, 0, c); 21 | sete(reg_dest, c); 22 | movzx_regs(reg_dest, reg_dest, 1, c); 23 | break; 24 | 25 | case TAC_OP_UNARY_BITWISE_NEG: 26 | mov_regs(reg_dest, reg_src, c); 27 | not(reg_dest, c); 28 | break; 29 | 30 | case TAC_OP_UNARY_MINUS: 31 | 32 | mov_regs(reg_dest, reg_src, c); 33 | neg(reg_dest, c); 34 | break; 35 | default: 36 | break; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/syscalls/syscalls.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "syscalls.h" 9 | 10 | extern struct Syscall syscalls[]; 11 | 12 | uint64_t syscall_number(char* name) { 13 | 14 | for (int i = 0; true; i++) { 15 | char* syscall_name = syscalls[i].name; 16 | 17 | if (syscall_name == NULL) { 18 | break; 19 | } 20 | 21 | if (strcmp(name, syscall_name) == 0) { 22 | return syscalls[i].number; 23 | } 24 | } 25 | fprintf(stderr, "syscall with name '%s' not found.\n", name); 26 | assert(false); 27 | return 1; 28 | } 29 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/syscalls/syscalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct Syscall { 7 | char* name; 8 | uint64_t number; 9 | }; 10 | 11 | uint64_t syscall_number(char* name); 12 | -------------------------------------------------------------------------------- /compiler/main/x86_code_gen/syscalls/table.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "syscalls.h" 9 | 10 | // TODO: enter all syscalls here 11 | struct Syscall syscalls[] = { 12 | { 13 | .name = "read", 14 | .number = 0, 15 | }, 16 | { 17 | .name = "write", 18 | .number = 1, 19 | }, 20 | { 21 | .name = "open", 22 | .number = 2, 23 | }, 24 | { 25 | .name = "close", 26 | .number = 3, 27 | }, 28 | { 29 | .name = "lseek", 30 | .number = 8, 31 | }, 32 | { 33 | .name = "mmap", 34 | .number = 9, 35 | }, 36 | { 37 | .name = "munmap", 38 | .number = 11, 39 | }, 40 | { 41 | .name = "exit", 42 | .number = 60, 43 | }, 44 | { 45 | .name = "kill", 46 | .number = 62, 47 | }, 48 | 49 | { 50 | // marks end of array 51 | .name = NULL, 52 | .number = 0, 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /compiler/test/avr_code_gen/compile_ir/test_compile_tac_goto.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libvmcu/libvmcu_system.h" 6 | #include "libvmcu/libvmcu_analyzer.h" 7 | 8 | #include "avr_code_gen/cg_avr.h" 9 | #include "avr_code_gen/cg_avr_basic_block.h" 10 | 11 | #include "tac/tacbuffer.h" 12 | 13 | #include "../test_avr_code_gen.h" 14 | #include "../test_avr_code_gen_util.h" 15 | 16 | #include "test_compile_tac.h" 17 | 18 | void test_compile_tac_goto() { 19 | 20 | status_test_codegen("TAC_GOTO"); 21 | 22 | struct TACBuffer* b = tacbuffer_ctor(); 23 | 24 | tacbuffer_append(b, makeTACLabel(0, 43)); 25 | tacbuffer_append(b, makeTACGoto(0, 43)); 26 | tacbuffer_append(b, makeTACReturn(0, 0)); 27 | 28 | vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); 29 | 30 | vmcu_system_step_n(system, 7); 31 | 32 | const uint32_t old_pc = vmcu_system_get_pc(system); 33 | 34 | vmcu_system_step_n(system, 5); 35 | 36 | //assert that the PC has not changed 37 | assert(vmcu_system_get_pc(system) == old_pc); 38 | 39 | vmcu_system_dtor(system); 40 | } 41 | -------------------------------------------------------------------------------- /compiler/test/avr_code_gen/test_avr_code_gen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libvmcu/libvmcu_system.h" 6 | #include "libvmcu/libvmcu_analyzer.h" 7 | 8 | #include "avr_code_gen/cg_avr.h" 9 | #include "avr_code_gen/cg_avr_basic_block.h" 10 | 11 | #include "tac/tacbuffer.h" 12 | 13 | #include "test_avr_code_gen.h" 14 | #include "test_avr_code_gen_util.h" 15 | 16 | #include "compile_ir/test_compile_tac.h" 17 | 18 | #include "timer/test_avr_code_gen_timer.h" 19 | 20 | void status_test_codegen(char* msg) { 21 | printf(" - [TEST] avr codegen %s\n", msg); 22 | } 23 | -------------------------------------------------------------------------------- /compiler/test/avr_code_gen/test_avr_code_gen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "compile_ir/test_compile_tac.h" 4 | #include "timer/test_avr_code_gen_timer.h" 5 | 6 | void status_test_codegen(char* msg); 7 | -------------------------------------------------------------------------------- /compiler/test/avr_code_gen/test_avr_code_gen_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../../dependencies/libvmcu-Virtual-MCU-Library/engine/include/libvmcu/libvmcu_system.h" 4 | struct TACBuffer; 5 | 6 | //compile a struct TACBuffer* to .asm 7 | //call avra to create .hex 8 | //create vmcu_model_t 9 | //create vmcu_report_t 10 | //create a vmcu_system_t 11 | //return vmcu_system_t* 12 | 13 | vmcu_system_t* prepare_vmcu_system_from_tacbuffer(struct TACBuffer* buffer); 14 | 15 | // additionally creates a red zone around the given address, 16 | // to be able to later check if any unintended writes or reads happened there 17 | vmcu_system_t* prepare_vmcu_system_from_tacbuffer_with_redzone(struct TACBuffer* buffer, uint16_t addr_redzone, uint8_t redzone); 18 | 19 | // assert that the values around the address still have 'redzone' value 20 | void assert_redzone(vmcu_system_t* system, uint16_t addr, uint8_t width, uint8_t redzone); 21 | -------------------------------------------------------------------------------- /compiler/test/avr_code_gen/timer/test_avr_code_gen_timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_avr_code_gen_timer(); 4 | -------------------------------------------------------------------------------- /compiler/test/gen_tac/test_gen_tac.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test_gen_tac.h" 5 | 6 | void status_test_codegen_tac(char* msg) { 7 | printf(" - [TEST] TAC CodeGen %s\n", msg); 8 | } 9 | -------------------------------------------------------------------------------- /compiler/test/libvmcu_utils/libvmcu_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //utilities for testing with libvmcu. 4 | 5 | #include "libvmcu/libvmcu_system.h" 6 | #include "libvmcu/libvmcu_analyzer.h" 7 | 8 | void vmcu_system_step_n(vmcu_system_t* system, uint32_t count); 9 | 10 | // Do 1 step and compare register values. 11 | // Print any register values which have changed. 12 | void vmcu_system_step_debug(vmcu_system_t* system); 13 | 14 | void vmcu_system_step_n_debug(vmcu_system_t* system, uint32_t count); 15 | 16 | uint16_t vmcu_system_read_sp(vmcu_system_t* system); 17 | 18 | uint16_t vmcu_system_read_y(vmcu_system_t* system); 19 | 20 | uint16_t vmcu_system_read_data16(vmcu_system_t* system, uint16_t addr); 21 | uint32_t vmcu_system_read_data32(vmcu_system_t* system, uint16_t addr); 22 | uint64_t vmcu_system_read_data64(vmcu_system_t* system, uint16_t addr); 23 | 24 | void vmcu_system_write_data16(vmcu_system_t* system, uint16_t addr, uint16_t value); 25 | 26 | // read 16 bit value from 2 adjacent gprs 27 | uint16_t vmcu_system_read_2_gpr(vmcu_system_t* system, const int low_reg); 28 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/all_errors.dg: -------------------------------------------------------------------------------- 1 | /* 2 | DO NOT DELETE. 3 | create a test from this, that checks 4 | that this file truly triggers all possibly typechecker errors. 5 | 6 | this file could also be used to improve the error messages 7 | and make them consistent, since all error messages 8 | can be seen at once. 9 | */ 10 | 11 | fn main()~>int { 12 | hello(); 13 | int k = u; 14 | 15 | if 3 {} 16 | 17 | while 'c' {} 18 | 19 | for i in 0 .. 'c' {} 20 | 21 | int k = 3 + 'c'; 22 | 23 | int k2 = 'c'; 24 | 25 | [int] arr = malloc(); 26 | 27 | int m = arr['c']; 28 | 29 | int n = arr[0][3]; 30 | 31 | int help = 3; 32 | 33 | help(); 34 | 35 | sub(true); 36 | sub(3,3); 37 | 38 | int j = !3; 39 | 40 | return 'h'; 41 | } 42 | 43 | fn sub(int a)->int { 44 | return a; 45 | } 46 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/assign_primitive.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | 3 | int k = 'c'; 4 | 5 | return 0; 6 | } -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/binop_type_mismatch.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | char c = (3+'c'); 3 | return 3; 4 | } -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/condition_requires_bool.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int{ 2 | if 3 { return 3; } 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/impure_called_in_pure.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int{ 2 | return sub1(); 3 | } 4 | fn sub1()->int { return sub2(); } 5 | fn sub2()~>int { return 1; } 6 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/index_not_found.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | 3 | local [uint8] arr; 4 | 5 | return arr[index]; 6 | } 7 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/local_var_not_a_subroutine.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | 3 | int k = 0; 4 | return k(); 5 | } 6 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/no_return_stmt.dg: -------------------------------------------------------------------------------- 1 | fn main () -> int { 2 | 3 | uint8 x = 3; 4 | 5 | if x == 3 { 6 | x = 2; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/range_requires_int.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int{ 2 | for i in 0 .. 'c' {} 3 | return 0; 4 | } 5 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/subr_not_found.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int{ 2 | return sub(); 3 | } -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/switch_case_type_mismatch.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | int k = 0; 3 | switch k { 4 | case 'c' {} 5 | } 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/switch_requires_primitive.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int{ 2 | (()~>int) f= main; 3 | switch f { 4 | case 0x0 {} 5 | } 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/too_many_indices.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main()~>int { 3 | 4 | [int] arr = 0x0; 5 | return arr[0][1]; 6 | } 7 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/var_not_found.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | 3 | return k; 4 | } 5 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/wrong_number_of_args.dg: -------------------------------------------------------------------------------- 1 | fn main() ~> int { 2 | return sub(3); 3 | } 4 | fn sub() -> int { return 3; } -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/wrong_op_unop.dg: -------------------------------------------------------------------------------- 1 | fn main()~> int { 2 | return !2; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/wrong_return_type.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | return 'c'; 3 | } -------------------------------------------------------------------------------- /compiler/test/typechecker/test-src/wrong_type_of_arg.dg: -------------------------------------------------------------------------------- 1 | fn main() ~> int { 2 | sub(3); 3 | return 0; 4 | } 5 | fn sub(char c) ~> int { return 0; } -------------------------------------------------------------------------------- /compiler/test/typechecker/test_typechecker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_typecheck_wrong_assign_primitive(); 4 | void test_typecheck_wrong_number_of_args(); 5 | void test_typecheck_wrong_type_of_arg(); 6 | void test_typecheck_wrong_return_type(); 7 | void test_typecheck_binop_type_mismatch(); 8 | void test_typecheck_subr_not_found(); 9 | void test_typecheck_impure_called_in_pure(); 10 | void test_typecheck_condition_requires_bool(); 11 | void test_typecheck_range_requires_int(); 12 | void test_typecheck_wrong_op_unop(); 13 | void test_typecheck_too_many_indices(); 14 | void test_typecheck_local_var_not_a_subroutine(); 15 | void test_typecheck_var_not_found(); 16 | void test_typecheck_index_not_found(); 17 | void test_typecheck_no_return_stmt(); 18 | void test_typecheck_all_type_errors(); 19 | -------------------------------------------------------------------------------- /compiler/test/typechecker/test_typechecker_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // @returns NULL on error 4 | struct TCError* typecheck_file(char* filename); 5 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_call_with_array_access.dg: -------------------------------------------------------------------------------- 1 | 2 | fn sub()~>int { 3 | 4 | [(()->int)] b = get(); 5 | 6 | return b[0](); 7 | } 8 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_call_with_struct_member_access.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Astruct { 3 | (()->int) x; 4 | } 5 | 6 | fn sub()~>int { 7 | 8 | Astruct b = get(); 9 | 10 | return b.x(); 11 | } 12 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_expr.dg: -------------------------------------------------------------------------------- 1 | fn sub()->int { 2 | return 3 - 2; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_expr_multiple_terms.dg: -------------------------------------------------------------------------------- 1 | fn sub()->int { 2 | return 3 + 4; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_ptr_arithmetic.dg: -------------------------------------------------------------------------------- 1 | fn sub() -> *uint64 { 2 | 3 | local *uint64 ptr; 4 | ptr = 0; 5 | return ptr + 2; 6 | } 7 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_return_type_subroutine.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | return sub(); 3 | } 4 | fn sub()->int { return 0; } 5 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_simplevar_no_indices.dg: -------------------------------------------------------------------------------- 1 | fn main()~>int { 2 | char c = 'k'; 3 | return c; 4 | } 5 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_simplevar_with_indices.dg: -------------------------------------------------------------------------------- 1 | 2 | fn sub()~>bool { 3 | [bool] arr = arr_ctor(); 4 | return arr[0]; 5 | } 6 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_term.dg: -------------------------------------------------------------------------------- 1 | fn sub()~>int { 2 | return 83; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_type_param.dg: -------------------------------------------------------------------------------- 1 | fn sub(?T0 arg) -> ?T0 { 2 | return arg; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_unopterm.dg: -------------------------------------------------------------------------------- 1 | fn sub()->bool { 2 | return !true; 3 | } 4 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test-src/infer_type_var_with_member_access.dg: -------------------------------------------------------------------------------- 1 | 2 | struct MyStruct { 3 | int a; 4 | } 5 | 6 | fn sub()~>int { 7 | MyStruct x = mystruct_ctor(); 8 | return x.a; 9 | } 10 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test_typeinference.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | //term/expr/const 6 | void test_infer_type_term(); 7 | void test_infer_type_unopterm(); 8 | void test_infer_type_expr(); 9 | void test_infer_type_expr_multiple_terms(); 10 | 11 | //call 12 | void test_infer_type_return_type_subroutine(); 13 | void test_infer_type_call_with_struct_member_access(); 14 | void test_infer_type_call_with_array_access(); 15 | 16 | //variables 17 | void test_infer_type_simplevar_no_indices(); 18 | void test_infer_type_simplevar_with_indices(); 19 | void test_infer_type_var_with_member_access(); 20 | 21 | //type parameters 22 | void test_infer_type_type_param(); 23 | 24 | void test_infer_type_ptr_arithmetic(); 25 | -------------------------------------------------------------------------------- /compiler/test/typeinference/test_typeinference_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Type* typeinfer_in_file(char* filename); 4 | -------------------------------------------------------------------------------- /compiler/test/x86_code_gen/fake_lvst.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "tables/lvst/lvst.h" 4 | 5 | #include "util/ctx.h" 6 | 7 | void sd_uc_fake_lvst(struct Ctx* ctx, size_t fake_lvst_size, size_t stackframe_nargs); 8 | 9 | struct Type* fake_uint64_type(); 10 | -------------------------------------------------------------------------------- /compiler/test/x86_code_gen/test_x86_code_gen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "x86_code_gen/cg_x86.h" 6 | #include "x86_code_gen/cg_x86_basic_block.h" 7 | 8 | #include "tac/tacbuffer.h" 9 | 10 | #include "test_x86_code_gen.h" 11 | #include "test_x86_code_gen_util.h" 12 | 13 | #include "compile_ir/test_compile_tac.h" 14 | 15 | void status_test_x86_codegen(char* msg) { 16 | printf(" - [TEST] x86 codegen %s\n", msg); 17 | } 18 | -------------------------------------------------------------------------------- /compiler/test/x86_code_gen/test_x86_code_gen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "compile_ir/test_compile_tac.h" 4 | 5 | void status_test_x86_codegen(char* msg); 6 | -------------------------------------------------------------------------------- /dependencies/.gitignore: -------------------------------------------------------------------------------- 1 | libvmcu-Virtual-MCU-Library/ 2 | unicorn/ 3 | -------------------------------------------------------------------------------- /dependencies/Makefile: -------------------------------------------------------------------------------- 1 | all: build-libvmcu unicorn/build/libunicorn.so 2 | 3 | build-libvmcu: libvmcu-Virtual-MCU-Library 4 | cd libvmcu-Virtual-MCU-Library/build-release; make -f build.mk; cd ../.. 5 | 6 | unicorn/build/libunicorn.so: unicorn 7 | # i tried to have this be a cmake ExternalProject_Add but did not get far 8 | cd unicorn; mkdir build; cd build; cmake .. -DCMAKE_BUILD_TYPE=Release -DUNICORN_ARCH="x86" -DUNICORN_INSTALL=True -DCMAKE_POLICY_VERSION_MINIMUM=3.5; make 9 | # -DUNICORN_HAS_X86=True 10 | 11 | libvmcu-Virtual-MCU-Library: 12 | git clone https://github.com/Milo-D/libvmcu-Virtual-MCU-Library.git 13 | 14 | unicorn: 15 | git clone https://github.com/unicorn-engine/unicorn.git 16 | cd unicorn; git reset --hard d4b9248 17 | 18 | -------------------------------------------------------------------------------- /docs/_headers: -------------------------------------------------------------------------------- 1 | #https://docs.netlify.com/routing/headers/#syntax-for-the-headers-file 2 | #https://developer.mozilla.org/de/docs/Web/HTTP/Headers/Cache-Control 3 | 4 | #cache for 30 minutes 5 | #and accept expired resources if they are 6 | #max 30 minutes expired 7 | /* 8 | cache-control: max-age=1200 9 | cache-control: public 10 | cache-control: max-stale=1200 11 | -------------------------------------------------------------------------------- /docs/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | h1,h2,h3,h4,h5 { 3 | color: #D14F42; 4 | } 5 | 6 | html { 7 | /* padding from the top when clicking 8 | * ... 9 | * section links 10 | * https://getpublii.com/blog/one-line-css-solution-to-prevent-anchor-links-from-scrolling-behind-a-sticky-header.html 11 | */ 12 | scroll-margin-top: 20%; 13 | scroll-padding-top: 20%; 14 | } 15 | 16 | body { 17 | font-family: monospace; 18 | font-size: 1rem; 19 | background-color: #fefefe; 20 | } 21 | 22 | a { 23 | color: #006C11; 24 | } 25 | 26 | pre { 27 | /* highlight code snippets */ 28 | background-color: rgb(235, 204, 145); 29 | border-radius: 0.3rem; 30 | padding: 1rem; 31 | font-size: 1rem; 32 | } 33 | 34 | .nav-bg{ 35 | background-color: rgb(159, 201, 167); 36 | padding: 0.6rem; 37 | } 38 | 39 | .nav-bg a { 40 | color: rgb(209, 79, 66); 41 | font-size: 1.2rem; 42 | } 43 | 44 | .box { 45 | border: 1px solid rgb(209, 79, 66); 46 | border-radius: 6px; 47 | margin: 2px; 48 | padding: 5px; 49 | } 50 | -------------------------------------------------------------------------------- /docs/googlec8c33fc0ae3784b9.html: -------------------------------------------------------------------------------- 1 | google-site-verification: googlec8c33fc0ae3784b9.html -------------------------------------------------------------------------------- /docs/html/architecture.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Architecture 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 23 | 24 |

Architecture

25 | 26 | smalldragon architecture 27 | 28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/html/skeleton.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Skeleton Page 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 22 | 23 |

Heading 1

24 | 25 |

26 | Content 27 |
28 | Content 29 |

30 | 31 |

Heading 2

32 | 33 |

34 | Content 35 |
36 | Content 37 |

38 | 39 |

Heading 3

40 | 41 |

42 | Content 43 |
44 | Content 45 |
46 | Content 47 |
48 | Content 49 |

50 |
51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/docs/img/favicon.ico -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.asm 3 | main 4 | *.dracovm 5 | *.dg.json 6 | *.java 7 | 8 | #the transpiled C files 9 | *.c 10 | *.h 11 | *.o 12 | *.elf 13 | *.hex 14 | *.cof 15 | *.obj 16 | *.bin 17 | 18 | *.ppm 19 | 20 | gtk/ 21 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | 2 | CALL2 := sd 3 | CALLX86 := sd -x86 4 | 5 | all: examples-avr examples-x86 6 | 7 | examples-x86: 8 | @echo "[Examples] Compiling Example Programs (x86)" 9 | $(CALLX86) other/everything.dg 10 | $(CALLX86) typeinference/localvartypeinference.dg 11 | $(CALLX86) array/array.dg 12 | make -C externc 13 | ./assert_examples.sh 14 | @echo "[Examples (x86)] done" 15 | 16 | examples-avr: 17 | @echo "[Examples] Compiling Example Programs (AVR)" 18 | $(CALL2) ifstatement/true.dg 19 | $(CALL2) ifstatement/false.dg 20 | $(CALL2) local_variables/simple.dg 21 | $(CALL2) loops/whileloop/whileloop.dg 22 | $(CALL2) loops/forloop/forloop.dg 23 | $(CALL2) methodCalls/add/add_8.dg 24 | $(CALL2) methodCalls/add/add_16.dg 25 | $(CALL2) other/everything.dg 26 | $(CALL2) typeinference/localvartypeinference.dg 27 | $(CALL2) array/array.dg 28 | $(MAKE) -C led_blink_timer 29 | $(MAKE) -C led_blink_no_timer 30 | @echo "[Examples (AVR)] done" 31 | 32 | clean: 33 | rm -f */*.tokens 34 | rm -f */*.out 35 | -------------------------------------------------------------------------------- /examples/array/array.dg: -------------------------------------------------------------------------------- 1 | fn main()->int { 2 | 3 | [int] arr = 0xc7; 4 | 5 | arr[1] = 0xff; 6 | 7 | return arr[1]; 8 | } 9 | -------------------------------------------------------------------------------- /examples/array/array2.dg: -------------------------------------------------------------------------------- 1 | fn main()->int { 2 | 3 | [[int]] arr = 199; //0xc7 4 | 5 | arr[0] = 200; //0xc8 6 | 7 | arr[0][0] = 255; //0xff 8 | 9 | return arr[0][0]; 10 | } 11 | -------------------------------------------------------------------------------- /examples/enum/enum_hex_value/enum_hex_value.dg: -------------------------------------------------------------------------------- 1 | 2 | enum VALUES { 3 | VALUE_1 = 0x1; 4 | VALUE_6 = 0x6; 5 | VALUE_9 = 0x9; 6 | } 7 | 8 | fn main () -> int { 9 | 10 | return VALUE_9; 11 | } 12 | -------------------------------------------------------------------------------- /examples/enum/enum_hex_value/enum_hex_value.exitcode: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /examples/enum/simple_enum/simple_enum.dg: -------------------------------------------------------------------------------- 1 | 2 | enum VALUES { 3 | VALUE_1 = 1; 4 | VALUE_28 = 28; 5 | VALUE_29 = 29; 6 | } 7 | 8 | fn main () -> int { 9 | 10 | return VALUE_28; 11 | } 12 | -------------------------------------------------------------------------------- /examples/enum/simple_enum/simple_enum.exitcode: -------------------------------------------------------------------------------- 1 | 28 2 | -------------------------------------------------------------------------------- /examples/externc/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: compile run 3 | 4 | run: /tmp/program 5 | /tmp/program 6 | 7 | compile: caller.dg f1.c 8 | rm -f *.o 9 | gcc -c f1.c 10 | sd -x86 -nolink caller.dg 11 | ld -o /tmp/program f1.o caller.o 12 | -------------------------------------------------------------------------------- /examples/externc/caller.dg: -------------------------------------------------------------------------------- 1 | 2 | @extern 3 | fn f1() -> int {} 4 | 5 | fn main() ~> int { 6 | 7 | // should result in exit code 0 8 | return f1() - 6; 9 | } 10 | -------------------------------------------------------------------------------- /examples/externc/f1.c: -------------------------------------------------------------------------------- 1 | 2 | int f1(){ 3 | 4 | return 6; 5 | } 6 | -------------------------------------------------------------------------------- /examples/externc/params/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: compile run 3 | 4 | run: /tmp/program 5 | /tmp/program 6 | 7 | compile: caller_params.dg f2.c 8 | rm -f *.o 9 | gcc -g -c f2.c 10 | sd -x86 -nolink caller_params.dg 11 | ld -o /tmp/program f2.o caller_params.o 12 | -------------------------------------------------------------------------------- /examples/externc/params/caller_params.dg: -------------------------------------------------------------------------------- 1 | 2 | @extern 3 | fn f2(int x) -> int {} 4 | 5 | fn main() ~> int { 6 | 7 | return f2(-2); 8 | } 9 | -------------------------------------------------------------------------------- /examples/externc/return-value/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: compile run 3 | 4 | run: /tmp/program 5 | /tmp/program 6 | 7 | compile: caller.dg f1.c 8 | rm -f *.o 9 | gcc -c f1.c 10 | sd -x86 -nolink caller.dg 11 | ld -o /tmp/program f1.o caller.o 12 | -------------------------------------------------------------------------------- /examples/externc/return-value/caller.dg: -------------------------------------------------------------------------------- 1 | 2 | @extern 3 | fn f1() -> int {} 4 | 5 | fn main() ~> int { 6 | 7 | // should result in exit code 0 8 | return f1() - 6; 9 | } 10 | -------------------------------------------------------------------------------- /examples/ifstatement/false.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | 4 | uint x = 3 ; 5 | 6 | if x > 5 { 7 | return 44; 8 | } else { 9 | return 55; 10 | } 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /examples/ifstatement/false.exitcode: -------------------------------------------------------------------------------- 1 | 55 2 | -------------------------------------------------------------------------------- /examples/ifstatement/true.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | 4 | uint x = 3 ; 5 | 6 | if x < 5 { 7 | return 44; 8 | } 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /examples/ifstatement/true.exitcode: -------------------------------------------------------------------------------- 1 | 44 2 | -------------------------------------------------------------------------------- /examples/led_blink_no_timer/Makefile: -------------------------------------------------------------------------------- 1 | main: compile 2 | 3 | compile: 4 | sd led_blink_no_timer.dg 5 | 6 | flash: 7 | sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink_no_timer.hex 8 | clean: 9 | rm -f *.hex *.obj *.cof *.asm *.png *.dot 10 | 11 | -------------------------------------------------------------------------------- /examples/led_blink_timer/Makefile: -------------------------------------------------------------------------------- 1 | main: compile 2 | 3 | compile: clean 4 | sd -stdlib led_blink.dg 5 | 6 | flash: 7 | sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink.hex 8 | 9 | clean: 10 | rm -f *.hex *.obj *.cof *.asm *.png *.dot 11 | 12 | -------------------------------------------------------------------------------- /examples/led_blink_timer/led_blink.dg: -------------------------------------------------------------------------------- 1 | //Program to make an LED Blink using Timers 2 | 3 | //Arduino Board: 4 | //https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf 5 | 6 | /* Hardware Setup 7 | 8 | GND ----- LED ----- Resistor 9 | | 10 | D13 PIN -------------------| 11 | 12 | */ 13 | 14 | //LED_BUILTIN PB5 15 | //PB5 is on D13 on the Arduino 16 | //PB0 is on D08 on the Arduino 17 | 18 | fn main () ~> int { 19 | //set D13 / PB5 20 | 21 | portb_ddrd(0xff); // set everything to output 22 | 23 | while(true){ 24 | 25 | portb_write(0b00010000); 26 | delay(); 27 | delay(); 28 | portb_write(0b00100000); 29 | delay(); 30 | delay(); 31 | } 32 | return 1; 33 | } 34 | 35 | fn delay() -> int { 36 | 37 | //using Timer0 38 | 39 | //TCCR0A = 0x0, set timer mode 40 | timer0_mode(0x0); 41 | 42 | //TCCR0B = 0b00000101, set prescaler to 1024 43 | timer0_prescaler(0x5); 44 | 45 | //while(TCNT0 != 0xfe){} 46 | while(timer0_read() != 0xfe){} 47 | 48 | return 1; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /examples/local_variables/simple.dg: -------------------------------------------------------------------------------- 1 | fn main () -> int { 2 | 3 | int x = 10; 4 | int k = 0; 5 | 6 | // testing load of x 7 | // testing store of k 8 | k = x + 3; 9 | 10 | return k; 11 | } 12 | -------------------------------------------------------------------------------- /examples/local_variables/simple.exitcode: -------------------------------------------------------------------------------- 1 | 13 2 | -------------------------------------------------------------------------------- /examples/loops/forloop/forloop.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | 3 | int16 n = 0; 4 | 5 | for i in 0 .. 10 { 6 | n += 1; 7 | } 8 | 9 | return n; 10 | } 11 | -------------------------------------------------------------------------------- /examples/loops/forloop/forloop.exitcode: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /examples/loops/whileloop/whileloop.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main ()~> int { 3 | uint i=0; 4 | uint j=0; 5 | while (i < 33){ 6 | j = j + 1; 7 | i = i + 1; 8 | } 9 | return j; 10 | } 11 | -------------------------------------------------------------------------------- /examples/loops/whileloop/whileloop.exitcode: -------------------------------------------------------------------------------- 1 | 33 2 | -------------------------------------------------------------------------------- /examples/mathematics/div/div.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local uint32 x; 5 | 6 | x = 33 / 3; 7 | 8 | return x; 9 | } 10 | -------------------------------------------------------------------------------- /examples/mathematics/div/div.exitcode: -------------------------------------------------------------------------------- 1 | 11 2 | -------------------------------------------------------------------------------- /examples/mathematics/div_int/div_int.dg: -------------------------------------------------------------------------------- 1 | // test that the integer division semantic applies correctly 2 | 3 | fn main () -> int { 4 | 5 | local uint32 x; 6 | 7 | x = 100 / 3; 8 | 9 | return x; 10 | } 11 | -------------------------------------------------------------------------------- /examples/mathematics/div_int/div_int.exitcode: -------------------------------------------------------------------------------- 1 | 33 2 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_11.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | return fibonacci(11); 3 | } 4 | 5 | fn fibonacci (uint n) -> uint{ 6 | 7 | if(n<3){ 8 | return 1; 9 | } 10 | return (fibonacci(n-1)+fibonacci(n-2)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_11.exitcode: -------------------------------------------------------------------------------- 1 | 89 2 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_3.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | return fibonacci(3); 3 | } 4 | 5 | fn fibonacci (uint n) -> uint{ 6 | 7 | if(n<3){ 8 | return 1; 9 | } 10 | return (fibonacci(n-1)+fibonacci(n-2)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_3.exitcode: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_4.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | return fibonacci(4); 3 | } 4 | 5 | fn fibonacci (uint n) -> uint{ 6 | 7 | if(n<3){ 8 | return 1; 9 | } 10 | return (fibonacci(n-1)+fibonacci(n-2)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_4.exitcode: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_5.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | return fibonacci(5); 3 | } 4 | 5 | fn fibonacci (uint n) -> uint{ 6 | 7 | if(n<3){ 8 | return 1; 9 | } 10 | return (fibonacci(n-1)+fibonacci(n-2)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_5.exitcode: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_6.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | return fibonacci(6); 3 | } 4 | 5 | fn fibonacci (uint n) -> uint{ 6 | 7 | if(n<3){ 8 | return 1; 9 | } 10 | return (fibonacci(n-1)+fibonacci(n-2)); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /examples/mathematics/fibonacci_6.exitcode: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /examples/mathematics/modulus/mod.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local uint32 x; 5 | 6 | x = 100 % 40; 7 | 8 | return x; // should be 20 9 | } 10 | -------------------------------------------------------------------------------- /examples/mathematics/modulus/mod.exitcode: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /examples/methodCalls/3-deep/3deep.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main() ~> int { 3 | 4 | return f1(1); 5 | } 6 | 7 | fn f1(int x) -> int { 8 | return f2(x); 9 | } 10 | 11 | fn f2(int y) -> int { 12 | return y + 4; 13 | } 14 | -------------------------------------------------------------------------------- /examples/methodCalls/3-deep/3deep.exitcode: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_16.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | return add( 9, 8 ); 4 | } 5 | 6 | fn add (uint16 a, uint16 b) ~> uint16 { 7 | return ( a + b ) ; 8 | } 9 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_16.exitcode: -------------------------------------------------------------------------------- 1 | 17 2 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_32.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | return add( 3, 30 ); 4 | } 5 | 6 | fn add (uint32 a, uint32 b) ~> uint32 { 7 | return ( a + b ) ; 8 | } 9 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_32.exitcode: -------------------------------------------------------------------------------- 1 | 33 2 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_64.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | return add( 25, 40 ); 4 | } 5 | 6 | fn add (uint64 a, uint64 b) ~> uint64 { 7 | return ( a + b ) ; 8 | } 9 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_64.exitcode: -------------------------------------------------------------------------------- 1 | 65 2 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_8.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | return add( 2, 7 ); 4 | } 5 | 6 | fn add (uint8 a, uint8 b) ~> uint8 { 7 | return ( a + b ) ; 8 | } 9 | -------------------------------------------------------------------------------- /examples/methodCalls/add/add_8.exitcode: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /examples/methodCalls/call_as_arg/call_as_arg.dg: -------------------------------------------------------------------------------- 1 | // A function call as argument to another function call 2 | // This stresses the compilers ability to calculate the liveness correctly 3 | 4 | fn f(uint8 x, uint8 y) -> uint8 { 5 | return x+y; 6 | } 7 | 8 | fn main () -> int { 9 | // 9 10 | return f( 11 | f( 12 | f(0, 1), 13 | 2 14 | ), 15 | f( 16 | 0, 17 | f( 18 | 1, 19 | f(2, 3) 20 | ) 21 | ) 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /examples/methodCalls/call_as_arg/call_as_arg.exitcode: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /examples/methodCalls/function_ptr/function_ptr.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f () -> int8 { 3 | 4 | return 8; 5 | } 6 | 7 | fn main () ~> int { 8 | 9 | local (() -> int) ptr; 10 | 11 | ptr = f; 12 | 13 | int8 r = ptr(); 14 | 15 | return r; 16 | } 17 | -------------------------------------------------------------------------------- /examples/methodCalls/function_ptr/function_ptr.exitcode: -------------------------------------------------------------------------------- 1 | 8 2 | -------------------------------------------------------------------------------- /examples/methodCalls/function_ptr_with_arg/function_ptr_with_arg.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f (int8 x) -> int8 { 3 | 4 | return 8 + x; 5 | } 6 | 7 | fn main () ~> int { 8 | 9 | local ((int8) -> int8) ptr; 10 | 11 | ptr = f; 12 | 13 | int8 r = ptr(2); 14 | 15 | return r; 16 | } 17 | -------------------------------------------------------------------------------- /examples/methodCalls/function_ptr_with_arg/function_ptr_with_arg.exitcode: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /examples/methodCalls/pass_function_ptr/pass_function_ptr.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f () -> int8 { 3 | 4 | return 9; 5 | } 6 | 7 | fn g ((() -> int8) other) -> int8 { 8 | 9 | int8 x = other(); 10 | 11 | return x; 12 | } 13 | 14 | fn main () ~> int { 15 | 16 | local (() -> int8) ptr; 17 | 18 | ptr = f; 19 | 20 | int8 r = g(ptr); 21 | 22 | return r; 23 | } 24 | -------------------------------------------------------------------------------- /examples/methodCalls/pass_function_ptr/pass_function_ptr.exitcode: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /examples/methodCalls/recursion/recursion.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main() ~> int { 3 | 4 | return f(4); 5 | } 6 | 7 | fn f(int32 x) -> int32 { 8 | 9 | if (x <= 0) { 10 | return 9; 11 | } 12 | 13 | return f(x-1); 14 | } 15 | -------------------------------------------------------------------------------- /examples/methodCalls/recursion/recursion.exitcode: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /examples/octal/octal_notation.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local uint64 x; 5 | 6 | x = 0666; 7 | 8 | x -= 0600; 9 | 10 | return x; 11 | } 12 | -------------------------------------------------------------------------------- /examples/octal/octal_notation.exitcode: -------------------------------------------------------------------------------- 1 | 54 2 | -------------------------------------------------------------------------------- /examples/other/everything.dg: -------------------------------------------------------------------------------- 1 | //The goal of this example is to 2 | //contain all Statement c_types_util 3 | //and use as many features of smalldragon 4 | //as possible 5 | //so that transpiling it will 6 | //be useful to detect memory leaks with Valgrind 7 | 8 | /* 9 | //Statements 10 | [x] ForStmt 11 | [x] WhileStmt 12 | [x] BreakStmt 13 | [x] ReturnStmt 14 | [x] AssignStmt 15 | [x] IfStmt 16 | 17 | [x] Local Variable Type Inference 18 | */ 19 | 20 | fn main () ~> int { 21 | 22 | 23 | for i in 0 .. 1 { 24 | } 25 | 26 | a = 0; 27 | 28 | while a < 4 { 29 | 30 | a = a + 1; 31 | } 32 | 33 | sub1(); 34 | sub2(); 35 | 36 | return 0; 37 | } 38 | 39 | fn sub2 () -> int { 40 | 41 | int a = 3; 42 | 43 | if a == 4 { 44 | return 2; 45 | } 46 | 47 | return 3; 48 | } 49 | 50 | fn sub1 () -> int { 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /examples/pointer_type/address_of_deref/address_of_deref.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local int8 x; 5 | *int8 y = &x; 6 | 7 | *int8 z = &(*y); 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/pointer_type/address_of_deref/address_of_deref.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_assignment/deref_assignment.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | int8 x = 0; 5 | *int8 y = &x; 6 | 7 | *y = 36; 8 | 9 | return x; 10 | } 11 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_assignment/deref_assignment.exitcode: -------------------------------------------------------------------------------- 1 | 36 2 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_of_address/deref_of_address.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | uint8 x = 75; 5 | 6 | return *(&x); 7 | } 8 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_of_address/deref_of_address.exitcode: -------------------------------------------------------------------------------- 1 | 75 2 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_once/deref_pointer.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main() -> int { 3 | 4 | uint64 x = 33; 5 | 6 | *uint64 y = &x; 7 | 8 | //uint64 z = *y; 9 | 10 | //return z; 11 | return *y; 12 | } 13 | -------------------------------------------------------------------------------- /examples/pointer_type/deref_once/deref_pointer.exitcode: -------------------------------------------------------------------------------- 1 | 33 2 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function/pass_to_function.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f(*int8 ptr) -> int8 { 3 | 4 | return (*ptr + 9); 5 | } 6 | 7 | fn main () -> int { 8 | 9 | int8 x = 81; 10 | *int8 y = &x; 11 | 12 | return f(y); 13 | } 14 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function/pass_to_function.exitcode: -------------------------------------------------------------------------------- 1 | 90 2 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function_deref_assign/pass_to_function_deref_assign.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f(*int8 ptr) -> int { 3 | 4 | *ptr = 74; 5 | return 0; 6 | } 7 | 8 | fn main () -> int { 9 | 10 | int8 x = 0; 11 | f(&x); 12 | 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function_deref_assign/pass_to_function_deref_assign.exitcode: -------------------------------------------------------------------------------- 1 | 74 2 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function_twice/pass_to_function_twice.dg: -------------------------------------------------------------------------------- 1 | 2 | fn f(**int8 ptr) -> int8 { 3 | 4 | return (*(*ptr) + 7); 5 | } 6 | 7 | fn main () -> int { 8 | 9 | int8 x = 81; 10 | *int8 y = &x; 11 | **int8 z = &y; 12 | 13 | return f(z); 14 | } 15 | -------------------------------------------------------------------------------- /examples/pointer_type/pass_to_function_twice/pass_to_function_twice.exitcode: -------------------------------------------------------------------------------- 1 | 88 2 | -------------------------------------------------------------------------------- /examples/pointer_type/twice/deref_twice.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main() -> int { 3 | 4 | uint64 x = 83; 5 | 6 | *uint64 y = &x; 7 | 8 | **uint64 z = &(y); 9 | 10 | return *(*z); 11 | } 12 | -------------------------------------------------------------------------------- /examples/pointer_type/twice/deref_twice.exitcode: -------------------------------------------------------------------------------- 1 | 83 2 | -------------------------------------------------------------------------------- /examples/portb/Makefile: -------------------------------------------------------------------------------- 1 | main: compile 2 | 3 | compile: clean 4 | sd test_portb.dg ../../stdlib/avr/portb.dg 5 | 6 | flash: 7 | sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:test_portb.hex 8 | 9 | clean: 10 | rm -f *.hex *.obj *.cof *.asm *.png *.dot 11 | 12 | -------------------------------------------------------------------------------- /examples/portb/test_portb.dg: -------------------------------------------------------------------------------- 1 | //Program to make an LED glow 2 | 3 | //Arduino Board: 4 | //https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf 5 | 6 | /* Hardware Setup 7 | 8 | GND ----- LED ----- Resistor 9 | | 10 | D13 PIN -------------------| 11 | 12 | */ 13 | 14 | //LED_BUILTIN PB5 15 | //PB5 is on D13 on the Arduino 16 | 17 | fn main () ~> int { 18 | //set D13 / PB5 19 | 20 | //set PORTB Data Direction Register (DDRB) to enable DDRB5 21 | //[0x24] = 0b00100000; 22 | 23 | portb_ddrd(0xff); // set everything to output 24 | 25 | portb_write(0b00010000); 26 | portb_write(0b00100000); 27 | 28 | while(true){ 29 | 30 | } 31 | return 1; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/alloc_0_bytes/alloc_0_bytes.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local *uint8 ptr; 5 | 6 | ptr = malloc(0); 7 | 8 | if ptr != 0 { 9 | return 1; 10 | } 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/alloc_0_bytes/alloc_0_bytes.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/alloc_0_bytes/alloc_0_bytes.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/alloc_0_bytes/alloc_0_bytes.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/calloc_test/calloc_test.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | [uint64] p = calloc(100); 5 | 6 | if p == 0 { 7 | return 1; 8 | } 9 | 10 | println_uint64(p[10]); 11 | 12 | p[10] = 831212; 13 | 14 | println_uint64(p[10]); 15 | 16 | free(p); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/calloc_test/calloc_test.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/calloc_test/calloc_test.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/calloc_test/calloc_test.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/calloc_test/calloc_test.stdout: -------------------------------------------------------------------------------- 1 | 0 2 | 831212 3 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/loop_test/loop_test.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | // test that the allocations do not exhaus memory 5 | 6 | for i in 0 .. 10000 { 7 | 8 | *uint64 p = malloc(3000); 9 | 10 | if p == 0 { 11 | return 1; 12 | } 13 | 14 | if free(p) != 0 { 15 | return 1; 16 | } 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/loop_test/loop_test.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/loop_test/loop_test.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/loop_test/loop_test.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/memcpy_test/memcpy_test.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | [uint8] p1 = calloc(4); 5 | [uint8] p2 = calloc(4); 6 | 7 | if p1 == 0 { 8 | return 1; 9 | } 10 | if p2 == 0 { 11 | return 1; 12 | } 13 | 14 | p1[0] = 1; 15 | p1[1] = 2; 16 | p1[2] = 3; 17 | 18 | memcpy(p2, p1, 3); 19 | 20 | println_uint64(p2[0]); 21 | println_uint64(p2[1]); 22 | println_uint64(p2[2]); 23 | 24 | println_uint64(p2[3]); // 0 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/memcpy_test/memcpy_test.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/memcpy_test/memcpy_test.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/memcpy_test/memcpy_test.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/memcpy_test/memcpy_test.stdout: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 0 5 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/no_overlap/no_overlap.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | *uint64 ptr1 = malloc(30); 5 | *uint64 ptr2 = malloc(30); 6 | 7 | if ((ptr1 + 30) > ptr2 && (ptr1 <= ptr2)){ 8 | return 1; 9 | } 10 | 11 | if ((ptr2 + 30) > ptr1 && (ptr2 <= ptr1)){ 12 | return 1; 13 | } 14 | 15 | free(ptr1); 16 | free(ptr2); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/no_overlap/no_overlap.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/no_overlap/no_overlap.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/no_overlap/no_overlap.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/realloc_test/realloc_test.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | *uint8 p1 = malloc(PAGE_SIZE_COMMON); 5 | 6 | if p1 == 0 { 7 | return 1; 8 | } 9 | 10 | *p1 = 9; 11 | 12 | *uint8 p2 = realloc(p1, PAGE_SIZE_COMMON * 2); 13 | 14 | if p2 == 0 { 15 | return 2; 16 | } 17 | 18 | if *p2 != 9 { 19 | return 3; 20 | } 21 | 22 | if p1 == p2 { 23 | // it should not re-use that block, it is too small 24 | return 4; 25 | } 26 | 27 | *uint8 p3 = realloc(p2, PAGE_SIZE_COMMON); 28 | 29 | if p3 != p2 { 30 | // it should re-use the block, it is big enough 31 | return 5; 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/realloc_test/realloc_test.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/realloc_test/realloc_test.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/realloc_test/realloc_test.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/use_allocator/use_allocator.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | local *uint8 ptr; 5 | 6 | ptr = malloc(329); 7 | 8 | if ptr == 0 { 9 | return 2; 10 | } 11 | 12 | free(ptr); 13 | 14 | ptr = malloc(8349); 15 | 16 | if ptr == 0 { 17 | return 3; 18 | } 19 | 20 | local *uint8 p; 21 | p = ptr; 22 | 23 | p += 100; 24 | *p = 84; 25 | p += 10; 26 | *p = 92; 27 | p -= 10; 28 | 29 | uint8 res = *p; 30 | 31 | free(ptr); 32 | 33 | return res; 34 | } 35 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/use_allocator/use_allocator.exitcode: -------------------------------------------------------------------------------- 1 | 84 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/allocator/use_allocator/use_allocator.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/allocator/use_allocator/use_allocator.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/string/streq/test_streq.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | bool b1 = streq("hi", "hi"); 5 | 6 | if !b1 { 7 | return 1; 8 | } 9 | 10 | bool b2 = streq("str1", "hello"); 11 | 12 | if b2 { 13 | return 2; 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /examples/stdlib/base/string/streq/test_streq.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/string/streq/test_streq.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/string/streq/test_streq.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/string/strlen/test_strlen.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | 4 | [char] buf = "12345"; 5 | *char ptr = buf; 6 | 7 | return strlen(ptr); 8 | } 9 | -------------------------------------------------------------------------------- /examples/stdlib/base/string/strlen/test_strlen.exitcode: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /examples/stdlib/base/string/strlen/test_strlen.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/string/strlen/test_strlen.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/test_string.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | 4 | println_uint64(8329); 5 | 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /examples/stdlib/base/test_string.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/base/test_string.stdlib -------------------------------------------------------------------------------- /examples/stdlib/base/test_string.stdout: -------------------------------------------------------------------------------- 1 | 8329 2 | -------------------------------------------------------------------------------- /examples/stdlib/draw/svg/test_svg.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () -> int { 3 | uint64 n = 400; 4 | int fd = 1; 5 | 6 | svg_start(fd, n, n); 7 | 8 | svg_rect(fd, 100, 100, 10, 10); 9 | 10 | svg_line(fd, 10, 10, 200, 200); 11 | 12 | [char] buf = "textual"; 13 | *char ptr = buf; 14 | svg_text(fd, 30, 30, ptr); 15 | 16 | svg_end(fd); 17 | 18 | return 0; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/stdlib/draw/svg/test_svg.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/draw/svg/test_svg.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/draw/svg/test_svg.stdlib -------------------------------------------------------------------------------- /examples/stdlib/draw/svg/test_svg.stdout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | textual 5 | 6 | -------------------------------------------------------------------------------- /examples/stdlib/draw/testdraw.dg: -------------------------------------------------------------------------------- 1 | 2 | // Example program for drawing an image in PPM format 3 | // To convert it to png, imagemagick can be used 4 | // ./a.out > /tmp/test.ppm 5 | // magick /tmp/test.ppm /tmp/test.png 6 | 7 | fn main () -> int { 8 | 9 | uint64 n = 10; 10 | 11 | int fd = 1; 12 | 13 | ppm_create(fd, n, n, 15); 14 | 15 | uint8 red = 0; 16 | uint8 green = 0; 17 | 18 | for r in 0 .. n-1 { 19 | red = r % 15; 20 | for c in 0 .. n-1 { 21 | green = c % 15; 22 | ppm_pixel(fd, red, green, 2); 23 | } 24 | ppm_newline(fd); 25 | } 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /examples/stdlib/draw/testdraw.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/draw/testdraw.stdlib -------------------------------------------------------------------------------- /examples/stdlib/draw/testdraw.stdout: -------------------------------------------------------------------------------- 1 | P3 2 | 10 3 | 10 4 | 15 5 | 0 0 2 0 1 2 0 2 2 0 3 2 0 4 2 0 5 2 0 6 2 0 7 2 0 8 2 0 9 2 6 | 1 0 2 1 1 2 1 2 2 1 3 2 1 4 2 1 5 2 1 6 2 1 7 2 1 8 2 1 9 2 7 | 2 0 2 2 1 2 2 2 2 2 3 2 2 4 2 2 5 2 2 6 2 2 7 2 2 8 2 2 9 2 8 | 3 0 2 3 1 2 3 2 2 3 3 2 3 4 2 3 5 2 3 6 2 3 7 2 3 8 2 3 9 2 9 | 4 0 2 4 1 2 4 2 2 4 3 2 4 4 2 4 5 2 4 6 2 4 7 2 4 8 2 4 9 2 10 | 5 0 2 5 1 2 5 2 2 5 3 2 5 4 2 5 5 2 5 6 2 5 7 2 5 8 2 5 9 2 11 | 6 0 2 6 1 2 6 2 2 6 3 2 6 4 2 6 5 2 6 6 2 6 7 2 6 8 2 6 9 2 12 | 7 0 2 7 1 2 7 2 2 7 3 2 7 4 2 7 5 2 7 6 2 7 7 2 7 8 2 7 9 2 13 | 8 0 2 8 1 2 8 2 2 8 3 2 8 4 2 8 5 2 8 6 2 8 7 2 8 8 2 8 9 2 14 | 9 0 2 9 1 2 9 2 2 9 3 2 9 4 2 9 5 2 9 6 2 9 7 2 9 8 2 9 9 2 15 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/exit/exit.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main() ~> int { 3 | 4 | exit(84); 5 | 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/exit/exit.exitcode: -------------------------------------------------------------------------------- 1 | 84 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/exit/exit.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/exit/exit.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/mmap/use_mmap.dg: -------------------------------------------------------------------------------- 1 | fn main () -> int { 2 | 3 | local *uint8 ptr; 4 | ptr = mmap(0, PAGE_SIZE_COMMON, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); 5 | 6 | uint64 value = ptr; 7 | 8 | local *char msg; 9 | if value == MAP_FAILED { 10 | msg = "map failed\n"; 11 | write(1, msg, 11); 12 | } else { 13 | msg = "map success\n"; 14 | write(1, msg, 12); 15 | } 16 | 17 | ptr += 4; 18 | 19 | *ptr = 89; 20 | 21 | local uint8 x; 22 | x = *ptr; 23 | 24 | munmap(ptr - 4, PAGE_SIZE_COMMON); 25 | 26 | return x ; 27 | } 28 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/mmap/use_mmap.exitcode: -------------------------------------------------------------------------------- 1 | 89 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/mmap/use_mmap.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/mmap/use_mmap.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/read_file/read_file.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | 3 | // since this is run as part of tests, 4 | // the path needs to be relative from examples/ 5 | [char] filename = "stdlib/syscalls/read_file/read_file.dg"; 6 | *char path = filename; 7 | int fd = open(path, 0, 1); 8 | 9 | if fd < 0 { 10 | return 1; 11 | } 12 | 13 | char c = ' '; 14 | *char ptr = &c; 15 | 16 | read(fd, ptr, 1); 17 | write(1, &c, 1); 18 | read(fd, ptr, 1); 19 | write(1, &c, 1); 20 | read(fd, ptr, 1); 21 | write(1, &c, 1); 22 | read(fd, ptr, 1); 23 | write(1, &c, 1); 24 | read(fd, ptr, 1); 25 | write(1, &c, 1); 26 | read(fd, ptr, 1); 27 | write(1, &c, 1); 28 | read(fd, ptr, 1); 29 | write(1, &c, 1); 30 | 31 | c = '\n'; 32 | write(1, &c, 1); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/read_file/read_file.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/read_file/read_file.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/read_file/read_file.stdout: -------------------------------------------------------------------------------- 1 | fn main 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write/write_stdout.dg: -------------------------------------------------------------------------------- 1 | 2 | 3 | fn main () ~> int { 4 | 5 | local char c; 6 | local *char ptr; 7 | *char ptr = &c; 8 | 9 | c = 'x'; 10 | write(1, ptr, 1); 11 | 12 | c = '\n'; 13 | write(1, ptr, 1); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write/write_stdout.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write/write_stdout.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/write/write_stdout.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write/write_stdout.stdout: -------------------------------------------------------------------------------- 1 | x 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_file/write_file.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | 3 | [char] filename = "/tmp/write_file.txt"; 4 | *char path = filename; 5 | int fd = open(path, O_RDWR | O_CREAT, 0666); 6 | 7 | if fd < 0 { 8 | return 1; 9 | } 10 | 11 | [char] buf = "hello,file\n"; 12 | *char ptr = buf; 13 | 14 | int written = write(fd, ptr, strlen(ptr)); 15 | 16 | if (written < 11){ 17 | return written; 18 | } 19 | 20 | if (close(fd) < 0){ 21 | return 2; 22 | } 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_file/write_file.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_file/write_file.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/write_file/write_file.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_string/write_string.dg: -------------------------------------------------------------------------------- 1 | fn main () ~> int { 2 | 3 | write(1, "Hello, ", 7); 4 | 5 | write(1, "World!\n", 7); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_string/write_string.exitcode: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_string/write_string.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/stdlib/syscalls/write_string/write_string.stdlib -------------------------------------------------------------------------------- /examples/stdlib/syscalls/write_string/write_string.stdout: -------------------------------------------------------------------------------- 1 | Hello, World! 2 | -------------------------------------------------------------------------------- /examples/struct/nested/nested.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Astruct { 3 | uint8 x; 4 | Bstruct b; 5 | } 6 | 7 | struct Bstruct { 8 | uint8 y; 9 | } 10 | 11 | fn main () ~> int { 12 | 13 | local Astruct m; 14 | 15 | m.b.y = 3; 16 | 17 | return m.b.y + 3; 18 | } 19 | -------------------------------------------------------------------------------- /examples/struct/nested/nested.exitcode: -------------------------------------------------------------------------------- 1 | 6 2 | -------------------------------------------------------------------------------- /examples/struct/struct_and_array/struct_and_array.dg: -------------------------------------------------------------------------------- 1 | // testing the common use-case of a container struct 2 | // for an array of structs 3 | 4 | struct Container { 5 | 6 | uint64 count; 7 | uint64 capacity; 8 | 9 | [*Line] lines; 10 | } 11 | 12 | struct Line { 13 | uint64 a; 14 | uint64 b; 15 | uint64 c; 16 | } 17 | 18 | fn main () -> int { 19 | 20 | *Container c = malloc(100); 21 | 22 | if c == 0 { 23 | return 1; 24 | } 25 | 26 | c.count = 1; 27 | c.capacity = 3; 28 | c.lines = calloc(c.capacity * 8); 29 | 30 | if c.lines == 0 { 31 | return 2; 32 | } 33 | 34 | *Line line = calloc(16); 35 | line.a = 403; 36 | line.b = 73; 37 | 38 | c.lines[c.count] = line; 39 | 40 | *Line line2 = c.lines[c.count]; 41 | 42 | return line2.b; 43 | } 44 | -------------------------------------------------------------------------------- /examples/struct/struct_and_array/struct_and_array.exitcode: -------------------------------------------------------------------------------- 1 | 73 2 | -------------------------------------------------------------------------------- /examples/struct/struct_and_array/struct_and_array.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/struct/struct_and_array/struct_and_array.stdlib -------------------------------------------------------------------------------- /examples/struct/struct_on_heap/struct_on_heap.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Astruct { 3 | 4 | uint64 count_members; 5 | uint64 capacity_members; 6 | [uint8] members; 7 | } 8 | 9 | fn main () -> int { 10 | 11 | *Astruct ptr = malloc(100); 12 | 13 | if ptr == 0 { 14 | fprint(STDERR, "malloc failure\n"); 15 | return 1; 16 | } 17 | 18 | uint64 x1 = ptr; 19 | 20 | ptr.count_members = 43; 21 | 22 | uint64 x2 = ptr; 23 | 24 | println_uint64(x1-x2); 25 | 26 | return ptr.count_members; 27 | } 28 | -------------------------------------------------------------------------------- /examples/struct/struct_on_heap/struct_on_heap.exitcode: -------------------------------------------------------------------------------- 1 | 43 2 | -------------------------------------------------------------------------------- /examples/struct/struct_on_heap/struct_on_heap.stdlib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pointbazaar/espl1000/28434271b969531f24d439d88c78ba0410dce370/examples/struct/struct_on_heap/struct_on_heap.stdlib -------------------------------------------------------------------------------- /examples/struct/struct_on_heap/struct_on_heap.stdout: -------------------------------------------------------------------------------- 1 | 0 2 | -------------------------------------------------------------------------------- /examples/struct/struct_on_stack/one_member.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Point { 3 | uint8 x; 4 | uint8 y; 5 | uint8 z; 6 | } 7 | 8 | fn main ()-> int { 9 | local Point a; 10 | a.y = 22; 11 | return a.y; 12 | } 13 | -------------------------------------------------------------------------------- /examples/struct/struct_on_stack/one_member.exitcode: -------------------------------------------------------------------------------- 1 | 22 2 | -------------------------------------------------------------------------------- /examples/struct/struct_on_stack/two_member.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Point { 3 | uint8 x; 4 | uint8 y; 5 | uint8 z; 6 | } 7 | 8 | fn main ()-> int { 9 | local Point a; 10 | a.x = 22; 11 | a.z = 9; 12 | 13 | return a.x + a.z; 14 | } 15 | -------------------------------------------------------------------------------- /examples/struct/struct_on_stack/two_member.exitcode: -------------------------------------------------------------------------------- 1 | 31 2 | -------------------------------------------------------------------------------- /examples/struct/very_nested/very_nested.dg: -------------------------------------------------------------------------------- 1 | 2 | struct As { 3 | uint8 x; 4 | Bs b; 5 | } 6 | 7 | struct Bs { 8 | Cs c; 9 | uint8 y; 10 | } 11 | 12 | struct Cs { 13 | uint16 z1; 14 | uint16 z2; 15 | uint16 z3; 16 | uint16 z4; 17 | } 18 | 19 | fn main () ~> int { 20 | 21 | local As a; 22 | 23 | a.b.y = 33; 24 | 25 | a.b.c.z1 = 0; 26 | a.b.c.z2 = 0; 27 | a.b.c.z3 = 9; 28 | a.b.c.z4 = 0; 29 | 30 | a.x = 1; 31 | 32 | return a.b.y + a.b.c.z3; 33 | } 34 | -------------------------------------------------------------------------------- /examples/struct/very_nested/very_nested.exitcode: -------------------------------------------------------------------------------- 1 | 42 2 | -------------------------------------------------------------------------------- /examples/tc_err.dg: -------------------------------------------------------------------------------- 1 | //this example should showcase 2 | //the various typechecking errors 3 | //that smalldragon can detect. 4 | 5 | //the goal is to trigger each type of 6 | //error once. 7 | 8 | fn main () -> int { 9 | 10 | int f = 1; 11 | 12 | subr(3,0); 13 | 14 | subr('h'); 15 | 16 | for i in 'h' .. 4 { } 17 | 18 | if 3+6 { } 19 | 20 | switch "hello" { 21 | 22 | case 3 {} 23 | } 24 | 25 | loop 'h' { } 26 | 27 | return 0; 28 | } 29 | 30 | fn subr(int k) -> int { 31 | 32 | return "hi"; 33 | } 34 | -------------------------------------------------------------------------------- /examples/typeinference/localvartypeinference.dg: -------------------------------------------------------------------------------- 1 | 2 | fn main () ~> int { 3 | 4 | 5 | a12 = 3; 6 | 7 | b = a12 + 4 + subr(); 8 | subr(); 9 | 10 | return 0; 11 | } 12 | 13 | fn subr() -> int { 14 | return 3; 15 | } 16 | -------------------------------------------------------------------------------- /examples/usart/Makefile: -------------------------------------------------------------------------------- 1 | main: compile 2 | 3 | compile: clean 4 | sd \ 5 | main.dg \ 6 | ../../stdlib/avr/timer0.dg \ 7 | ../../stdlib/avr/usart.dg 8 | 9 | flash: 10 | sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:main.hex 11 | 12 | clean: 13 | rm -f *.hex *.obj *.cof *.asm *.png *.dot 14 | 15 | -------------------------------------------------------------------------------- /format-code.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | 5 | SCRIPT_DIR=$(realpath "$(dirname "$0")") 6 | 7 | echo "running from" "$SCRIPT_DIR" 8 | 9 | SRC=$(find "$SCRIPT_DIR" -type d \( -name 'build' -o -name 'dependencies' -o -name 'stdlib' -o -name 'examples' \) -prune -o \( -name '*.c' -o -name '*.h' \) -print) 10 | 11 | echo "$SRC" 12 | 13 | # shellcheck disable=SC2086 14 | clang-format -i --style='file:.clang-format' $SRC 15 | -------------------------------------------------------------------------------- /ibuffer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-ibuffer" STATIC 3 | ibuffer.c 4 | ibuffer_write.c 5 | mnem.c 6 | ) 7 | 8 | #Util dependency 9 | target_link_libraries("sd-ibuffer" sd-util) 10 | -------------------------------------------------------------------------------- /ibuffer/ibuffer_write.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include "ikey.h" 8 | 9 | void ibu_write_instr(enum IKEY key, int32_t x1, int32_t x2, int32_t x3, char* str, char* comment, FILE* fout); 10 | -------------------------------------------------------------------------------- /lexer/.gitignore: -------------------------------------------------------------------------------- 1 | lexer 2 | dragon-lexer 3 | 4 | lex.yy.c 5 | lex.yy.h 6 | 7 | build/* 8 | -------------------------------------------------------------------------------- /lexer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(src) 2 | add_subdirectory(test) 3 | -------------------------------------------------------------------------------- /lexer/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(lexer-lib 3 | 4 | driver.h 5 | driver.c 6 | lexer_main.c 7 | lexer.c 8 | ) 9 | 10 | target_include_directories(lexer-lib PUBLIC "../../") 11 | -------------------------------------------------------------------------------- /lexer/src/driver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "token/list/TokenList.h" 7 | 8 | void out_nostr(struct TokenList* list, int id); 9 | void out(struct TokenList* list, int id, char* str); 10 | void out_length(struct TokenList* list, int id, char* str, int length); 11 | 12 | void out_plus_plus(struct TokenList* list); 13 | void out_minus_minus(struct TokenList* list); 14 | 15 | // @returns NULL on error 16 | struct LexerFlags* handle_arguments(int argc, char** argv); 17 | 18 | char* lexer_make_tkn_filename(char* filename); 19 | -------------------------------------------------------------------------------- /lexer/src/lexer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "token/list/TokenList.h" 6 | 7 | //TODO: get rid of this global 8 | extern uint32_t line_no; 9 | 10 | // @returns NULL on error 11 | struct TokenList* lexer_impl(FILE* infile); 12 | -------------------------------------------------------------------------------- /lexer/src/lexer_flags.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct LexerFlags { 6 | 7 | char* filename; 8 | bool write_token_file; 9 | bool debug; 10 | }; 11 | -------------------------------------------------------------------------------- /lexer/src/lexer_main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct LexerFlags; 4 | 5 | #include "token/list/TokenList.h" 6 | 7 | // @returns NULL on error 8 | struct TokenList* lexer_main(struct LexerFlags* flags); 9 | -------------------------------------------------------------------------------- /lexer/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(sd-lexer-test 3 | lexer_test_utils.c 4 | test.c 5 | 6 | testcases/tests_operators.c 7 | testcases/tests_mixed.c 8 | testcases/tests_keywords.c 9 | testcases/tests_const.c 10 | testcases/tests_comments.c 11 | testcases/tests_other.c 12 | ) 13 | 14 | target_link_libraries(sd-lexer-test lexer-lib) 15 | 16 | target_include_directories(sd-lexer-test PUBLIC "../..") 17 | 18 | target_link_libraries(sd-lexer-test sd-token) 19 | 20 | target_link_libraries(sd-lexer-test sd-util) 21 | -------------------------------------------------------------------------------- /lexer/test/lexer_test_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // @returns NULL on error 4 | // @param[out][count] count of tokens read 5 | #include 6 | struct Token** lex(char* source, size_t* out_count); 7 | 8 | void free_tokens(struct Token** tokens, unsigned int count); 9 | 10 | void assert_eq(char* actual, char* expected); 11 | -------------------------------------------------------------------------------- /lexer/test/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "test.h" 8 | #include "../../token/token/token.h" 9 | #include "../../token/TokenKeys.h" 10 | #include "lexer_test_utils.h" 11 | 12 | #include "util/status/status.h" 13 | 14 | void printt(char* test_name) { 15 | status(test_name); 16 | } 17 | -------------------------------------------------------------------------------- /lexer/test/testcases/tests_comments.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../test.h" 6 | #include "../token/token/token.h" 7 | #include "../token/TokenKeys.h" 8 | #include "../lexer_test_utils.h" 9 | 10 | void test_single_line_comment() { 11 | 12 | printt("single line comment"); 13 | 14 | char* str = "x1 //hello there \n x2 "; 15 | size_t count = 0; 16 | struct Token** tokens = lex(str, &count); 17 | 18 | assert(tokens[0]->kind == ID); 19 | assert(tokens[1]->kind == ID); 20 | 21 | assert(strcmp(tokens[0]->value_ptr, "x1") == 0); 22 | assert(strcmp(tokens[1]->value_ptr, "x2") == 0); 23 | 24 | free_tokens(tokens, 2); 25 | } 26 | 27 | void test_multi_line_comment() { 28 | 29 | printt("multi line comment"); 30 | 31 | char* str = "x1 /*hello //there \n now*/ x2 "; 32 | size_t count = 0; 33 | struct Token** tokens = lex(str, &count); 34 | 35 | assert(tokens[0]->kind == ID); 36 | assert(tokens[1]->kind == ID); 37 | 38 | assert(strcmp(tokens[0]->value_ptr, "x1") == 0); 39 | assert(strcmp(tokens[1]->value_ptr, "x2") == 0); 40 | 41 | free_tokens(tokens, 2); 42 | } 43 | -------------------------------------------------------------------------------- /parser/.gitignore: -------------------------------------------------------------------------------- 1 | dragon-parser 2 | 3 | -------------------------------------------------------------------------------- /parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_subdirectory(main) 3 | add_subdirectory(test) 4 | -------------------------------------------------------------------------------- /parser/main/astnodes/EnumDecl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct EnumDecl; 5 | 6 | struct EnumDecl* makeEnumDecl(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/EnumMember.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct EnumMember; 5 | 6 | struct EnumMember* makeEnumMember(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/Identifier.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Identifier.h" 8 | 9 | #include "ast/util/free_ast.h" 10 | 11 | #include "token/list/TokenList.h" 12 | #include "token/TokenKeys.h" 13 | #include "token/token/token.h" 14 | 15 | struct Id* makeIdentifier(struct TokenList* tokens) { 16 | 17 | if (list_size(tokens) == 0) { return NULL; } 18 | 19 | struct Id* res = make(Id); 20 | 21 | struct Token* tk = list_head(tokens); 22 | 23 | res->super.line_num = tk->line_num; 24 | res->super.annotations = 0; 25 | 26 | if (tk->kind == ID) { 27 | asprintf(&(res->identifier), "%s", tk->value_ptr); 28 | list_consume(tokens, 1); 29 | } else { 30 | free(res); 31 | return NULL; 32 | } 33 | 34 | return res; 35 | } 36 | -------------------------------------------------------------------------------- /parser/main/astnodes/Identifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct Id; 6 | struct TokenList; 7 | 8 | struct Id* makeIdentifier(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/Namespace.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct Namespace; 5 | 6 | struct Namespace* makeNamespace(struct TokenList* tokens, char* name); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/Range.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct Range; 5 | 6 | struct Range* makeRange(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/StmtBlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct StmtBlock; 7 | 8 | struct StmtBlock* makeStmtBlock(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/const/ConstValue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct ConstValue; 6 | struct TokenList; 7 | 8 | struct ConstValue* makeConstValue(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/const/IntConst.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct TokenList; 7 | 8 | int32_t makeIntConst(struct TokenList* tokens, bool* error); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/const/StringConst.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "StringConst.h" 5 | 6 | #include "ast/util/free_ast.h" 7 | 8 | #include "token/list/TokenList.h" 9 | #include "token/TokenKeys.h" 10 | #include "token/token/token.h" 11 | 12 | struct StringConst* makeStringConst(struct TokenList* tokens) { 13 | 14 | if (list_size(tokens) == 0) { return NULL; } 15 | 16 | struct StringConst* res = make(StringConst); 17 | 18 | struct Token* tk = list_head(tokens); 19 | 20 | res->super.line_num = tk->line_num; 21 | res->super.annotations = 0; 22 | 23 | if (tk->kind == STRINGCONST) { 24 | res->value = malloc(sizeof(char) * (strlen(tk->value_ptr) + 1)); 25 | 26 | if (!res->value) { 27 | free(res); 28 | return NULL; 29 | } 30 | 31 | strcpy(res->value, tk->value_ptr); 32 | 33 | list_consume(tokens, 1); 34 | } else { 35 | free(res); 36 | return NULL; 37 | } 38 | 39 | return res; 40 | } 41 | -------------------------------------------------------------------------------- /parser/main/astnodes/const/StringConst.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct StringConst; 5 | 6 | // @returns NULL on error 7 | struct StringConst* makeStringConst(struct TokenList* tokens); 8 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/AddressOf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "parser/main/util/parse_astnode.h" 5 | 6 | #include "Deref.h" 7 | #include "Term.h" 8 | 9 | #include "ast/ast.h" 10 | 11 | #include "token/list/TokenList.h" 12 | #include "token/TokenKeys.h" 13 | 14 | struct AddressOf* makeAddresOf(struct Term* term) { 15 | 16 | struct AddressOf* res = make(AddressOf); 17 | 18 | res->super.line_num = term->super.line_num; 19 | res->super.annotations = 0; 20 | 21 | res->term = term; 22 | 23 | return res; 24 | } 25 | 26 | struct AddressOf* makeAddressOf2(struct TokenList* tokens) { 27 | 28 | struct AddressOf* res = make(AddressOf); 29 | struct TokenList* copy = list_copy(tokens); 30 | 31 | parse_astnode(copy, &(res->super)); 32 | 33 | if (!list_expect(copy, OPKEY_BITWISE_AND)) { 34 | goto error; 35 | } 36 | 37 | res->term = makeTerm(copy); 38 | if (res->term == NULL) { 39 | goto error; 40 | } 41 | 42 | list_set(tokens, copy); 43 | freeTokenListShallow(copy); 44 | 45 | return res; 46 | 47 | error: 48 | freeTokenListShallow(copy); 49 | free(res); 50 | return NULL; 51 | } 52 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/AddressOf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct AddressOf; 7 | struct Term; 8 | 9 | struct AddressOf* makeAddresOf(struct Term* term); 10 | struct AddressOf* makeAddressOf2(struct TokenList* tokens); 11 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/Deref.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "parser/main/util/parse_astnode.h" 5 | 6 | #include "Deref.h" 7 | #include "Term.h" 8 | 9 | #include "ast/ast.h" 10 | 11 | #include "token/list/TokenList.h" 12 | #include "token/TokenKeys.h" 13 | 14 | struct Deref* makeDeref(struct Term* term) { 15 | 16 | struct Deref* res = make(Deref); 17 | 18 | res->super.line_num = term->super.line_num; 19 | res->super.annotations = 0; 20 | 21 | res->term = term; 22 | 23 | return res; 24 | } 25 | 26 | struct Deref* makeDeref2(struct TokenList* tokens) { 27 | 28 | struct Deref* res = make(Deref); 29 | struct TokenList* copy = list_copy(tokens); 30 | 31 | parse_astnode(copy, &(res->super)); 32 | 33 | if (!list_expect(copy, OPKEY_ARITHMETIC_MUL)) { 34 | goto error; 35 | } 36 | 37 | res->term = makeTerm(copy); 38 | if (res->term == NULL) { 39 | goto error; 40 | } 41 | 42 | list_set(tokens, copy); 43 | freeTokenListShallow(copy); 44 | 45 | return res; 46 | 47 | error: 48 | freeTokenListShallow(copy); 49 | free(res); 50 | return NULL; 51 | } 52 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/Deref.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Deref; 7 | struct Term; 8 | 9 | struct Deref* makeDeref(struct Term* term); 10 | struct Deref* makeDeref2(struct TokenList* tokens); 11 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/Expr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ast/ast.h" 7 | 8 | struct TokenList; 9 | 10 | //an expression should be anything that returns a value or computes to a value 11 | 12 | struct Expr* makeExpr(struct TokenList* tokens); 13 | struct Expr* makeExpr_1(struct UnOpTerm* myterm); 14 | struct Expr* makeExpr_3(struct UnOpTerm* leftTerm, enum OP op, struct UnOpTerm* rightTerm); 15 | 16 | int find(void** arr, int size, void* element); 17 | 18 | int prec_index(enum OP op); 19 | 20 | void** insert(void** arr, int index, void* element, int size_before); 21 | 22 | void** erase(void** arr, int index, int size_before); 23 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/LValue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct LValue; 7 | struct Term; 8 | struct Variable; 9 | 10 | struct LValue* makeLValue(struct Variable* var); 11 | struct LValue* makeLValue2(struct TokenList* tokens); 12 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/Op.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | enum OP; 5 | 6 | enum OP makeOp(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/Term.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct Term; 5 | struct Expr; 6 | 7 | struct Term* makeTerm_other(struct Expr* myexpr); 8 | struct Term* makeTerm(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/expr/UnOpTerm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct UnOpTerm; 7 | 8 | struct UnOpTerm* makeUnOpTerm(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/AssignStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct AssignStmt; 7 | 8 | struct AssignStmt* makeAssignStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/Call.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Call; 7 | 8 | struct Call* makeCall(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/ForStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct ForStmt; 7 | 8 | struct ForStmt* makeForStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/IfStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct IfStmt; 7 | 8 | struct IfStmt* makeIfStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/LocalVarDeclStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct LocalVarDeclStmt; 7 | 8 | struct LocalVarDeclStmt* makeLocalVarDeclStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/RetStmt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "parser/main/util/parse_astnode.h" 5 | 6 | #include "RetStmt.h" 7 | #include "expr/Expr.h" 8 | 9 | #include "token/list/TokenList.h" 10 | #include "token/TokenKeys.h" 11 | #include "token/token/token.h" 12 | 13 | struct RetStmt* makeRetStmt(struct TokenList* tokens) { 14 | 15 | struct RetStmt* res = make(RetStmt); 16 | struct TokenList* copy = list_copy(tokens); 17 | 18 | parse_astnode(copy, &(res->super)); 19 | 20 | if (!list_expect(copy, RETURN)) { 21 | free(res); 22 | return NULL; 23 | } 24 | 25 | res->return_value = makeExpr(copy); 26 | if (res->return_value == NULL) { 27 | free(res); 28 | return NULL; 29 | } 30 | 31 | if (!list_expect(copy, SEMICOLON)) { 32 | free(res); 33 | return NULL; 34 | } 35 | 36 | list_set(tokens, copy); 37 | freeTokenListShallow(copy); 38 | 39 | return res; 40 | } 41 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/RetStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct RetStmt; 7 | 8 | struct RetStmt* makeRetStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/Stmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Stmt; 7 | 8 | struct Stmt* makeStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/statements/WhileStmt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct WhileStmt; 7 | 8 | struct WhileStmt* makeWhileStmt(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/struct/StructDecl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct StructDecl; 5 | 6 | struct StructDecl* makeStructDecl(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/struct/StructMember.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct StructMember; 5 | 6 | struct StructMember* makeStructMember(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/subr/DeclArg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct DeclArg; 6 | struct TokenList; 7 | 8 | struct DeclArg* makeDeclArg(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/subr/Method.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Method; 7 | 8 | struct Method* makeMethod(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/subr/MethodDecl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct MethodDecl; 4 | struct TokenList; 5 | 6 | struct MethodDecl* makeMethodDecl(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/ArrayType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Type; 7 | struct ArrayType; 8 | 9 | struct ArrayType* makeArrayType(struct Type* element_type); 10 | struct ArrayType* makeArrayType2(struct TokenList* tokens); 11 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/BasicType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct BasicType; 7 | struct SimpleType; 8 | struct SubrType; 9 | 10 | struct BasicType* makeBasicTypeSimple(struct SimpleType* typeNode); 11 | struct BasicType* makeBasicTypeSubr(struct SubrType* typeNode); 12 | struct BasicType* makeBasicType2(struct TokenList* tokens); 13 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/PointerType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Type; 7 | struct PointerType; 8 | 9 | struct PointerType* makePointerType(struct Type* element_type); 10 | struct PointerType* makePointerType2(struct TokenList* tokens); 11 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/PrimitiveType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct PrimitiveType; 7 | 8 | struct PrimitiveType* makePrimitiveType(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/SimpleType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct SimpleType; 7 | 8 | struct SimpleType* makeSimpleType(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/StructType.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "parser/main/util/parse_astnode.h" 8 | 9 | #include "StructType.h" 10 | #include "Type.h" 11 | 12 | #include "ast/ast.h" 13 | 14 | #include "token/list/TokenList.h" 15 | #include "token/TokenKeys.h" 16 | #include "token/token/token.h" 17 | 18 | struct StructType* makeStructType(struct TokenList* tokens) { 19 | 20 | struct StructType* res = make(StructType); 21 | struct TokenList* copy = list_copy(tokens); 22 | 23 | parse_astnode(copy, &(res->super)); 24 | 25 | struct Token* next = list_head(copy); 26 | 27 | if (next->kind != TYPEID && next->kind != ANYTYPE) { 28 | 29 | fprintf(stderr, "[Parser][Error] Could not parse StructType\n"); 30 | return NULL; 31 | } 32 | 33 | asprintf(&(res->type_name), "%s", next->value_ptr); 34 | 35 | list_consume(copy, 1); 36 | 37 | list_set(tokens, copy); 38 | freeTokenListShallow(copy); 39 | 40 | return res; 41 | } 42 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/StructType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct StructType; 7 | 8 | // @returns NULL on error 9 | struct StructType* makeStructType(struct TokenList* tokens); 10 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/SubrType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Type; 7 | struct SubrType; 8 | 9 | struct SubrType* makeSubrType(struct TokenList* tokens); 10 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/Type.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "ast/ast_declare.h" 6 | 7 | struct TokenList; 8 | 9 | struct Type* makeType2(struct TokenList* tokens); 10 | struct Type* makeType_1(struct BasicType* typeNode); 11 | struct Type* makeType_2(struct TypeParam* typeNode); 12 | struct Type* makeType_3(struct ArrayType* typeNode); 13 | struct Type* makeType_4(struct SimpleType* typeNode); 14 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/TypeParam.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "parser/main/util/parse_astnode.h" 7 | 8 | #include "TypeParam.h" 9 | 10 | #include "ast/ast.h" 11 | 12 | #include "token/list/TokenList.h" 13 | #include "token/TokenKeys.h" 14 | #include "token/token/token.h" 15 | 16 | struct TypeParam* makeTypeParam(struct TokenList* tokens) { 17 | 18 | if (list_size(tokens) == 0) { return NULL; } 19 | 20 | struct TypeParam* res = make(TypeParam); 21 | struct TokenList* copy = list_copy(tokens); 22 | 23 | parse_astnode(copy, &(res->super)); 24 | 25 | struct Token* token = list_head(copy); 26 | 27 | if (token->kind != TPARAM) { 28 | //Error: could not read type parameter node 29 | freeTokenListShallow(copy); 30 | free(res); 31 | return NULL; 32 | } 33 | 34 | res->index = atoi(token->value_ptr); 35 | 36 | list_consume(copy, 1); 37 | 38 | list_set(tokens, copy); 39 | freeTokenListShallow(copy); 40 | 41 | return res; 42 | } 43 | -------------------------------------------------------------------------------- /parser/main/astnodes/types/TypeParam.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct TypeParam; 7 | 8 | struct TypeParam* makeTypeParam(struct TokenList* tokens); 9 | -------------------------------------------------------------------------------- /parser/main/astnodes/var/SimpleVar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct SimpleVar; 5 | 6 | struct SimpleVar* makeSimpleVar(struct TokenList* tokens); 7 | -------------------------------------------------------------------------------- /parser/main/astnodes/var/Variable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct TokenList; 6 | struct Variable; 7 | 8 | // @returns NULL on error 9 | struct Variable* makeVariable(struct TokenList* tokens); 10 | -------------------------------------------------------------------------------- /parser/main/util/parse_astnode.c: -------------------------------------------------------------------------------- 1 | #include "ast/ast_declare.h" 2 | 3 | #include "parse_astnode.h" 4 | 5 | #include "token/list/TokenList.h" 6 | #include "token/TokenKeys.h" 7 | #include "token/token/token.h" 8 | 9 | void parse_astnode(struct TokenList* tknList, struct ASTNode* node) { 10 | 11 | node->line_num = list_head(tknList)->line_num; 12 | node->annotations = 0; 13 | 14 | struct Token* tk = list_head(tknList); 15 | 16 | while ( 17 | list_size(tknList) > 1 && tk->kind > _ANNOT_START_ && tk->kind < _ANNOT_END_) { 18 | node->annotations |= 1 << (tk->kind - _ANNOT_START_); 19 | 20 | list_consume(tknList, 1); 21 | tk = list_head(tknList); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /parser/main/util/parse_astnode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct TokenList; 4 | struct ASTNode; 5 | 6 | void parse_astnode(struct TokenList* tknList, struct ASTNode* node); 7 | -------------------------------------------------------------------------------- /parser/main/util/parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "token/list/TokenList.h" 4 | 5 | struct AST* build_ast(struct TokenList* list, char* filename_display); 6 | struct Namespace* build_namespace(struct TokenList* list, char* filename_display); 7 | -------------------------------------------------------------------------------- /parser/spec/thought_about_grammar.txt: -------------------------------------------------------------------------------- 1 | Recently thought about subroutine type signatures and 2 | how subroutines are declared. 3 | 4 | //this currently looks the best to me 5 | //because it seperates the implementation, 6 | //the types, and the interesting properties we also want to track. 7 | //These 'concepts' exist in their own world, but are connected by the name of the subroutine. 8 | //They are also connected by being close together. 9 | //To be clear, the order of them in source code would be fixed as shown. 10 | 11 | subr :: @{terminates, public} 12 | subr :: (uint a, uint b) -> uint 13 | subr :: { 14 | return a+b; 15 | } 16 | -------------------------------------------------------------------------------- /parser/test/astnodes/NamespaceTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int namespace_test_can_parse_namespace_with_1_empty_struct(); 6 | int namespace_test_can_parse_namespace_with_1_empty_method(); 7 | -------------------------------------------------------------------------------- /parser/test/astnodes/RangeTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "RangeTest.h" 7 | 8 | #include "Range.h" 9 | 10 | #include "token/list/TokenList.h" 11 | #include "token/TokenKeys.h" 12 | #include "token/token/token.h" 13 | 14 | #include "ast/util/free_ast.h" 15 | 16 | void range_test1() { 17 | 18 | status_test("range_test1"); 19 | 20 | struct TokenList* list = makeTokenList(); 21 | 22 | list_add(list, makeToken2(ID, "a")); 23 | 24 | list_add(list, makeToken2(RANGEOP, "..")); 25 | 26 | list_add(list, makeToken2(INTEGER, "0")); 27 | 28 | list_add(list, makeToken(SEMICOLON)); 29 | 30 | struct Range* r = makeRange(list); 31 | 32 | assert(r != NULL); 33 | assert(r->start != NULL); 34 | assert(r->end != NULL); 35 | 36 | freeTokenList(list); 37 | free_range(r); 38 | } 39 | -------------------------------------------------------------------------------- /parser/test/astnodes/RangeTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void range_test1(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/StmtBlockTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "StmtBlockTest.h" 7 | 8 | #include "statements/Stmt.h" 9 | #include "StmtBlock.h" 10 | 11 | #include "token/list/TokenList.h" 12 | #include "token/TokenKeys.h" 13 | #include "token/token/token.h" 14 | 15 | #include "ast/util/free_ast.h" 16 | 17 | int test_stmtblock_1() { 18 | 19 | status_test("test_stmtblock_1"); 20 | 21 | struct TokenList* tokens = makeTokenList(); 22 | list_add(tokens, makeToken2(LCURLY, "{")); 23 | 24 | list_add(tokens, makeToken2(ID, "a")); 25 | list_add(tokens, makeToken2(ASSIGNOP_SIMPLE, "=")); 26 | list_add(tokens, makeToken2(INTEGER, "3")); 27 | list_add(tokens, makeToken(SEMICOLON)); 28 | 29 | list_add(tokens, makeToken2(RCURLY, "}")); 30 | 31 | struct StmtBlock* node = makeStmtBlock(tokens); 32 | 33 | assert(0 == list_size(tokens)); 34 | //all tokens should have been consumed 35 | assert(node != NULL); 36 | 37 | freeTokenList(tokens); 38 | free_stmt_block(node); 39 | 40 | return 1; 41 | } 42 | -------------------------------------------------------------------------------- /parser/test/astnodes/StmtBlockTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int test_stmtblock_1(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/const/ConstValueTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int test_boolconst_parse_bool_constant_node(); 6 | 7 | int test_charconst_parse_char_constant_node(); 8 | 9 | int test_charconst_parse_char_constant_node_newline(); 10 | -------------------------------------------------------------------------------- /parser/test/astnodes/expr/AddressOfTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ParseExprTests.h" 7 | 8 | #include "expr/AddressOf.h" 9 | 10 | #include "token/list/TokenList.h" 11 | #include "token/TokenKeys.h" 12 | #include "token/token/token.h" 13 | 14 | #include "ast/util/free_ast.h" 15 | 16 | int test_address_of() { 17 | 18 | status_test((char*)__func__); 19 | 20 | struct TokenList* list = makeTokenList(); 21 | list_add(list, makeToken(OPKEY_BITWISE_AND)); 22 | list_add(list, makeToken2(ID, "x")); 23 | 24 | struct AddressOf* d = makeAddressOf2(list); 25 | assert(d != NULL); 26 | 27 | freeTokenList(list); 28 | free_address_of(d); 29 | 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /parser/test/astnodes/expr/DerefTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "ParseExprTests.h" 7 | 8 | #include "expr/Deref.h" 9 | 10 | #include "token/list/TokenList.h" 11 | #include "token/TokenKeys.h" 12 | #include "token/token/token.h" 13 | 14 | #include "ast/util/free_ast.h" 15 | 16 | int test_deref() { 17 | 18 | status_test((char*)__func__); 19 | 20 | struct TokenList* list = makeTokenList(); 21 | list_add(list, makeToken(OPKEY_ARITHMETIC_MUL)); 22 | list_add(list, makeToken2(ID, "x")); 23 | 24 | struct Deref* d = makeDeref2(list); 25 | assert(d != NULL); 26 | 27 | freeTokenList(list); 28 | free_deref(d); 29 | 30 | return 1; 31 | } 32 | -------------------------------------------------------------------------------- /parser/test/astnodes/expr/ParseExprTests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // expr 6 | int expr_test_simple_expression(); 7 | int expr_test_variable_name_expression(); 8 | int expr_recognize_2_op_expr(); 9 | int expr_test_comparison(); 10 | int expr_test_3_terms(); 11 | 12 | // term 13 | int term_test_simple_term(); 14 | int term_test_variable_term(); 15 | int term_test_parentheses(); 16 | 17 | // unop 18 | int test_unop_with(); 19 | int test_unop_without(); 20 | 21 | // Deref 22 | int test_deref(); 23 | 24 | // AddressOf 25 | int test_address_of(); 26 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/AssignStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int assignstmt_test1(); 6 | int assignstmt_test_assign_method_call_result(); 7 | 8 | int assignstmt_test_assign_method_call_result_2(); 9 | 10 | int assignstmt_test_assign_variable_with_array_index(); 11 | 12 | int assignstmt_test_assign_char(); 13 | 14 | int assignstmt_test_can_assign_to_struct_member(); 15 | 16 | int assignstmt_test_type_declaration_for_variable(); 17 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/CallTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int methodcall_test1(); 6 | 7 | int methodcall_test2(); 8 | 9 | int methodcall_test3(); 10 | 11 | int methodcall_test_can_parse_subroutine_call(); 12 | 13 | int methodcall_test_can_parse_subroutine_call2(); 14 | 15 | int methodcall_test_can_parse_struct_member_access(); 16 | int methodcall_test_can_parse_array_access(); 17 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/CaseStmtTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "CaseStmtTest.h" 6 | 7 | #include "statements/CaseStmt.h" 8 | 9 | #include "token/list/TokenList.h" 10 | #include "token/TokenKeys.h" 11 | #include "token/token/token.h" 12 | 13 | #include "ast/util/free_ast.h" 14 | 15 | int test_parser_case_stmt() { 16 | 17 | status_test("test_parser_case_stmt"); 18 | 19 | struct TokenList* list = makeTokenList(); 20 | 21 | list_add(list, makeToken2(CASE, "case")); 22 | 23 | list_add(list, makeToken2(BCONST_TRUE, "true")); 24 | 25 | list_add(list, makeToken2(LCURLY, "{")); 26 | 27 | list_add(list, makeToken2(RCURLY, "}")); 28 | 29 | struct CaseStmt* node = makeCaseStmt(list); 30 | 31 | assert(node != NULL); 32 | assert(node->const_value->kind == 1); 33 | 34 | assert(node->const_value->ptr.m1_bool_const == true); 35 | assert(node->block != NULL); 36 | 37 | freeTokenList(list); 38 | free_case_stmt(node); 39 | 40 | return 1; 41 | } 42 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/CaseStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int test_parser_case_stmt(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/ForStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void for_test1(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/IfStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int if_test1(); 6 | int if_test2(); 7 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/RetStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int retstmt_test1(); 6 | 7 | int retstmt_test2(); 8 | 9 | int retstmt_test3(); 10 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/StmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int stmt_test_assignment_statement_with_struct_access(); 6 | 7 | int stmt_test_assignment_statement_with_method_call(); 8 | -------------------------------------------------------------------------------- /parser/test/astnodes/statements/WhileStmtTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int whilestmt_test1(); 6 | 7 | int whilestmt_test2(); 8 | -------------------------------------------------------------------------------- /parser/test/astnodes/struct/StructDeclTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int structdecl_test_can_parse_empty_struct_decl(); 6 | 7 | int structdecl_test_can_parse_struct_with_1_member(); 8 | 9 | int structdecl_test_can_parse_struct_with_2_members(); 10 | -------------------------------------------------------------------------------- /parser/test/astnodes/struct/StructMemberTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int structmember_test_can_parse_struct_member(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/subr/DeclArgTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int declarg_test_parse_declared_argument(); 6 | -------------------------------------------------------------------------------- /parser/test/astnodes/subr/MethodTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int method_test_can_parse_method_with_arguments(); 6 | 7 | int method_test_can_parse_subroutine(); 8 | 9 | int method_test_can_parse_method_without_arguments(); 10 | -------------------------------------------------------------------------------- /parser/test/astnodes/types/BasicTypeTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ParseTypeTests.h" 6 | 7 | #include "token/list/TokenList.h" 8 | #include "token/TokenKeys.h" 9 | #include "token/token/token.h" 10 | 11 | #include "types/BasicType.h" 12 | 13 | #include "ast/util/free_ast.h" 14 | 15 | int basictype_test_type_parsing_simple_type() { 16 | 17 | status_test("basictype_test_type_parsing_simple_type"); 18 | 19 | struct TokenList* list = makeTokenList(); 20 | list_add(list, makeToken2(TYPEID, "Carrot")); 21 | 22 | struct BasicType* b = makeBasicType2(list); 23 | 24 | //it is SimpleType 25 | assert(b->simple_type != NULL && b->subr_type == NULL); 26 | 27 | assert(0 == list_size(list)); 28 | 29 | freeTokenList(list); 30 | free_basic_type(b); 31 | 32 | return 1; 33 | } 34 | -------------------------------------------------------------------------------- /parser/test/astnodes/types/ParseTypeTests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int basictype_test_type_parsing_simple_type(); 6 | 7 | int simpletype_test_typenode_parsing(); 8 | int simpletype_test_typenode_parsing_fails(); 9 | int simpletype_test_typenode_parsing_anytype(); 10 | int simpletype_test_generic(); 11 | 12 | int structtype_test(); 13 | int structtype_test_type_param(); 14 | int structtype_test_generic(); 15 | 16 | int subrtype_test_typename(); 17 | int subrtype_test_typename_subroutine_return_type(); 18 | int subrtype_test_subroutine_type_parsing_subroutine_with_side_effects(); 19 | int subrtype_test_subroutine_type_parsing_subroutine_without_side_effects(); 20 | 21 | int pointertype_test_type_parsing(); 22 | -------------------------------------------------------------------------------- /parser/test/astnodes/types/StructTypeTest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "token/list/TokenList.h" 6 | #include "token/token/token.h" 7 | #include "token/TokenKeys.h" 8 | #include "ast/util/free_ast.h" 9 | #include "types/StructType.h" 10 | #include "ParseTypeTests.h" 11 | #include "ast/ast/ast_types.h" 12 | 13 | int structtype_test() { 14 | 15 | status_test("structtype_test"); 16 | 17 | struct TokenList* list = makeTokenList(); 18 | list_add(list, makeToken2(TYPEID, "MyType")); 19 | 20 | struct StructType* node = makeStructType(list); 21 | 22 | assert(0 == list_size(list)); 23 | assert(node != NULL); 24 | 25 | freeTokenList(list); 26 | free_struct_type(node); 27 | 28 | return 1; 29 | } 30 | -------------------------------------------------------------------------------- /parser/test/astnodes/var/SimpleVarTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int simplevar_test_parse_simple_variable(); 6 | 7 | int simplevar_test_parse_simple_indexed_variable(); 8 | 9 | int simplevar_test_2_indices(); 10 | -------------------------------------------------------------------------------- /parser/test/astnodes/var/VariableTest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | int variable_test_parse_struct_member_access(); 6 | int variable_test_parse_index_access(); 7 | int variable_test_parse_n_index_access(); 8 | int variable_test_parse_struct_member_access_and_index_access(); 9 | -------------------------------------------------------------------------------- /parser/test/commandline/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_parser_suite_constnodes(); 4 | 5 | void test_parser_suite_term_expr_simplevar_var(); 6 | void test_parser_suite_term(); 7 | void test_parser_suite_expr(); 8 | void test_parser_suite_simplevar(); 9 | void test_parser_suite_var(); 10 | 11 | void test_parser_suite_stmts(); 12 | void test_parser_suite_assignstmt(); 13 | 14 | void test_parser_suite_method(); 15 | void test_parser_suite_struct(); 16 | void test_parser_suite_types(); 17 | void test_parser_suite_range(); 18 | void test_parser_suite_namespace(); 19 | void test_parser_suite_unop(); 20 | -------------------------------------------------------------------------------- /parser/test/test_parser_util.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "test_parser_util.h" 4 | 5 | void status_test(char* name) { 6 | printf(" - [TEST] %s\n", name); 7 | } -------------------------------------------------------------------------------- /parser/test/test_parser_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void status_test(char* name); 4 | -------------------------------------------------------------------------------- /rat/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /rat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-rat" STATIC 3 | rat.c 4 | rat_avr.c 5 | rat_x86.c 6 | ) 7 | 8 | target_link_libraries("sd-rat" sd-util) 9 | 10 | add_subdirectory(test) 11 | -------------------------------------------------------------------------------- /rat/rat_avr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "rat.h" 8 | #include "register.h" 9 | #include "_struct.h" 10 | 11 | void rat_init_avr(struct RAT* rat) { 12 | 13 | for (uint32_t reg = r0; reg <= r31; reg++) { 14 | rat->status[reg] = REG_FREE; 15 | } 16 | 17 | rat_reserve_reg(rat, rat_return_reg(rat), "reserved for return value"); 18 | rat_reserve_reg(rat, rat_return_reg(rat) + 1, "reserved for return value"); 19 | rat_reserve_reg(rat, rat_scratch_reg(rat), "reserved as scratch register"); 20 | 21 | //r26 through r31 are X,Y,Z 22 | //and are used as pointer registers, 23 | //and should not be available for allocation 24 | rat_reserve_reg(rat, r26, "XL"); 25 | rat_reserve_reg(rat, r27, "XH"); 26 | 27 | //Y is our base pointer for the stack frame 28 | rat_reserve_reg(rat, rat_base_ptr(rat), "YL, frame ptr"); 29 | rat_reserve_reg(rat, rat_base_ptr(rat) + 1, "YH, frame ptr"); 30 | 31 | rat_reserve_reg(rat, r30, "ZL"); 32 | rat_reserve_reg(rat, r31, "ZH"); 33 | } 34 | -------------------------------------------------------------------------------- /rat/rat_x86.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | struct RAT; 9 | 10 | void rat_init_x86(struct RAT* rat); 11 | 12 | enum SD_REGISTER rat_return_reg_x86(); 13 | enum SD_REGISTER rat_base_ptr_x86(); 14 | enum SD_REGISTER rat_stack_ptr_x86(); 15 | enum SD_REGISTER rat_scratch_reg_x86(); 16 | 17 | enum SD_REGISTER rat_param_reg_x86(uint32_t index, bool is_syscall); 18 | 19 | // x86 specific 20 | char* rat_regname_x86(size_t i); 21 | 22 | // @returns the register name considering the number of bytes 23 | // e.g. (rax, 8) -> rax 24 | // e.g. (rax, 4) -> eax 25 | // e.g. (rax, 1) -> al 26 | // @returns NULL on error 27 | char* rat_regname_x86_width(size_t i, uint8_t nbytes); 28 | 29 | void rat_print_regname_x86(FILE* fout, size_t reg); 30 | -------------------------------------------------------------------------------- /rat/register.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct RAT; 8 | 9 | enum SD_REGISTER { 10 | 11 | // AVR 12 | r0 = 0, 13 | r1, 14 | r2, 15 | r3, 16 | r4, 17 | r5, 18 | r6, 19 | r7, 20 | r8, 21 | r9, 22 | r10, 23 | r11, 24 | r12, 25 | r13, 26 | r14, 27 | r15, 28 | r16, 29 | r17, 30 | r18, 31 | r19, 32 | r20, 33 | r21, 34 | r22, 35 | r23, 36 | r24, 37 | r25, 38 | r26, 39 | r27, 40 | r28, 41 | r29, 42 | r30, 43 | r31, 44 | 45 | // x86-64 46 | SD_REG_START_X86, 47 | 48 | SD_REG_RAX, 49 | SD_REG_RBX, 50 | SD_REG_RCX, 51 | SD_REG_RDX, 52 | SD_REG_RDI, 53 | SD_REG_RSI, 54 | 55 | SD_REG_RSP, 56 | SD_REG_RBP, 57 | 58 | SD_REG_R8, 59 | SD_REG_R9, 60 | SD_REG_R10, 61 | SD_REG_R11, 62 | SD_REG_R12, 63 | SD_REG_R13, 64 | SD_REG_R14, 65 | SD_REG_R15, 66 | 67 | SD_REG_END_X86, 68 | 69 | SD_REGISTER_END, 70 | }; 71 | -------------------------------------------------------------------------------- /rat/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-rat-test" 3 | test.c 4 | ) 5 | 6 | target_link_libraries("sd-rat-test" sd-util sd-rat) 7 | target_include_directories("sd-rat-test" PUBLIC "../..") 8 | -------------------------------------------------------------------------------- /rat/test/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_rat_scratch_reg(); 4 | void test_rat_alloc_different_regs(); 5 | void test_rat_alloc_in_bounds(); 6 | void test_rat_can_free(); 7 | void test_rat_occupant(); 8 | void test_rat_can_free_pair(); 9 | void test_rat_occupant_pair(); 10 | void test_rat_alloc_n_regs(); 11 | void test_rat_is_wide(); 12 | void test_rat_multiple_temps_in_register(); 13 | -------------------------------------------------------------------------------- /spec/types/generics.txt: -------------------------------------------------------------------------------- 1 | 2 | Generics are a staple of modern high level languages. 3 | They provide a way to write a function once, for a whole 4 | set of types (even all types, in some cases), given 5 | that the implementation does not require knowing anything 6 | about the type. 7 | 8 | This is especially useful when writing containers 9 | like Lists, Trees and such. 10 | 11 | I want to implement Generics in smalldragon. 12 | 13 | Proposed Syntax Changes: 14 | 15 | ------------- 16 | SimpleType ::= upperCaseLetter alphanumeric* ('<' TypeParameter+ '>')? | anyTypeToken 17 | ------------- 18 | 19 | This would enable (Examples): 20 | 21 | fn id (?T0 a) -> ?T0 { return a; } 22 | 23 | struct Point { 24 | ?T0 v1, 25 | ?T0 v2 26 | } 27 | 28 | fn get([?T0] arr, int index) -> ?T0 { 29 | return arr[index]; 30 | } 31 | -------------------------------------------------------------------------------- /spec/types/transiently-typed.txt: -------------------------------------------------------------------------------- 1 | when considering int, 2 | there could be the possibility of variables, 3 | when not being explicitly typed, to be of some of these types for only a certain amount of time. 4 | 5 | consider: 6 | 7 | uint x= 1; 8 | x=0; 9 | 10 | in such statements, in the first case it is of type uint and has property ( != 0), 11 | although only uint is declared. 12 | 13 | we should probably allow it to be set to 0, 14 | as mutable variables can be useful in some situations. 15 | 16 | before the 2nd statement, with x being (nonzero integer), 17 | there could be a division (z=10/x;) inserted. 18 | 19 | so all this is to illustrate that primitive datatypes could have different types throughout their lifetime. 20 | 21 | -------------------------------------------------------------------------------- /stdlib/.gitignore: -------------------------------------------------------------------------------- 1 | *.dracovm 2 | *.json 3 | main 4 | *.asm 5 | a.out 6 | *.c 7 | *.cof 8 | *.obj 9 | *.hex 10 | -------------------------------------------------------------------------------- /stdlib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | TESTS := tests/test_matrix.dg \ 3 | #tests/test_math.dg \ 4 | #tests/collections/test_intbintree.dg \ 5 | #tests/collections/test_arraylist.dg \ 6 | #tests/collections/test_linkedlist.dg \ 7 | #tests/collections/test_array.dg \ 8 | #tests/test_primes.dg \ 9 | #tests/test_polynomial.dg \ 10 | #tests/collections/test_set.dg \ 11 | #tests/collections/test_stack.dg \ 12 | 13 | SOURCES := test.dg \ 14 | collections/linkedlist.dg \ 15 | collections/arraylist.dg \ 16 | collections/array.dg \ 17 | collections/set.dg \ 18 | collections/stack.dg \ 19 | collections/intbintree.dg \ 20 | base/math.dg \ 21 | base/primes.dg \ 22 | base/polynomial.dg \ 23 | avr/portb.dg \ 24 | avr/timer0.dg \ 25 | 26 | test: $(SOURCES) clean 27 | sd $(SOURCES) 28 | 29 | debug: $(SOURCES) clean 30 | sd -debug $(SOURCES) 31 | 32 | clean: 33 | rm -f a.out 34 | rm -f *.c *.asm *.hex *.obj 35 | rm -f *.dot *.png 36 | -------------------------------------------------------------------------------- /stdlib/avr/portb.dg: -------------------------------------------------------------------------------- 1 | 2 | fn portb_ddrd(uint8 value) -> int { 3 | 4 | *uint8 ptr = DDRB; 5 | *ptr = value; 6 | return 0; 7 | } 8 | 9 | fn portb_write(uint8 value) -> int { 10 | 11 | *uint8 portb_data = PORTB; 12 | *portb_data = value; 13 | return 0; 14 | } 15 | 16 | fn portb_read() -> uint8 { 17 | 18 | *uint8 ptr = PORTB; 19 | return *ptr; 20 | } 21 | -------------------------------------------------------------------------------- /stdlib/avr/timer0.dg: -------------------------------------------------------------------------------- 1 | // functions to control Timer0 on ATMega328p 2 | 3 | fn timer0_mode(uint8 value) -> int { 4 | 5 | *uint8 tccr0a = TCCR0A; 6 | *tccr0a = value; 7 | return 0; 8 | } 9 | 10 | fn timer0_prescaler(uint8 value) -> int { 11 | 12 | //valid values: 1,2,3,4,5 13 | 14 | *uint8 tccr0b = TCCR0B; 15 | *tccr0b = value; 16 | return 0; 17 | } 18 | 19 | fn timer0_read() -> uint8 { 20 | 21 | *uint8 tcnt0 = TCNT0; 22 | return *tcnt0; 23 | } 24 | -------------------------------------------------------------------------------- /stdlib/base/assert.dg: -------------------------------------------------------------------------------- 1 | 2 | fn assert(bool x) -> int { 3 | 4 | //TODO: print error message 5 | if (!x){ 6 | exit(1); 7 | } 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /stdlib/base/polynomial.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Poly { 3 | [int] coeff; 4 | 5 | @private 6 | uint n; 7 | } 8 | 9 | @private 10 | struct Monomial { 11 | int factor; 12 | uint exponent; 13 | } 14 | 15 | 16 | fn poly_deg(Poly p) -> uint { 17 | uint i = p.n - 1; 18 | while i >= 0 { 19 | if p.coeff[i] != 0 { return i; } 20 | i--; 21 | } 22 | return 0; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /stdlib/base/primes.dg: -------------------------------------------------------------------------------- 1 | //this file provides subroutines for dealing with 2 | //prime numbers. 3 | 4 | @halts 5 | fn isprime(uint n) -> bool { 6 | 7 | uint count = 0; 8 | 9 | for k in 1 .. n { 10 | 11 | if n % k == 0 12 | { count++; } 13 | } 14 | return count == 2; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /stdlib/collections/array.dg: -------------------------------------------------------------------------------- 1 | //simple functions dealing with arrays of integers 2 | 3 | fn array_contains([int] arr, uint size, int elem) -> bool { 4 | 5 | for i in 0 .. (size - 1) { 6 | if arr[i] == elem { return true; } 7 | } 8 | return false; 9 | } 10 | -------------------------------------------------------------------------------- /stdlib/collections/arraylist.dg: -------------------------------------------------------------------------------- 1 | 2 | struct ArrayList { 3 | 4 | @private [int] arr; 5 | @private uint size; 6 | @private uint capacity; 7 | } 8 | 9 | 10 | fn arraylist_size(ArrayList list) -> uint { 11 | return list.size; 12 | } 13 | 14 | 15 | fn arraylist_at(ArrayList list, uint i) -> int { 16 | 17 | return list.arr[i]; 18 | } 19 | 20 | fn arraylist_contains(ArrayList list, int elem) -> bool { 21 | 22 | for i in 0 .. (list.size - 1) { 23 | if list.arr[i] == elem { return true; } 24 | } 25 | return false; 26 | } 27 | 28 | fn arraylist_index_of(ArrayList list, int elem) -> int { 29 | 30 | for i in 0 .. (list.size - 1) { 31 | if list.arr[i] == elem { return i; } 32 | } 33 | return -1; 34 | } 35 | 36 | fn arraylist_clear(ArrayList list) ~> bool { 37 | list.size = 0; 38 | return true; 39 | } 40 | 41 | 42 | -------------------------------------------------------------------------------- /stdlib/collections/linkedlist.dg: -------------------------------------------------------------------------------- 1 | 2 | //A simple double-linked list 3 | 4 | struct LinkedList { 5 | 6 | @private uint size; 7 | 8 | @private bool is_empty; 9 | @private LLNode head; 10 | @private LLNode tail; 11 | } 12 | 13 | @private 14 | struct LLNode { 15 | 16 | int value; 17 | bool has_next; 18 | 19 | LLNode prev; 20 | LLNode next; 21 | } 22 | 23 | @halts 24 | fn linkedlist_size(LinkedList l) -> uint { 25 | return l.size; 26 | } 27 | 28 | 29 | fn linkedlist_contains(LinkedList l, int value) -> bool { 30 | 31 | return linkedlist_index_of(l, value) >= 0; 32 | } 33 | 34 | fn linkedlist_index_of(LinkedList l, int value) -> int { 35 | 36 | LLNode current = l.head; 37 | int i = 0; 38 | 39 | while current.has_next { 40 | 41 | if current.value == value { 42 | return i; 43 | } 44 | 45 | current = current.next; 46 | i++; 47 | } 48 | 49 | if current.value == value { 50 | return i; 51 | } 52 | 53 | return -1; 54 | } 55 | -------------------------------------------------------------------------------- /stdlib/collections/set.dg: -------------------------------------------------------------------------------- 1 | 2 | struct Set { 3 | @private uint size; 4 | @private uint capacity; 5 | @private [int] arr; 6 | } 7 | 8 | 9 | fn set_size(Set s) -> uint { 10 | 11 | return s.size; 12 | } 13 | 14 | fn set_contains(Set s, int x) -> bool { 15 | 16 | for i in 1 .. s.size { 17 | 18 | if s.arr[i-1] == x { return true; } 19 | } 20 | 21 | return false; 22 | } 23 | 24 | 25 | fn set_remove(Set s, int x) -> bool { 26 | 27 | if !set_contains(s, x) { return true; } 28 | 29 | //find the index of the element 30 | uint idx = 0; 31 | for i in 0 .. s.size - 1 { 32 | if s.arr[i] == x { 33 | 34 | idx = i; 35 | break; 36 | } 37 | } 38 | 39 | //shift all elements left 40 | for j in idx .. s.size - 1 { 41 | 42 | s.arr[j] = s.arr[j+1]; 43 | } 44 | 45 | s.size--; 46 | 47 | return true; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /stdlib/collections/stack.dg: -------------------------------------------------------------------------------- 1 | 2 | //A naive implementation of a stack 3 | 4 | struct Stack { 5 | @private uint size; 6 | @private uint capacity; 7 | @private [int] arr; 8 | } 9 | 10 | 11 | fn stack_size(Stack s) -> uint { 12 | return s.size; 13 | } 14 | 15 | fn stack_contains(Stack s, int elem) -> bool { 16 | 17 | for i in 0 .. (s.size - 1) { 18 | if s.arr[i] == elem { return true; } 19 | } 20 | return false; 21 | } 22 | 23 | 24 | fn stack_peek(Stack s) -> int { 25 | 26 | return s.arr[s.size - 1]; 27 | } 28 | 29 | fn stack_pop(Stack s) -> int { 30 | 31 | res = stack_peek(s); 32 | s.size--; 33 | 34 | return res; 35 | } 36 | -------------------------------------------------------------------------------- /stdlib/draw/ppm.dg: -------------------------------------------------------------------------------- 1 | // PPM is a very simple image format 2 | 3 | // https://de.wikipedia.org/wiki/Portable_Anymap 4 | // https://netpbm.sourceforge.net/doc/ppm.html 5 | 6 | fn ppm_create(int fd, uint64 w, uint64 h, uint64 maxvalue) -> int { 7 | 8 | fprint(fd, "P3\n"); 9 | 10 | fprint_uint64(fd, w); 11 | fprintln(fd); 12 | fprint_uint64(fd, h); 13 | fprintln(fd); 14 | fprint_uint64(fd, maxvalue); 15 | fprintln(fd); 16 | 17 | return 0; 18 | } 19 | 20 | fn ppm_pixel (int fd, uint8 red, uint8 green, uint8 blue) -> int { 21 | 22 | fprint_uint64(fd, red); 23 | fprint(fd, " "); 24 | fprint_uint64(fd, green); 25 | fprint(fd, " "); 26 | fprint_uint64(fd, blue); 27 | fprint(fd, " "); 28 | 29 | return 0; 30 | } 31 | 32 | fn ppm_newline(int fd) -> int { 33 | 34 | fprintln(fd); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /stdlib/tests/test_math.dg: -------------------------------------------------------------------------------- 1 | fn testmath() ~> int { 2 | 3 | assert(sign(4) == 1); 4 | assert(sign(-8) == -1); 5 | 6 | assert( ipow(2,3) == 8 ); 7 | 8 | assert( faculty(3) == 6 ); 9 | assert( faculty(4) == 24 ); 10 | 11 | assert( min(4,5) == 4 ); 12 | 13 | assert( max(2,6) == 6 ); 14 | 15 | assert(gcd(10,15) == 5); 16 | assert(lcm(15,20) == 60); 17 | 18 | assert(fib(1) == 0); 19 | assert(fib(2) == 1); 20 | assert(fib(3) == 1); 21 | assert(fib(4) == 2); 22 | assert(fib(5) == 3); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /stdlib/tests/test_primes.dg: -------------------------------------------------------------------------------- 1 | fn test_primes() ~> int { 2 | 3 | assert(isprime(2)); 4 | assert(isprime(3)); 5 | assert(!isprime(4)); 6 | assert(isprime(5)); 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /syntax-tools/batcat/install.sh: -------------------------------------------------------------------------------- 1 | #https://github.com/sharkdp/bat 2 | 3 | #process is similar to sublime text 4 | #they accept sublime text packages 5 | 6 | mkdir -p "$(batcat --config-dir)/syntaxes" 7 | cd "$(batcat --config-dir)/syntaxes" || exit 1 8 | 9 | # Put new '.sublime-syntax' language definition files 10 | # in this folder (or its subdirectories), for example: 11 | ln -s ~/smalldragon/syntax-tools/sublime-text/dragon.sublime-syntax . 12 | 13 | batcat cache --build 14 | 15 | #to remove it: 16 | #batcat cache --clear 17 | -------------------------------------------------------------------------------- /syntax-tools/geany/README.txt: -------------------------------------------------------------------------------- 1 | #https://wiki.geany.org/config/start 2 | #how to achieve smalldragon syntax highlight in geany 3 | 4 | #step 1: 5 | 6 | cd ~/.config/geany/filedefs 7 | ln -s ~/smalldragon/syntax-tools/geany/filetypes.smalldragon.conf 8 | 9 | #step 2: 10 | In Geany: 11 | go to Tools -> Configuration Files -> filetype_extensions.conf 12 | 13 | put 14 | #~ smalldragon=*.dg; 15 | 16 | directly under 17 | #~ [Extensions] 18 | 19 | #step 3: 20 | #if the step 2 did not give you syntax highlight after 21 | #restart, you can also edit global config files 22 | #and perform step 2 that way 23 | 24 | sudo vim/usr/share/geany/filetype_extensions.conf 25 | -------------------------------------------------------------------------------- /syntax-tools/micro/HOWTO.txt: -------------------------------------------------------------------------------- 1 | create a symlink to this file in 2 | ~/.config/micro/syntax/ 3 | 4 | when starting micro, it should highlight it according to this file 5 | -------------------------------------------------------------------------------- /syntax-tools/sublime-text/.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-package 2 | -------------------------------------------------------------------------------- /syntax-tools/sublime-text/install.sh: -------------------------------------------------------------------------------- 1 | #mkdir ~/.config/sublime-text-3/Packages/User 2 | 3 | #zip dragon.zip dragon.sublime-syntax 4 | #mv dragon.zip dragon.sublime-package 5 | 6 | cp dragon.sublime-syntax ~/.config/sublime-text-3/Packages/User 7 | -------------------------------------------------------------------------------- /syntax-tools/syntaxfiles.txt: -------------------------------------------------------------------------------- 1 | Dragon should have atleast syntax highlighting 2 | in some of my most favorite Text Editors. 3 | This makes it much more fun to program in Dragon. 4 | 5 | - [x] vim 6 | - [x] micro 7 | - [ ] sublime text 8 | 9 | https://github.com/zyedidia/micro/issues/573 10 | 11 | https://github.com/zyedidia/micro/tree/master/runtime/syntax 12 | 13 | 14 | -------------------------------------------------------------------------------- /syntax-tools/vim/dotvimrc-append.txt: -------------------------------------------------------------------------------- 1 | 2 | "this file is to be appended to ~/.vimrc 3 | "You can also use 'source $PATH_TO_THIS_FILE' in your ~/.vimrc 4 | "in order to avoid manually appending 5 | 6 | hi def link singlelineComment Comment 7 | hi def link multilineComment Comment 8 | 9 | hi def link basicLanguageKeywords Statement 10 | 11 | 12 | hi def link basicNumber Constant 13 | hi def link basicString Constant 14 | hi def link basicBool Boolean 15 | 16 | hi def link Braces Delimiter 17 | hi def link Parens Delimiter 18 | 19 | hi def link basicIdentifier Identifier 20 | hi def link basicType Type 21 | hi def link basicType2 Type 22 | hi def link primitiveType Type 23 | 24 | hi def link basicOperator Operator 25 | 26 | hi def link annotation PreProc 27 | -------------------------------------------------------------------------------- /syntax-tools/vim/ftdetect/dg.vim: -------------------------------------------------------------------------------- 1 | autocmd BufRead,BufNewFile *.dg set filetype=dg 2 | -------------------------------------------------------------------------------- /syntax-tools/vim/install.sh: -------------------------------------------------------------------------------- 1 | # How to setup syntax highlighting in vim 2 | # for smalldragon 3 | 4 | cp ftdetect/* ~/.vim/ftdetect/ 5 | cp syntax/* ~/.vim/syntax/ 6 | -------------------------------------------------------------------------------- /tables/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-tables" STATIC 3 | 4 | cc/cc.c 5 | 6 | lvst/lvst.c 7 | 8 | sst/sst.c 9 | sst/sst_fill.c 10 | sst/sst_print.c 11 | 12 | stst/stst.c 13 | stst/stst_print.c 14 | 15 | data/data.c 16 | 17 | enum/enum_table.c 18 | enum/enum_table.h 19 | 20 | symtable/symtable.c 21 | ) 22 | 23 | target_include_directories("sd-tables" PUBLIC "..") 24 | 25 | add_subdirectory(test) 26 | -------------------------------------------------------------------------------- /tables/cc/cc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct CCNode; 7 | 8 | struct CC { 9 | //CC means "Callees and Callers" 10 | 11 | struct CCNode* callees; 12 | struct CCNode* callers; 13 | 14 | bool calls_fn_ptrs; 15 | }; 16 | 17 | //-------------------------------------------- 18 | 19 | struct CC* cc_ctor(); 20 | void cc_free(struct CC* cc); 21 | 22 | //-------------------------------------------- 23 | void cc_add_callee(struct CC* cc, char* name); 24 | void cc_add_caller(struct CC* cc, char* name); 25 | //-------------------------------------------- 26 | uint32_t cc_size(struct CCNode* ccnode); 27 | //-------------------------------------------- 28 | struct CCNode* cc_next(struct CCNode* node); //may return NULL 29 | char* cc_name(struct CCNode* node); 30 | 31 | void cc_set_calls_fn_ptrs(struct CC* cc, bool value); 32 | -------------------------------------------------------------------------------- /tables/data/data.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct DataTable; 8 | 9 | struct DataEntry { 10 | 11 | // needs to be freed 12 | char* symbol; 13 | // needs to be freed 14 | char* value; 15 | }; 16 | 17 | struct DataTable* data_ctor(); 18 | void data_dtor(struct DataTable* data); 19 | 20 | // @returns the count of entries in data table 21 | size_t data_count(struct DataTable* data); 22 | 23 | void data_write_data_segment(struct DataTable* data, FILE* fout); 24 | 25 | // @brief inserts a new entry into data table 26 | // @param str the string to enter 27 | bool data_insert(struct DataTable* data, char* str); 28 | 29 | // @brief may return e.g. "str_hello" 30 | // for string "hello" stored in table 31 | // @returns NULL if entry is not found 32 | char* data_symbol(struct DataTable* data, uint32_t offset); 33 | 34 | // @brief returns offset of string in data table 35 | // @param str The string from 'struct StringConst' 36 | // @returns < 0 on error 37 | int32_t data_string_offset(struct DataTable* data, char* str); 38 | -------------------------------------------------------------------------------- /tables/enum/enum_table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ast/ast_declare.h" 7 | #include "tables/symtable/symtable.h" 8 | 9 | struct EnumTable; 10 | 11 | struct EnumTableEntry { 12 | 13 | // needs to be freed 14 | char* name; 15 | 16 | int64_t value; 17 | }; 18 | 19 | struct EnumTable* enum_table_ctor(); 20 | void enum_table_dtor(struct EnumTable* data); 21 | 22 | // @brief inserts a new entry into enum value table 23 | // @param str the name to enter 24 | // @param value the value for that enum value name 25 | bool enum_table_insert(struct EnumTable* data, char* str, int64_t value); 26 | 27 | // @returns false if entry is not found 28 | // @sets value_out = integer value for the enum value name 29 | bool enum_table_lookup(struct EnumTable* data, char* name, int64_t* value_out); 30 | 31 | bool enum_table_fill(struct EnumTable* enum_table, struct Namespace* ns, bool debug); 32 | 33 | void enum_table_print(struct EnumTable* enum_table); 34 | 35 | int int_value_from_const(struct ConstValue* cv); 36 | -------------------------------------------------------------------------------- /tables/sst/sst_fill.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //utilities to help fill the SST 4 | 5 | struct Namespace; 6 | struct Method; 7 | struct MethodDecl; 8 | 9 | struct SST; 10 | struct ST; 11 | 12 | void sst_fill(struct ST* st, struct SST* sst, struct Namespace* ns); 13 | 14 | struct Type* method_to_type(struct Method* m); 15 | // @returns NULL on error 16 | struct SubrType* method_decl_to_subrtype(struct MethodDecl* mdecl); 17 | struct Type* method_decl_to_type(struct MethodDecl* mdecl); 18 | -------------------------------------------------------------------------------- /tables/sst/sst_print.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct SST; 4 | 5 | void sst_print(struct SST* sst); 6 | -------------------------------------------------------------------------------- /tables/stst/stst_print.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "stst.h" 4 | 5 | static void stst_print_for_struct(struct STSTLine* line); 6 | static char* fmt = "%16s|%16s|\n"; 7 | 8 | void stst_print(struct STST* stst) { 9 | 10 | printf("[STST] Struct Symbol Table (%d elements)\n", stst_size(stst)); 11 | printf(fmt, "struct name", "member name"); 12 | 13 | //-------- 14 | //---------------- 15 | 16 | printf("----------------|----------------|\n"); 17 | 18 | for (size_t i = 0; i < stst_size(stst); i++) { 19 | 20 | struct STSTLine* line = stst_at(stst, i); 21 | 22 | stst_print_for_struct(line); 23 | } 24 | } 25 | 26 | static void stst_print_for_struct(struct STSTLine* line) { 27 | 28 | for (int j = 0; j < line->decl->count_members; j++) { 29 | 30 | struct StructMember* member = line->decl->members[j]; 31 | 32 | printf(fmt, line->name, member->name); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tables/stst/stst_print.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct STST; 4 | 5 | void stst_print(struct STST* stst); 6 | -------------------------------------------------------------------------------- /tables/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-tables-test" STATIC 3 | 4 | test.c 5 | ) 6 | 7 | target_link_libraries("sd-tables-test" sd-tables) 8 | target_link_libraries("sd-tables-test" sd-util) 9 | 10 | target_include_directories("sd-tables-test" PUBLIC "../..") 11 | 12 | -------------------------------------------------------------------------------- /tables/test/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_tables_lvst_ctor(); 4 | void test_tables_lvst_sizeof_type_primitive(); 5 | void test_tables_lvst_sizeof_type_other(); 6 | void test_tables_lvst_sizeof_pointer_type(); 7 | void test_tables_lvst_stack_frame_size_avr(); 8 | void test_tables_lvst_stack_frame_size_x86(); 9 | void test_tables_lvst_stack_frame_offset_avr_int8(); 10 | void test_tables_lvst_stack_frame_offset_avr_int64(); 11 | void test_tables_lvst_stack_frame_offset_x86_int8(); 12 | void test_tables_lvst_stack_frame_offset_x86_int64(); 13 | void test_tables_lvst_arg_index(); 14 | -------------------------------------------------------------------------------- /tac/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library("sd-tac" STATIC 2 | tac.c 3 | tac_ctor.c 4 | tac_str.c 5 | tacbuffer.c 6 | tacbuffer_optimize.c 7 | ) 8 | 9 | target_include_directories("sd-tac" PUBLIC "..") 10 | 11 | add_subdirectory(test) 12 | -------------------------------------------------------------------------------- /tac/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library("sd-tac-test" 3 | test_tac.c 4 | test_tacbuffer.c 5 | ) 6 | 7 | target_link_libraries("sd-tac-test" sd-tac) 8 | target_link_libraries("sd-tac-test" sd-util) 9 | target_link_libraries("sd-tac-test" sd-tables) 10 | target_link_libraries("sd-tac-test" sd-ast) 11 | -------------------------------------------------------------------------------- /tac/test/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_tac_tostring(); 4 | void test_tac_opt_dest(); 5 | 6 | void test_tacbuffer_tostring(); 7 | void test_tacbuffer_indexof(); 8 | void test_tacbuffer_set(); 9 | void test_tacbuffer_get(); 10 | void test_tacbuffer_get_last(); 11 | void test_tacbuffer_last_dest(); 12 | void test_tacbuffer_count(); 13 | -------------------------------------------------------------------------------- /token/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(sd-token STATIC 2 | list/TokenList.c 3 | token/token.c 4 | ) 5 | 6 | target_link_libraries(sd-token sd-util) 7 | 8 | target_include_directories(sd-token PUBLIC ".") 9 | 10 | add_subdirectory(test) 11 | -------------------------------------------------------------------------------- /token/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | add_library(sd-token-test 3 | testcases/tests_tokenlist.c 4 | ) 5 | 6 | target_include_directories(sd-token-test PUBLIC "../..") 7 | 8 | target_link_libraries(sd-token-test sd-util) 9 | target_link_libraries(sd-token-test sd-token) 10 | -------------------------------------------------------------------------------- /token/test/test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void test_tokenlist_no_leak(); 4 | void test_tokenlist_1element(); 5 | void test_tokenlist_copy(); 6 | void test_tokenlist_code(); 7 | void test_tokenlist_print(); 8 | void test_tokenlist_consume(); 9 | -------------------------------------------------------------------------------- /util/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library("sd-util" STATIC 2 | status/status.c 3 | ) 4 | -------------------------------------------------------------------------------- /util/status/status.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "status.h" 3 | 4 | void status(char* msg) { 5 | 6 | printf(" - [TEST] %s\n", msg); 7 | } 8 | -------------------------------------------------------------------------------- /util/status/status.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // for use in testcases 4 | void status(char* msg); 5 | --------------------------------------------------------------------------------