Implement pointers

This commit is contained in:
2025-01-10 23:17:18 +01:00
parent 954425f4bd
commit 35c32fcf3f
15 changed files with 131 additions and 915 deletions

View File

@ -30,7 +30,6 @@ elna_OBJS = \
elna/lexer.o \
elna/parser.o \
elna/result.o \
elna/symbol_table.o \
elna/types.o \
$(END)

View File

@ -36,6 +36,10 @@ namespace gcc
{
return "String";
}
else if (is_pointer_type(type))
{
return "pointer";
}
else if (is_array_type(type))
{
return "array";

View File

@ -51,6 +51,10 @@ namespace gcc
{
format_number = "%s\n";
}
else if (is_pointer_type(argument_type))
{
format_number = "%p\n";
}
else
{
error_at(get_location(&argument->position()),
@ -256,6 +260,20 @@ namespace gcc
operator_code, target_type, left, right);
}
void generic_visitor::visit(source::unary_expression *expression)
{
switch (expression->operation())
{
case source::unary_operator::reference:
expression->operand().accept(this);
this->current_expression = build1_loc(get_location(&expression->position()), ADDR_EXPR,
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true),
this->current_expression);
break;
}
}
void generic_visitor::visit(source::constant_definition *definition)
{
location_t definition_location = get_location(&definition->position());
@ -344,6 +362,10 @@ namespace gcc
{
return TREE_TYPE(symbol->second);
}
error_at(get_location(&basic_type->position()),
"type '%s' not declared", basic_type->base_name().c_str());
return error_mark_node;
}
else if (source::array_type_expression *array_type = type.is_array())
{
@ -351,14 +373,24 @@ namespace gcc
tree upper_bound = build_int_cst_type(integer_type_node, array_type->size);
tree base_type = build_type(array_type->base());
if (base_type == NULL_TREE)
if (base_type == NULL_TREE || base_type == error_mark_node)
{
return NULL_TREE;
return base_type;
}
tree range_type = build_range_type(integer_type_node, lower_bound, upper_bound);
return build_array_type(base_type, range_type);
}
else if (source::pointer_type_expression *pointer_type = type.is_pointer())
{
tree base_type = build_type(pointer_type->base());
if (base_type == NULL_TREE || base_type == error_mark_node)
{
return base_type;
}
return build_pointer_type_for_mode(base_type, VOIDmode, true);
}
else if (source::record_type_expression *record_type = type.is_record())
{
std::set<std::string> field_names;
@ -397,13 +429,8 @@ namespace gcc
void generic_visitor::visit(source::declaration *declaration)
{
tree declaration_type = build_type(declaration->type());
gcc_assert(declaration_type != NULL_TREE);
if (declaration_type == NULL_TREE)
{
error_at(get_location(&declaration->type().position()),
"type '%s' not declared", declaration->type().base_name().c_str());
return;
}
auto declaration_location = get_location(&declaration->position());
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
get_identifier(declaration->identifier().c_str()), declaration_type);
@ -455,6 +482,46 @@ namespace gcc
ARRAY_REF, element_type, designator, index, NULL_TREE, NULL_TREE);
}
void generic_visitor::visit(source::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)
{
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);
}
}
void generic_visitor::visit(source::dereference_expression *expression)
{
expression->base().accept(this);
this->current_expression = build1_loc(get_location(&expression->position()), INDIRECT_REF,
TREE_TYPE(TREE_TYPE(this->current_expression)), this->current_expression);
}
void generic_visitor::visit(source::assign_statement *statement)
{
statement->lvalue().accept(this);

View File

@ -16,10 +16,15 @@ namespace gcc
TYPE_STRING_FLAG(elna_char_type_node) = 1;
}
bool is_string_type(tree type)
bool is_pointer_type(tree type)
{
gcc_assert(TYPE_P(type));
return TREE_CODE(type) == POINTER_TYPE
return TREE_CODE(type) == POINTER_TYPE;
}
bool is_string_type(tree type)
{
return is_pointer_type(type)
&& TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node;
}