Use colon instead of as to cast

This commit is contained in:
Eugen Wissner 2025-02-14 08:05:03 +01:00
parent c564847c6b
commit ee4ebf64b9
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
10 changed files with 488 additions and 290 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

@ -61,7 +61,7 @@ namespace boot
expression->value().accept(this);
}
void empty_visitor::visit(size_of_expression *expression)
void empty_visitor::visit(type_expression *expression)
{
expression->body().accept(this);
}
@ -152,21 +152,21 @@ namespace boot
expression->operand().accept(this);
}
void empty_visitor::visit(basic_type_expression *)
void empty_visitor::visit(basic_type *)
{
}
void empty_visitor::visit(array_type_expression *expression)
void empty_visitor::visit(array_type *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(pointer_type_expression *expression)
void empty_visitor::visit(pointer_type *expression)
{
expression->base().accept(this);
}
void empty_visitor::visit(record_type_expression *expression)
void empty_visitor::visit(record_type *expression)
{
for (auto& field : expression->fields)
{
@ -174,7 +174,7 @@ namespace boot
}
}
void empty_visitor::visit(union_type_expression *expression)
void empty_visitor::visit(union_type *expression)
{
for (auto& field : expression->fields)
{
@ -250,115 +250,113 @@ namespace boot
{
}
type_expression::type_expression(const struct position position)
top_type::top_type(const struct position position)
: node(position)
{
}
basic_type_expression *type_expression::is_basic()
basic_type *top_type::is_basic()
{
return nullptr;
}
array_type_expression *type_expression::is_array()
array_type *top_type::is_array()
{
return nullptr;
}
record_type_expression *type_expression::is_record()
record_type *top_type::is_record()
{
return nullptr;
}
union_type_expression *type_expression::is_union()
union_type *top_type::is_union()
{
return nullptr;
}
pointer_type_expression *type_expression::is_pointer()
pointer_type *top_type::is_pointer()
{
return nullptr;
}
basic_type_expression::basic_type_expression(
const struct position position, const std::string& name)
: type_expression(position), m_name(name)
basic_type::basic_type(const struct position position, const std::string& name)
: top_type(position), m_name(name)
{
}
void basic_type_expression::accept(parser_visitor *visitor)
void basic_type::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
const std::string& basic_type_expression::base_name()
const std::string& basic_type::base_name()
{
return m_name;
}
basic_type_expression *basic_type_expression::is_basic()
basic_type *basic_type::is_basic()
{
return this;
}
array_type_expression::array_type_expression(const struct position position, type_expression *base,
array_type::array_type(const struct position position, top_type *base,
const std::uint32_t size)
: type_expression(position), m_base(base), size(size)
: top_type(position), m_base(base), size(size)
{
}
void array_type_expression::accept(parser_visitor *visitor)
void array_type::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
type_expression& array_type_expression::base()
top_type& array_type::base()
{
return *m_base;
}
array_type_expression *array_type_expression::is_array()
array_type*array_type::is_array()
{
return this;
}
array_type_expression::~array_type_expression()
array_type::~array_type()
{
delete m_base;
}
pointer_type_expression::pointer_type_expression(const struct position position, type_expression *base)
: type_expression(position), m_base(base)
pointer_type::pointer_type(const struct position position, top_type *base)
: top_type(position), m_base(base)
{
}
void pointer_type_expression::accept(parser_visitor *visitor)
void pointer_type::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
type_expression& pointer_type_expression::base()
top_type& pointer_type::base()
{
return *m_base;
}
pointer_type_expression *pointer_type_expression::is_pointer()
pointer_type *pointer_type::is_pointer()
{
return this;
}
pointer_type_expression::~pointer_type_expression()
pointer_type::~pointer_type()
{
delete m_base;
}
composite_type_expression::composite_type_expression(const struct position position,
fields_t&& fields)
: type_expression(position), fields(std::move(fields))
composite_type::composite_type(const struct position position, fields_t&& fields)
: top_type(position), fields(std::move(fields))
{
}
composite_type_expression::~composite_type_expression()
composite_type::~composite_type()
{
for (auto& field_declaration : fields)
{
@ -366,40 +364,38 @@ namespace boot
}
}
record_type_expression::record_type_expression(const struct position position,
fields_t&& fields)
: composite_type_expression(position, std::move(fields))
record_type::record_type(const struct position position, fields_t&& fields)
: composite_type(position, std::move(fields))
{
}
void record_type_expression::accept(parser_visitor *visitor)
void record_type::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
record_type_expression *record_type_expression::is_record()
record_type *record_type::is_record()
{
return this;
}
union_type_expression::union_type_expression(const struct position position,
fields_t&& fields)
: composite_type_expression(position, std::move(fields))
union_type::union_type(const struct position position, fields_t&& fields)
: composite_type(position, std::move(fields))
{
}
union_type_expression *union_type_expression::is_union()
union_type *union_type::is_union()
{
return this;
}
void union_type_expression::accept(parser_visitor *visitor)
void union_type::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
variable_declaration::variable_declaration(const struct position position, const std::string& identifier,
const bool exported, type_expression *type)
const bool exported, top_type *type)
: definition(position, identifier, exported), m_type(type)
{
}
@ -414,7 +410,7 @@ namespace boot
visitor->visit(this);
}
type_expression& variable_declaration::type()
top_type& variable_declaration::variable_type()
{
return *m_type;
}
@ -446,7 +442,7 @@ namespace boot
}
procedure_definition::procedure_definition(const struct position position, const std::string& identifier,
const bool exported, type_expression *return_type)
const bool exported, top_type *return_type)
: definition(position, identifier, exported), m_return_type(return_type)
{
}
@ -467,7 +463,7 @@ namespace boot
return this;
}
type_expression *procedure_definition::return_type()
top_type *procedure_definition::return_type()
{
return m_return_type;
}
@ -485,7 +481,7 @@ namespace boot
}
type_definition::type_definition(const struct position position, const std::string& identifier,
const bool exported, type_expression *body)
const bool exported, top_type *body)
: definition(position, identifier, exported), m_body(body)
{
}
@ -495,7 +491,7 @@ namespace boot
visitor->visit(this);
}
type_expression& type_definition::body()
top_type& type_definition::body()
{
return *m_body;
}
@ -776,7 +772,7 @@ namespace boot
}
}
cast_expression::cast_expression(const struct position position, type_expression *target, expression *value)
cast_expression::cast_expression(const struct position position, top_type *target, expression *value)
: expression(position), m_target(target), m_value(value)
{
}
@ -786,7 +782,7 @@ namespace boot
visitor->visit(this);
}
type_expression& cast_expression::target()
top_type& cast_expression::target()
{
return *m_target;
}
@ -802,22 +798,22 @@ namespace boot
delete m_value;
}
size_of_expression::size_of_expression(const struct position position, type_expression *body)
type_expression::type_expression(const struct position position, top_type *body)
: expression(position), m_body(body)
{
}
void size_of_expression::accept(parser_visitor *visitor)
void type_expression::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
type_expression& size_of_expression::body()
top_type& type_expression::body()
{
return *m_body;
}
size_of_expression::~size_of_expression()
type_expression::~type_expression()
{
delete m_body;
}
@ -1014,6 +1010,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
@ -101,7 +101,7 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::variable_declaration *> variable_declaration;
%type <std::vector<elna::boot::variable_declaration *>> variable_declarations variable_part
formal_parameter_list;
%type <elna::boot::type_expression *> type_expression;
%type <elna::boot::top_type *> type_expression;
%type <elna::boot::expression *> expression operand unary;
%type <std::vector<elna::boot::expression *>> expressions actual_parameter_list;
%type <elna::boot::designator_expression *> designator_expression;
@ -117,8 +117,8 @@ along with GCC; see the file COPYING3. If not see
%type <elna::boot::type_definition *> type_definition;
%type <std::vector<elna::boot::type_definition *>> type_definitions type_part;
%type <elna::boot::block *> block;
%type <std::pair<std::string, elna::boot::type_expression *>> field_declaration;
%type <std::vector<std::pair<std::string, elna::boot::type_expression *>>> field_list;
%type <std::pair<std::string, elna::boot::top_type *>> field_declaration;
%type <std::vector<std::pair<std::string, elna::boot::top_type *>>> field_list;
%type <std::vector<elna::boot::conditional_statements *>> elsif_statement_list;
%type <elna::boot::cast_expression *> cast_expression;
%type <elna::boot::defer_statement *> defer_statement;
@ -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);
}
@ -265,9 +265,9 @@ literal:
operand:
literal { $$ = $1; }
| designator_expression { $$ = $1; }
| SIZEOF LEFT_PAREN type_expression RIGHT_PAREN
| LEFT_PAREN type_expression RIGHT_PAREN
{
$$ = new elna::boot::size_of_expression(elna::boot::make_position(@1), $3);
$$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2);
}
| cast_expression { $$ = $1; }
| call_expression { $$ = $1; }
@ -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,32 +408,32 @@ 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); }
type_expression:
ARRAY INTEGER OF type_expression
{
$$ = new elna::boot::array_type_expression(elna::boot::make_position(@1), $4, $2);
$$ = new elna::boot::array_type(elna::boot::make_position(@1), $4, $2);
}
| POINTER TO type_expression
{
$$ = new elna::boot::pointer_type_expression(elna::boot::make_position(@1), $3);
$$ = new elna::boot::pointer_type(elna::boot::make_position(@1), $3);
}
| RECORD field_list END_BLOCK
{
$$ = new elna::boot::record_type_expression(elna::boot::make_position(@1), std::move($2));
$$ = new elna::boot::record_type(elna::boot::make_position(@1), std::move($2));
}
| UNION field_list END_BLOCK
{
$$ = new elna::boot::union_type_expression(elna::boot::make_position(@1), std::move($2));
$$ = new elna::boot::union_type(elna::boot::make_position(@1), std::move($2));
}
| IDENTIFIER
{
$$ = new elna::boot::basic_type_expression(elna::boot::make_position(@1), $1);
$$ = new elna::boot::basic_type(elna::boot::make_position(@1), $1);
}
variable_declaration: identifier_definition COLON type_expression
{

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))
else if (TYPE_P(symbol) && TREE_CODE(symbol) == RECORD_TYPE)
{
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
{
@ -107,11 +169,9 @@ namespace gcc
cast_target, this->current_expression);
}
void generic_visitor::visit(boot::size_of_expression *expression)
void generic_visitor::visit(boot::type_expression *expression)
{
auto body_type = build_type(expression->body());
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(body_type));
this->current_expression = build_type(expression->body());
}
void generic_visitor::visit(boot::program *program)
@ -185,7 +245,7 @@ namespace gcc
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
{
parameter_types[i] = build_type(definition->parameters.at(i)->type());
parameter_types[i] = build_type(definition->parameters.at(i)->variable_type());
}
tree return_type = definition->return_type() == nullptr
? void_type_node
@ -315,12 +375,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 +389,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 +400,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 +415,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 +450,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 +573,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 +614,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 +634,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;
}
}
}
@ -603,9 +730,9 @@ namespace gcc
}
}
tree generic_visitor::build_type(boot::type_expression& type)
tree generic_visitor::build_type(boot::top_type& type)
{
if (boot::basic_type_expression *basic_type = type.is_basic())
if (boot::basic_type *basic_type = type.is_basic())
{
tree symbol = this->lookup(basic_type->base_name());
@ -618,7 +745,7 @@ namespace gcc
return error_mark_node;
}
else if (boot::array_type_expression *array_type = type.is_array())
else if (boot::array_type *array_type = type.is_array())
{
tree lower_bound = build_int_cst_type(integer_type_node, 0);
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
@ -632,7 +759,7 @@ namespace gcc
return build_array_type(base_type, range_type);
}
else if (boot::pointer_type_expression *pointer_type = type.is_pointer())
else if (boot::pointer_type *pointer_type = type.is_pointer())
{
tree base_type = build_type(pointer_type->base());
@ -642,7 +769,7 @@ namespace gcc
}
return build_pointer_type_for_mode(base_type, VOIDmode, true);
}
else if (boot::record_type_expression *record_type = type.is_record())
else if (boot::record_type *record_type = type.is_record())
{
std::set<std::string> field_names;
tree record_type_node = make_node(RECORD_TYPE);
@ -669,7 +796,7 @@ namespace gcc
return record_type_node;
}
else if (boot::union_type_expression *union_type = type.is_union())
else if (boot::union_type *union_type = type.is_union())
{
std::set<std::string> field_names;
tree union_type_node = make_node(UNION_TYPE);
@ -701,7 +828,7 @@ namespace gcc
void generic_visitor::visit(boot::variable_declaration *declaration)
{
tree declaration_type = build_type(declaration->type());
tree declaration_type = build_type(declaration->variable_type());
gcc_assert(declaration_type != NULL_TREE);
location_t declaration_location = get_location(&declaration->position());
@ -709,6 +836,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",
@ -795,32 +926,56 @@ namespace gcc
void generic_visitor::visit(boot::field_access_expression *expression)
{
expression->base().accept(this);
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
while (field_declaration != NULL_TREE)
{
tree declaration_name = DECL_NAME(field_declaration);
const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
if (expression->field() == identifier_pointer)
{
break;
}
field_declaration = TREE_CHAIN(field_declaration);
}
location_t expression_location = get_location(&expression->position());
if (field_declaration == NULL_TREE)
if (TYPE_P(this->current_expression))
{
error_at(expression_location,
"record type does not have a field named '%s'",
expression->field().c_str());
this->current_expression = error_mark_node;
if (expression->field() == "size")
{
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node,
size_in_bytes(this->current_expression));
}
else if (expression->field() == "alignment")
{
this->current_expression = build_int_cstu(elna_word_type_node,
TYPE_ALIGN_UNIT(this->current_expression));
}
else
{
error_at(expression_location, "type '%s' does not have property '%s'",
print_type(this->current_expression).c_str(), expression->field().c_str());
this->current_expression = error_mark_node;
}
}
else
else if (is_aggregate_type(TREE_TYPE(this->current_expression)))
{
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
TREE_TYPE(field_declaration), this->current_expression,
field_declaration, NULL_TREE);
tree field_declaration = TYPE_FIELDS(TREE_TYPE(this->current_expression));
while (field_declaration != NULL_TREE)
{
tree declaration_name = DECL_NAME(field_declaration);
const char *identifier_pointer = IDENTIFIER_POINTER(declaration_name);
if (expression->field() == identifier_pointer)
{
break;
}
field_declaration = TREE_CHAIN(field_declaration);
}
if (field_declaration == NULL_TREE)
{
error_at(expression_location,
"record type does not have a field named '%s'",
expression->field().c_str());
this->current_expression = error_mark_node;
}
else
{
this->current_expression = build3_loc(expression_location, COMPONENT_REF,
TREE_TYPE(field_declaration), this->current_expression,
field_declaration, NULL_TREE);
}
}
}
@ -848,8 +1003,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

