Compare commits

1 Commits

Author SHA1 Message Date
ec0b4be1f7 Use colon instead of as to cast 2025-02-14 19:56:46 +01:00
10 changed files with 290 additions and 116 deletions

View File

@ -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`.

View File

@ -1014,6 +1014,8 @@ namespace boot
return "and";
case binary_operator::disjunction:
return "or";
case binary_operator::exclusive_disjunction:
return "xor";
}
__builtin_unreachable();
};

View File

@ -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);
}

View File

@ -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); }

View File

@ -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<boot::expression *>& arguments)
{
vec<tree, va_gc> *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<boot::expression *>& arguments)
{
vec<constructor_elt, va_gc> *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<tree, va_gc> *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<constructor_elt, va_gc> *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<std::int32_t> *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<std::uint32_t> *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<double> *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<bool> *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<unsigned char> *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<nullptr_t> *)
@ -355,10 +417,10 @@ namespace gcc
void generic_visitor::visit(boot::number_literal<std::string> *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);

View File

@ -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))

View File

@ -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<typename T>
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

View File

@ -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<boot::expression *>& arguments);
void build_record_call(location_t call_location,
tree symbol, const std::vector<boot::expression *>& arguments);
public:
generic_visitor(std::shared_ptr<boot::symbol_table<tree>> symbol_table);

View File

@ -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);

View File

@ -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.