diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 35e451a..95b8603 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -303,24 +303,26 @@ namespace gcc void generic_visitor::visit(boot::binary_expression *expression) { expression->lhs().accept(this); - auto left = this->current_expression; - auto left_type = TREE_TYPE(left); + tree left = this->current_expression; + tree left_type = TREE_TYPE(left); expression->rhs().accept(this); - auto right = this->current_expression; - auto right_type = TREE_TYPE(right); + tree right = this->current_expression; + tree right_type = TREE_TYPE(right); - auto expression_location = get_location(&expression->position()); + location_t expression_location = get_location(&expression->position()); tree_code operator_code = ERROR_MARK; tree target_type = error_mark_node; - if (is_pointer_type(left_type) && is_integral_type(right_type) - && expression->operation() == boot::binary_operator::sum) + if (is_pointer_type(left_type) && is_integral_type(right_type)) { - tree convert_expression = build1_loc(expression_location, CONVERT_EXPR, - sizetype, right); - this->current_expression = build2_loc(expression_location, - POINTER_PLUS_EXPR, left_type, left, convert_expression); + this->current_expression = do_pointer_arithmetic(expression->operation(), left, right); + if (this->current_expression == error_mark_node) + { + error_at(expression_location, + "invalid operation %s on a pointer and an integral type", + boot::print_binary_operator(expression->operation())); + } return; } if (left_type != right_type) diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index 56d916c..4df2806 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -1,6 +1,7 @@ #include "elna/gcc/elna-tree.h" #include "stor-layout.h" +#include "fold-const.h" tree elna_global_trees[ELNA_TI_MAX]; @@ -81,5 +82,22 @@ namespace gcc return initial_table; } + + tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right) + { + tree result = error_mark_node; + tree convert_expression = fold_convert(sizetype, right); + + if (binary_operator == boot::binary_operator::sum) + { + result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression); + } + else if (binary_operator == boot::binary_operator::subtraction) + { + convert_expression = fold_build1(NEGATE_EXPR, sizetype, convert_expression); + result = fold_build2(POINTER_PLUS_EXPR, TREE_TYPE(left), left, convert_expression); + } + return result; + } } } diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index dada145..def424e 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -4,8 +4,8 @@ #include "system.h" #include "coretypes.h" #include "tree.h" -#include "tree.h" +#include "elna/boot/ast.h" #include "elna/boot/symbol.h" enum elna_tree_index @@ -58,5 +58,7 @@ namespace gcc }; std::shared_ptr> builtin_symbol_table(); + + tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right); } } diff --git a/source.elna b/source.elna index c53c785..bd15e59 100644 --- a/source.elna +++ b/source.elna @@ -20,6 +20,9 @@ type end, FILE = record dummy: Int + end, + CommandLine = record + input: pointer to Char end; const @@ -141,19 +144,6 @@ end; End of standard procedures. *) -proc test_primitive(); -begin - write_s("\nTest primitives:\n"); - write_u(25u); - write_c('\n'); - - write_i(8); - write_c('\n'); - - write_b(true); - write_c('\n') -end; - proc read_source(filename: String): pointer to Char; var input_file: pointer to FILE, @@ -272,7 +262,7 @@ var is_valid: Bool; begin token_end := input; - previous := cast(cast(input as Word) - 1u as pointer to Char); + previous := input - 1; while token_end^ <> '\0' and not (previous^ <> '\\' and token_end^ = '"') do previous := token_end; @@ -677,32 +667,51 @@ begin return tokens end; -proc command_line(argc: Int, argv: pointer to pointer to Char); +proc parse_command_line(argc: Int, argv: pointer to pointer to Char): pointer to CommandLine; var parameter: pointer to pointer to Char, - i: Int; + i: Int, + result: pointer to CommandLine; begin - write_s("Argument count: "); - write_i(argc - 1); - write_s("\nArguments:"); + if argc < 2 then + write_s("Fatal error: no input files.\n"); + return nil + end; + if argc > 2 then + write_s("Fatal error: Unknown command line options:"); - i := 1; - while i < argc do - parameter := argv + i * cast(sizeof(pointer to Char) as Int); + i := 2; + while i < argc do + parameter := argv + i * cast(sizeof(pointer to Char) as Int); + + write_c(' '); + write_s(parameter^); + i := i + 1 + end; + write_s(".\n"); + return nil + end; - write_c(' '); - write_s(parameter^); - i := i + 1 - end + parameter := argv + cast(sizeof(pointer to Char) as Int); + result := cast(malloc(sizeof(CommandLine)) as pointer to CommandLine); + result^.input := parameter^; + + return result end; -proc compile(); +proc process(argc: Int, argv: pointer to pointer to Char): Int; var input: pointer to Char, tokens: pointer to Token, - tokens_size: Word; + tokens_size: Word, + command_line: pointer to CommandLine; begin - input := read_source("example.elna"); + command_line := parse_command_line(argc, argv); + + if cast(command_line as Word) = 0u then + return 2 + end; + input := read_source(command_line^.input); tokens := tokenize(input, @tokens_size); free(input); @@ -711,9 +720,5 @@ begin end; begin - command_line(count, parameters); - compile(); - test_primitive(); - - exit(0) + exit(process(count, parameters)) end.