diff --git a/README.md b/README.md index c15d6a2..0c73162 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,25 @@ and a possbility to compile Elna programs for different platforms. Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found in the `boot/` directory. + +## Build + +The frontend requires GCC 14.2.0 (not tested with other versions). + +Download the GCC source. Copy the contents of this repository into `gcc/elna` +inside GCC. Finally build GCC enabling the frontend with +`--enable-languages=c,c++,elna`. After the installation the compiler can be +invoked with `$prefix/bin/gelna`. + +There is also a `Rakefile` that downloads, builds and installs GCC into the +`./build/` subdirectory. The `Rakefile` assumes that ruby and rake, as well as +all GCC dependencies are already available in the system. It works under Linux +and Mac OS. In the latter case GCC is patched with the patches used by Homebrew +(official GCC doesn't support Apple silicon targets). Invoke with + +```sh +rake boot +``` + +See `rake -T` for more tasks. The GCC source is under `build/tools`. The +installation path is `build/host/install`. diff --git a/boot/ast.cc b/boot/ast.cc index 9170485..55fa37f 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -1014,6 +1014,8 @@ namespace boot return "and"; case binary_operator::disjunction: return "or"; + case binary_operator::exclusive_disjunction: + return "xor"; } __builtin_unreachable(); }; diff --git a/boot/lexer.ll b/boot/lexer.ll index f0bbe8a..4fc2664 100644 --- a/boot/lexer.ll +++ b/boot/lexer.ll @@ -122,6 +122,9 @@ nil { and { return yy::parser::make_AND(this->location); } +xor { + return yy::parser::make_XOR(this->location); + } or { return yy::parser::make_OR(this->location); } @@ -134,9 +137,6 @@ return { cast { return yy::parser::make_CAST(this->location); } -as { - return yy::parser::make_AS(this->location); - } sizeof { return yy::parser::make_SIZEOF(this->location); } diff --git a/boot/parser.yy b/boot/parser.yy index f59f8ab..1a2fb25 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -85,12 +85,12 @@ along with GCC; see the file COPYING3. If not see %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION %token BEGIN_BLOCK END_BLOCK EXTERN DEFER %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA -%token AND OR NOT CAST AS SIZEOF +%token AND OR NOT CAST SIZEOF %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %token PLUS MINUS MULTIPLICATION DIVISION REMAINDER %token ASSIGNMENT COLON HAT AT NIL ARROW -%left OR AND +%left OR AND XOR %left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL %left PLUS MINUS %left MULTIPLICATION DIVISION REMAINDER @@ -189,7 +189,7 @@ call_expression: IDENTIFIER actual_parameter_list $$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1); std::swap($$->arguments(), $2); } -cast_expression: CAST LEFT_PAREN expression AS type_expression RIGHT_PAREN +cast_expression: CAST LEFT_PAREN expression COLON type_expression RIGHT_PAREN { $$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3); } @@ -339,6 +339,11 @@ expression: $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, elna::boot::binary_operator::disjunction); } + | expression XOR expression + { + $$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3, + elna::boot::binary_operator::exclusive_disjunction); + } unary: AT operand { @@ -403,9 +408,9 @@ optional_statements: field_declaration: IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); } field_list: - field_declaration SEMICOLON field_list + field_declaration field_list { - std::swap($$, $3); + std::swap($$, $2); $$.emplace($$.cbegin(), $1); } | field_declaration { $$.emplace_back($1); } diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index bd704bc..3cf6b99 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -43,6 +43,94 @@ namespace gcc this->symbol_map = symbol_table; } + void generic_visitor::build_procedure_call(location_t call_location, + tree symbol, const std::vector& arguments) + { + vec *argument_trees = nullptr; + tree current_parameter = TYPE_ARG_TYPES(TREE_TYPE(symbol)); + + vec_alloc(argument_trees, arguments.size()); + for (boot::expression *const argument : arguments) + { + location_t argument_location = get_location(&argument->position()); + if (is_void_type(TREE_VALUE(current_parameter))) + { + error_at(argument_location, "too many arguments, expected %i, got %lu", + list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size()); + this->current_expression = error_mark_node; + break; + } + argument->accept(this); + if (!is_assignable_from(TREE_VALUE(current_parameter), this->current_expression)) + { + error_at(argument_location, + "cannot assign value of type '%s' to variable of type '%s'", + print_type(TREE_TYPE(this->current_expression)).c_str(), + print_type(TREE_VALUE(current_parameter)).c_str()); + this->current_expression = error_mark_node; + } + current_parameter = TREE_CHAIN(current_parameter); + argument_trees->quick_push(this->current_expression); + } + tree stmt = build_call_expr_loc_vec(call_location, symbol, argument_trees); + + if (!is_void_type(TREE_VALUE(current_parameter))) + { + error_at(call_location, "too few arguments, expected %i, got %lu", + list_length(TYPE_ARG_TYPES(TREE_TYPE(symbol))) - 1, arguments.size()); + this->current_expression = error_mark_node; + } + else if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node) + { + append_statement(stmt); + this->current_expression = NULL_TREE; + } + else + { + this->current_expression = stmt; + } + } + + void generic_visitor::build_record_call(location_t call_location, + tree symbol, const std::vector& arguments) + { + vec *tree_arguments = nullptr; + tree record_fields = TYPE_FIELDS(symbol); + for (boot::expression *const argument : arguments) + { + location_t argument_location = get_location(&argument->position()); + + if (is_void_type(record_fields)) + { + error_at(argument_location, "too many arguments, expected %i, got %lu", + list_length(TYPE_FIELDS(symbol)), arguments.size()); + this->current_expression = error_mark_node; + break; + } + argument->accept(this); + if (!is_assignable_from(TREE_TYPE(record_fields), this->current_expression)) + { + error_at(argument_location, + "cannot assign value of type '%s' to variable of type '%s'", + print_type(TREE_TYPE(this->current_expression)).c_str(), + print_type(TREE_TYPE(record_fields)).c_str()); + this->current_expression = error_mark_node; + } + CONSTRUCTOR_APPEND_ELT(tree_arguments, record_fields, this->current_expression); + record_fields = TREE_CHAIN(record_fields); + } + if (!is_void_type(record_fields)) + { + error_at(call_location, "too few arguments, expected %i, got %lu", + list_length(TYPE_FIELDS(symbol)), arguments.size()); + this->current_expression = error_mark_node; + } + else + { + this->current_expression = build_constructor(symbol, tree_arguments); + } + } + void generic_visitor::visit(boot::call_expression *expression) { tree symbol = this->lookup(expression->name()); @@ -56,37 +144,11 @@ namespace gcc } else if (DECL_P(symbol) && is_procedure_type(TREE_TYPE(symbol))) { - vec *arguments = nullptr; - - vec_alloc(arguments, expression->arguments().size()); - for (boot::expression *const argument : expression->arguments()) - { - argument->accept(this); - arguments->quick_push(this->current_expression); - } - tree stmt = build_call_expr_loc_vec(get_location(&expression->position()), symbol, arguments); - - if (TREE_TYPE(TREE_TYPE(symbol)) == void_type_node) - { - append_statement(stmt); - this->current_expression = NULL_TREE; - } - else - { - this->current_expression = stmt; - } + build_procedure_call(call_location, symbol, expression->arguments()); } else if (TYPE_P(symbol) && is_record_type(symbol)) { - vec *arguments = nullptr; - tree record_fields = TYPE_FIELDS(symbol); - for (boot::expression *const argument : expression->arguments()) - { - argument->accept(this); - CONSTRUCTOR_APPEND_ELT(arguments, record_fields, this->current_expression); - record_fields = TREE_CHAIN(record_fields); - } - this->current_expression = build_constructor(symbol, arguments); + build_record_call(call_location, symbol, expression->arguments()); } else { @@ -315,12 +377,12 @@ namespace gcc void generic_visitor::visit(boot::number_literal *literal) { - this->current_expression = build_int_cst(elna_int_type_node, literal->number()); + this->current_expression = build_int_cst(elna_int_type_node, literal->value); } void generic_visitor::visit(boot::number_literal *literal) { - this->current_expression = build_int_cstu(elna_word_type_node, literal->number()); + this->current_expression = build_int_cstu(elna_word_type_node, literal->value); } void generic_visitor::visit(boot::number_literal *literal) @@ -329,7 +391,7 @@ namespace gcc mpfr_t number; mpfr_init2(number, SIGNIFICAND_BITS); - mpfr_set_d(number, literal->number(), MPFR_RNDN); + mpfr_set_d(number, literal->value, MPFR_RNDN); real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN); @@ -340,12 +402,12 @@ namespace gcc void generic_visitor::visit(boot::number_literal *boolean) { - this->current_expression = boolean->number() ? boolean_true_node : boolean_false_node; + this->current_expression = boolean->value ? boolean_true_node : boolean_false_node; } void generic_visitor::visit(boot::number_literal *character) { - this->current_expression = build_int_cstu(elna_char_type_node, character->number()); + this->current_expression = build_int_cstu(elna_char_type_node, character->value); } void generic_visitor::visit(boot::number_literal *) @@ -355,10 +417,10 @@ namespace gcc void generic_visitor::visit(boot::number_literal *string) { - tree index_constant = build_int_cstu(elna_word_type_node, string->number().size()); + tree index_constant = build_int_cstu(elna_word_type_node, string->value.size()); tree string_type = build_array_type(elna_char_type_node, build_index_type(index_constant)); - tree string_literal = build_string(string->number().size(), string->number().c_str()); + tree string_literal = build_string(string->value.size(), string->value.c_str()); TREE_TYPE(string_literal) = string_type; TREE_CONSTANT(string_literal) = 1; TREE_READONLY(string_literal) = 1; @@ -390,11 +452,49 @@ namespace gcc expression, operator_code, left, right, elna_bool_type_node); } - tree generic_visitor::build_logic_operation(boot::binary_expression *expression, - tree_code operator_code, tree left, tree right) + tree generic_visitor::build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right) { - return build_binary_operation(TREE_TYPE(left) == elna_bool_type_node, - expression, operator_code, left, right, elna_bool_type_node); + location_t expression_location = get_location(&expression->position()); + tree left_type = TREE_TYPE(left); + tree right_type = TREE_TYPE(right); + tree_code logical_code, bit_code; + + if (expression->operation() == boot::binary_operator::conjunction) + { + bit_code = BIT_AND_EXPR; + logical_code = TRUTH_ANDIF_EXPR; + } + else if (expression->operation() == boot::binary_operator::disjunction) + { + bit_code = BIT_IOR_EXPR; + logical_code = TRUTH_ORIF_EXPR; + } + else if (expression->operation() == boot::binary_operator::exclusive_disjunction) + { + bit_code = BIT_XOR_EXPR; + logical_code = TRUTH_XOR_EXPR; + } + else + { + gcc_unreachable(); + } + + if (left_type == elna_bool_type_node) + { + return build2_loc(expression_location, logical_code, elna_bool_type_node, left, right); + } + else if (is_integral_type(left_type)) + { + return build2_loc(expression_location, bit_code, left_type, left, right); + } + else + { + error_at(expression_location, + "invalid operands of type '%s' and '%s' for operator %s", + print_type(left_type).c_str(), print_type(right_type).c_str(), + elna::boot::print_binary_operator(expression->operation())); + return error_mark_node; + } } tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right) @@ -475,7 +575,9 @@ namespace gcc } return; } - if (left_type != right_type && !are_compatible_pointers(left, right) && !are_compatible_pointers(right, left)) + if (left_type != right_type + && !are_compatible_pointers(left_type, right) + && !are_compatible_pointers(right_type, left)) { error_at(expression_location, "invalid operands of type %s and %s for operator %s", @@ -514,10 +616,13 @@ namespace gcc this->current_expression = build_comparison_operation(expression, GE_EXPR, left, right); break; case boot::binary_operator::conjunction: - this->current_expression = build_logic_operation(expression, TRUTH_ANDIF_EXPR, left, right); + this->current_expression = build_bit_logic_operation(expression, left, right); break; case boot::binary_operator::disjunction: - this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right); + this->current_expression = build_bit_logic_operation(expression, left, right); + break; + case boot::binary_operator::exclusive_disjunction: + this->current_expression = build_bit_logic_operation(expression, left, right); break; case boot::binary_operator::equals: this->current_expression = build_equality_operation(expression, left, right); @@ -531,23 +636,47 @@ namespace gcc void generic_visitor::visit(boot::unary_expression *expression) { expression->operand().accept(this); + location_t location = get_location(&expression->position()); switch (expression->operation()) { case boot::unary_operator::reference: TREE_ADDRESSABLE(this->current_expression) = 1; - this->current_expression = build_fold_addr_expr_with_type_loc(get_location(&expression->position()), + this->current_expression = build_fold_addr_expr_with_type_loc(location, this->current_expression, build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true)); TREE_NO_TRAMPOLINE(this->current_expression) = 1; break; case boot::unary_operator::negation: - this->current_expression = build1_loc(get_location(&expression->position()), TRUTH_NOT_EXPR, - boolean_type_node, this->current_expression); + if (TREE_TYPE(this->current_expression) == elna_bool_type_node) + { + this->current_expression = build1_loc(location, TRUTH_NOT_EXPR, + boolean_type_node, this->current_expression); + } + else if (is_integral_type(TREE_TYPE(this->current_expression))) + { + this->current_expression = build1_loc(location, BIT_NOT_EXPR, + TREE_TYPE(this->current_expression), this->current_expression); + } + else + { + error_at(location, "type '%s' cannot be negated", + print_type(TREE_TYPE(this->current_expression)).c_str()); + this->current_expression = error_mark_node; + } break; case boot::unary_operator::minus: - this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression), - this->current_expression); + if (is_integral_type(TREE_TYPE(this->current_expression))) + { + this->current_expression = fold_build1(NEGATE_EXPR, TREE_TYPE(this->current_expression), + this->current_expression); + } + else + { + error_at(location, "type '%s' cannot be negated", + print_type(TREE_TYPE(this->current_expression)).c_str()); + this->current_expression = error_mark_node; + } } } @@ -709,6 +838,10 @@ namespace gcc get_identifier(declaration->identifier.c_str()), declaration_type); bool result = this->symbol_map->enter(declaration->identifier, declaration_tree); + if (is_pointer_type(declaration_type)) + { + DECL_INITIAL(declaration_tree) = elna_pointer_nil_node; + } if (!result) { error_at(declaration_location, "variable '%s' already declared in this scope", @@ -848,8 +981,7 @@ namespace gcc this->current_expression = error_mark_node; return; } - if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue) - || are_compatible_pointers(lvalue, this->current_expression)) + if (is_assignable_from(TREE_TYPE(lvalue), this->current_expression)) { tree assignment = build2_loc(statement_location, MODIFY_EXPR, void_type_node, lvalue, this->current_expression); diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index a51b540..5e8476a 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -67,15 +67,21 @@ namespace gcc return TREE_CODE(type) == RECORD_TYPE; } - bool are_compatible_pointers(tree lhs, tree rhs) + bool are_compatible_pointers(tree lhs_type, tree rhs) { - tree lhs_type = TREE_TYPE(lhs); + gcc_assert(TYPE_P(lhs_type)); tree rhs_type = TREE_TYPE(rhs); return (is_pointer_type(lhs_type) && rhs == elna_pointer_nil_node) || (is_pointer_type(lhs_type) && lhs_type == rhs_type); } + bool is_assignable_from(tree assignee, tree assignment) + { + return TREE_TYPE(assignment) == assignee + || are_compatible_pointers(assignee, assignment); + } + void append_statement(tree statement_tree) { if (!vec_safe_is_empty(f_binding_level->defers)) diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 32072fe..49a6a53 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -41,7 +41,8 @@ namespace boot less_equal, greater_equal, disjunction, - conjunction + conjunction, + exclusive_disjunction }; enum class unary_operator @@ -662,11 +663,11 @@ namespace boot template class number_literal : public literal { - T m_value; - public: + T value; + number_literal(const struct position position, const T& value) - : literal(position), m_value(value) + : literal(position), value(value) { } @@ -674,11 +675,6 @@ namespace boot { visitor->visit(this); } - - const T& number() const - { - return m_value; - } }; class defer_statement : public statement diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 6bd2b4c..eea3f46 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -53,9 +53,12 @@ namespace gcc tree_code operator_code, tree left, tree right); tree build_comparison_operation(boot::binary_expression *expression, tree_code operator_code, tree left, tree right); - tree build_logic_operation(boot::binary_expression *expression, - tree_code operator_code, tree left, tree right); + tree build_bit_logic_operation(boot::binary_expression *expression, tree left, tree right); tree build_equality_operation(boot::binary_expression *expression, tree left, tree right); + void build_procedure_call(location_t call_location, + tree symbol, const std::vector& arguments); + void build_record_call(location_t call_location, + tree symbol, const std::vector& arguments); public: generic_visitor(std::shared_ptr> symbol_table); diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index d1970e9..45167a0 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -46,7 +46,14 @@ namespace gcc * \param rhs Right hand value. * \return Whether rhs can be assigned to lhs. */ - bool are_compatible_pointers(tree lhs, tree rhs); + bool are_compatible_pointers(tree lhs_type, tree rhs); + + /** + * \param assignee Assignee. + * \param assignee Assignment. + * \return Whether an expression assignment can be assigned to a variable of type assignee. + */ + bool is_assignable_from(tree assignee, tree assignment); void append_statement(tree statement_tree); void defer(tree statement_tree); diff --git a/source.elna b/source.elna index 51c6e9c..18c6172 100644 --- a/source.elna +++ b/source.elna @@ -63,46 +63,46 @@ const type Position* = record - line: Word; + line: Word column: Word end Location* = record - first: Position; + first: Position last: Position end SourceCode = record - position: Position; + position: Position text: String end TokenValue* = union - int_value: Int; - string_value: pointer to Char; - string: String; - boolean_value: Bool; + int_value: Int + string_value: pointer to Char + string: String + boolean_value: Bool char_value: Char end Token* = record - kind: Int; - value: TokenValue; + kind: Int + value: TokenValue location: Location end FILE* = record dummy: Int end CommandLine* = record - input: pointer to Char; - tokenize: Bool; + input: pointer to Char + tokenize: Bool syntax_tree: Bool end Literal* = record value: Int end ConstantDefinition* = record - name: pointer to Char; + name: pointer to Char body: pointer to Literal end ConstantPart* = record - elements: pointer to pointer to ConstantDefinition; + elements: pointer to pointer to ConstantDefinition count: Word end Program* = record @@ -148,12 +148,12 @@ end proc write_s(value: String); begin - write(0, value.ptr, value.length) + write(0, cast(value.ptr: pointer to Byte), cast(value.length: Int)) end proc write_z(value: pointer to Char); begin - write(0, value, strlen(value)) + write(0, cast(value: pointer to Byte), cast(strlen(value): Int)) end proc write_b(value: Bool); @@ -167,7 +167,7 @@ end proc write_c(value: Char); begin - write(0, @value, 1) + write(0, cast(@value: pointer to Byte), 1) end proc write_i(value: Int); @@ -184,7 +184,7 @@ begin digit := value % 10; value := value / 10; - buffer[n] := cast(cast('0' as Int) + digit as Char); + buffer[n] := cast(cast('0': Int) + digit: Char); n := n - 1u end; while n < 10u do @@ -195,17 +195,17 @@ end proc write_u(value: Word); begin - write_i(value) + write_i(cast(value: Int)) end proc is_digit(c: Char) -> Bool; begin - return cast(c as Int) >= cast('0' as Int) and cast(c as Int) <= cast('9' as Int) + return cast(c: Int) >= cast('0': Int) and cast(c: Int) <= cast('9': Int) end proc is_alpha(c: Char) -> Bool; begin - return cast(c as Int) >= cast('A' as Int) and cast(c as Int) <= cast('z' as Int) + return cast(c: Int) >= cast('A': Int) and cast(c: Int) <= cast('z': Int) end proc is_alnum(c: Char) -> Bool; @@ -232,7 +232,7 @@ proc string_dup(origin: String) -> String; var copy: pointer to Char; begin - copy := cast(malloc(origin.length) as pointer to Char); + copy := cast(malloc(origin.length): pointer to Char); strncpy(copy, origin.ptr, origin.length); return String(copy, origin.length) @@ -246,9 +246,7 @@ proc make_position() -> Position; var result: Position; begin - result.line := 1u; - result.column := 1u; - return result + return Position(1u, 1u) end proc read_source(filename: pointer to Char, result: pointer to String) -> Bool; @@ -274,12 +272,12 @@ begin end; rewind(input_file); - input := malloc(source_size); - if fread(input, source_size, 1, input_file) <> 1u then + input := malloc(cast(source_size: Word)); + if fread(input, cast(source_size: Word), 1u, input_file) <> 1u then return false end; - result^.length := cast(source_size as Word); - result^.ptr := cast(input as pointer to Char); + result^.length := cast(source_size: Word); + result^.ptr := cast(input: pointer to Char); return true end @@ -373,12 +371,12 @@ begin while source_code^.text.length > 1u do if source_code^.text[1u] = '*' and source_code^.text[2u] = ')' then source_code^ := advance_source(source_code^, 2u); - token_content^ := substring(token_content^, 0, content_length); + token_content^ := substring(token_content^, 0u, content_length); return true end; content_length := content_length + 1u; - source_code^ := advance_source(source_code^, 1) + source_code^ := advance_source(source_code^, 1u) end; return false @@ -413,8 +411,8 @@ begin if token_end^ <> '\"' then return input end; - token_length := cast(token_end - input as Word); - current_token^.value.string_value := cast(calloc(token_length, 1) as pointer to Char); + token_length := cast(token_end - input: Word); + current_token^.value.string_value := cast(calloc(token_length, 1u): pointer to Char); is_valid := true; constructed_string := current_token^.value.string_value; @@ -565,7 +563,7 @@ begin write_s("u>") elsif current_token^.kind = TOKEN_CHARACTER then write_c('<'); - write_i(current_token^.value.char_value); + write_i(cast(current_token^.value.char_value: Int)); write_s("c>") elsif current_token^.kind = TOKEN_STRING then write_s("\"...\"") @@ -671,7 +669,7 @@ begin source_code := skip_spaces(source_code); while source_code.text.length <> 0u do - tokens := cast(reallocarray(tokens, tokens_size^ + 1u, sizeof(Token)) as pointer to Token); + tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, sizeof(Token)): pointer to Token); current_token := tokens + tokens_size^; first_char := source_code.text[1u]; @@ -681,7 +679,7 @@ begin elsif is_digit(first_char) then token_end := nil; current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10); - token_length := cast(token_end - source_code.text.ptr as Word); + token_length := cast(token_end - source_code.text.ptr: Word); if token_end^ = 'u' then current_token^.kind := TOKEN_WORD; @@ -712,7 +710,7 @@ begin source_code := advance_source(source_code, 1u) elsif first_char = '\'' then token_end := lex_character(source_code.text.ptr + 1, current_token); - token_length := cast(token_end - source_code.text.ptr as Word); + token_length := cast(token_end - source_code.text.ptr: Word); if token_end^ = '\'' then current_token^.kind := TOKEN_CHARACTER; @@ -725,7 +723,7 @@ begin if token_end^ = '"' then current_token^.kind := TOKEN_STRING; - token_length := cast(token_end - source_code.text.ptr as Word); + token_length := cast(token_end - source_code.text.ptr: Word); source_code := advance_source(source_code, token_length + 1u) end elsif first_char = '[' then @@ -823,7 +821,7 @@ end proc parse_literal(tokens: pointer to pointer to Token, tokens_size: pointer to Word) -> pointer to Literal; begin - return cast(calloc(1, sizeof(Literal)) as pointer to Literal) + return cast(calloc(1u, sizeof(Literal)): pointer to Literal) end proc parse_constant_definition(tokens: pointer to pointer to Token, @@ -831,9 +829,9 @@ proc parse_constant_definition(tokens: pointer to pointer to Token, var result: pointer to ConstantDefinition; begin - result := cast(calloc(1, sizeof(ConstantDefinition)) as pointer to ConstantDefinition); + result := cast(calloc(1u, sizeof(ConstantDefinition)): pointer to ConstantDefinition); - result^.name := cast(malloc(strlen(tokens^^.value.string_value)) as pointer to Char); + result^.name := cast(malloc(strlen(tokens^^.value.string_value)): pointer to Char); strcpy(result^.name, tokens^^.value.string_value); tokens^ := tokens^ + 2u; @@ -855,7 +853,7 @@ var result: pointer to Program, current_constant: pointer to pointer to ConstantDefinition; begin - result := cast(calloc(1, sizeof(Program)) as pointer to Program); + result := cast(calloc(1u, sizeof(Program)): pointer to Program); result^.constants.elements := nil; result^.constants.count := 0u; @@ -866,8 +864,11 @@ begin while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do result^.constants.elements := cast( - reallocarray(result^.constants.elements, result^.constants.count + 1u, sizeof(pointer to ConstantDefinition)) - as pointer to pointer to ConstantDefinition); + reallocarray( + cast(result^.constants.elements: pointer to Byte), + result^.constants.count + 1u, + sizeof(pointer to ConstantDefinition) + ) : pointer to pointer to ConstantDefinition); current_constant := result^.constants.elements + result^.constants.count; result^.constants.count := result^.constants.count + 1u; @@ -887,7 +888,7 @@ var result: pointer to CommandLine; begin i := 1; - result := cast(malloc(sizeof(CommandLine)) as pointer to CommandLine); + result := cast(malloc(sizeof(CommandLine)): pointer to CommandLine); result^.tokenize := false; result^.syntax_tree := false; result^.input := nil; @@ -950,5 +951,5 @@ begin end begin - exit(process(count, parameters)) + exit(process(cast(count: Int), cast(parameters: pointer to pointer to Char))) end.