@ -62,20 +62,27 @@ namespace gcc
return type == NULL_TREE || type == void_type_node;
}
bool is_record_type(tree type)
bool is_aggregate_type(tree type)
{
return TREE_CODE(type) == RECORD_TYPE;
gcc_assert(TYPE_P(type));
return TREE_CODE(type) == RECORD_TYPE || TREE_CODE(type) == UNION_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
@ -57,7 +58,7 @@ namespace boot
class type_definition;
class call_expression;
class cast_expression;
class size_of_expression;
class type_expression;
class assign_statement;
class if_statement;
class while_statement;
@ -67,11 +68,11 @@ namespace boot
class program;
class binary_expression;
class unary_expression;
class basic_type_expression;
class array_type_expression;
class pointer_type_expression;
class record_type_expression;
class union_type_expression;
class basic_type;
class array_type;
class pointer_type;
class record_type;
class union_type;
class variable_expression;
class array_access_expression;
class field_access_expression;
@ -91,7 +92,7 @@ namespace boot
virtual void visit(type_definition *) = 0;
virtual void visit(call_expression *) = 0;
virtual void visit(cast_expression *) = 0;
virtual void visit(size_of_expression *) = 0;
virtual void visit(type_expression *) = 0;
virtual void visit(call_statement *) = 0;
virtual void visit(assign_statement *) = 0;
virtual void visit(if_statement *) = 0;
@ -102,11 +103,11 @@ namespace boot
virtual void visit(program *) = 0;
virtual void visit(binary_expression *) = 0;
virtual void visit(unary_expression *) = 0;
virtual void visit(basic_type_expression *) = 0;
virtual void visit(array_type_expression *) = 0;
virtual void visit(pointer_type_expression *) = 0;
virtual void visit(record_type_expression *) = 0;
virtual void visit(union_type_expression *) = 0;
virtual void visit(basic_type *) = 0;
virtual void visit(array_type *) = 0;
virtual void visit(pointer_type *) = 0;
virtual void visit(record_type *) = 0;
virtual void visit(union_type *) = 0;
virtual void visit(variable_expression *) = 0;
virtual void visit(array_access_expression *) = 0;
virtual void visit(field_access_expression *is_field_access) = 0;
@ -131,7 +132,7 @@ namespace boot
virtual void visit(type_definition *definition) override;
virtual void visit(call_expression *expression) override;
virtual void visit(cast_expression *expression) override;
virtual void visit(size_of_expression *expression) override;
virtual void visit(type_expression *expression) override;
virtual void visit(call_statement *statement) override;
virtual void visit(assign_statement *statement) override;
virtual void visit(if_statement *) override;
@ -142,11 +143,11 @@ namespace boot
virtual void visit(program *program) override;
virtual void visit(binary_expression *expression) override;
virtual void visit(unary_expression *expression) override;
virtual void visit(basic_type_expression *) override;
virtual void visit(array_type_expression *expression) override;
virtual void visit(pointer_type_expression *) override;
virtual void visit(record_type_expression *expression) override;
virtual void visit(union_type_expression *expression) override;
virtual void visit(basic_type *) override;
virtual void visit(array_type *expression) override;
virtual void visit(pointer_type *) override;
virtual void visit(record_type *expression) override;
virtual void visit(union_type *expression) override;
virtual void visit(variable_expression *) override;
virtual void visit(array_access_expression *expression) override;
virtual void visit(field_access_expression *expression) override;
@ -217,23 +218,23 @@ namespace boot
/**
* Some type expression.
*/
class type_expression : public node
class top_type : public node
{
public:
virtual basic_type_expression *is_basic();
virtual array_type_expression *is_array();
virtual pointer_type_expression *is_pointer();
virtual record_type_expression *is_record();
virtual union_type_expression *is_union();
virtual basic_type *is_basic();
virtual array_type *is_array();
virtual pointer_type *is_pointer();
virtual record_type *is_record();
virtual union_type *is_union();
protected:
type_expression(const struct position position);
top_type(const struct position position);
};
/**
* Expression defining a basic type.
*/
class basic_type_expression final : public type_expression
class basic_type : public top_type
{
const std::string m_name;
@ -242,76 +243,76 @@ namespace boot
* \param position Source code position.
* \param name Type name.
*/
basic_type_expression(const struct position position, const std::string& name);
basic_type(const struct position position, const std::string& name);
virtual void accept(parser_visitor *visitor) override;
const std::string& base_name();
basic_type_expression *is_basic() override;
basic_type *is_basic() override;
};
class array_type_expression final : public type_expression
class array_type : public top_type
{
type_expression *m_base;
top_type *m_base;
public:
const std::uint32_t size;
array_type_expression(const struct position position, type_expression *base, const std::uint32_t size);
array_type(const struct position position, top_type*base, const std::uint32_t size);
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
top_type& base();
array_type_expression *is_array() override;
array_type *is_array() override;
virtual ~array_type_expression() override;
virtual ~array_type() override;
};
class pointer_type_expression final : public type_expression
class pointer_type : public top_type
{
type_expression *m_base;
top_type *m_base;
public:
pointer_type_expression(const struct position position, type_expression *base);
pointer_type(const struct position position, top_type *base);
virtual void accept(parser_visitor *visitor) override;
type_expression& base();
top_type& base();
pointer_type_expression *is_pointer() override;
pointer_type *is_pointer() override;
virtual ~pointer_type_expression() override;
virtual ~pointer_type() override;
};
using field_t = std::pair<std::string, type_expression *>;
using field_t = std::pair<std::string, top_type *>;
using fields_t = std::vector<field_t>;
class composite_type_expression : public type_expression
class composite_type : public top_type
{
protected:
composite_type_expression(const struct position position, fields_t&& fields);
composite_type(const struct position position, fields_t&& fields);
public:
fields_t fields;
virtual ~composite_type_expression() override;
virtual ~composite_type() override;
};
class record_type_expression final : public composite_type_expression
class record_type : public composite_type
{
public:
record_type_expression(const struct position position, fields_t&& fields);
record_type(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
record_type_expression *is_record() override;
record_type *is_record() override;
};
class union_type_expression final : public composite_type_expression
class union_type : public composite_type
{
public:
union_type_expression(const struct position position, fields_t&& fields);
union_type(const struct position position, fields_t&& fields);
virtual void accept(parser_visitor *visitor) override;
union_type_expression *is_union() override;
union_type *is_union() override;
};
/**
@ -319,14 +320,14 @@ namespace boot
*/
class variable_declaration : public definition
{
type_expression *m_type;
top_type *m_type;
public:
variable_declaration(const struct position position, const std::string& identifier,
const bool exported, type_expression *type);
const bool exported, top_type *type);
virtual void accept(parser_visitor *visitor) override;
type_expression& type();
top_type& variable_type();
virtual ~variable_declaration() override;
};
@ -367,17 +368,17 @@ namespace boot
*/
class procedure_definition : public definition
{
type_expression *m_return_type{ nullptr };
top_type *m_return_type{ nullptr };
block *m_body{ nullptr };
public:
std::vector<variable_declaration *> parameters;
procedure_definition(const struct position position, const std::string& identifier,
const bool exported, type_expression *return_type = nullptr);
const bool exported, top_type *return_type = nullptr);
virtual void accept(parser_visitor *visitor) override;
type_expression *return_type();
top_type *return_type();
block *body();
procedure_definition *add_body(block *procedure_body);
@ -390,14 +391,14 @@ namespace boot
*/
class type_definition : public definition
{
type_expression *m_body;
top_type *m_body;
public:
type_definition(const struct position position, const std::string& identifier,
const bool exported, type_expression *expression);
const bool exported, top_type *expression);
virtual void accept(parser_visitor *visitor) override;
type_expression& body();
top_type& body();
virtual ~type_definition() override;
};
@ -429,33 +430,33 @@ namespace boot
*/
class cast_expression : public expression
{
type_expression *m_target;
top_type *m_target;
expression *m_value;
public:
cast_expression(const struct position position, type_expression *target, expression *value);
cast_expression(const struct position position, top_type *target, expression *value);
virtual void accept(parser_visitor *visitor) override;
type_expression& target();
top_type& target();
expression& value();
virtual ~cast_expression() override;
};
/**
* sizeOf operator.
* Type inside an expression.
*/
class size_of_expression : public expression
class type_expression : public expression
{
type_expression *m_body;
top_type *m_body;
public:
size_of_expression(const struct position position, type_expression *body);
type_expression(const struct position position, top_type *body);
virtual void accept(parser_visitor *visitor) override;
type_expression& body();
top_type& body();
virtual ~size_of_expression() override;
virtual ~type_expression() override;
};
class call_statement : public statement
@ -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

@ -40,7 +40,7 @@ namespace gcc
std::shared_ptr<boot::symbol_table<tree>> symbol_map;
tree build_label_decl(const char *name, location_t loc);
tree build_type(boot::type_expression& type);
tree build_type(boot::top_type& type);
void enter_scope();
tree leave_scope();
@ -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);
@ -64,7 +67,7 @@ namespace gcc
void visit(boot::procedure_definition *definition) override;
void visit(boot::call_expression *expression) override;
void visit(boot::cast_expression *expression) override;
void visit(boot::size_of_expression *expression) override;
void visit(boot::type_expression *expression) override;
void visit(boot::number_literal<std::int32_t> *literal) override;
void visit(boot::number_literal<std::uint32_t> *literal) override;
void visit(boot::number_literal<double> *literal) override;

View File

@ -39,14 +39,26 @@ namespace gcc
bool is_array_type(tree type);
bool is_procedure_type(tree type);
bool is_void_type(tree type);
bool is_record_type(tree type);
/**
* \param type The type to evaluate.
* \return Whether the given type is record or union.
*/
bool is_aggregate_type(tree type);
/**
* \param lhs Left hand value.
* \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, Token.size): 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, Literal.size): 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, ConstantDefinition.size): 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, Program.size): 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,
(pointer to ConstantDefinition).size
) : 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(CommandLine.size): 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.