Implement string comparison
This commit is contained in:
parent
33aca4cc07
commit
cd949c4be7
@ -39,7 +39,6 @@ gelna$(exeext): $(ELNA_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
|
||||
elna_OBJS = \
|
||||
elna/elna1.o \
|
||||
elna/elna-generic.o \
|
||||
elna/elna-convert.o \
|
||||
elna/elna-diagnostic.o \
|
||||
elna/elna-tree.o \
|
||||
elna/elna-builtins.o \
|
||||
|
@ -1,3 +1,20 @@
|
||||
/* Builtin definitions.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "elna/gcc/elna-builtins.h"
|
||||
#include "elna/gcc/elna1.h"
|
||||
#include "stor-layout.h"
|
||||
@ -18,13 +35,15 @@ namespace gcc
|
||||
elna_float_type_node = double_type_node;
|
||||
|
||||
elna_string_type_node = make_node(RECORD_TYPE);
|
||||
tree_chain record_chain;
|
||||
tree string_ptr_type = build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true);
|
||||
tree record_chain = NULL_TREE;
|
||||
|
||||
record_chain.append(build_field(UNKNOWN_LOCATION, elna_string_type_node, "length", elna_word_type_node));
|
||||
record_chain.append(build_field(UNKNOWN_LOCATION, elna_string_type_node, "ptr",
|
||||
build_pointer_type_for_mode(elna_char_type_node, VOIDmode, true)));
|
||||
record_chain = chainon(record_chain,
|
||||
build_field(UNKNOWN_LOCATION, elna_string_type_node, "length", elna_word_type_node));
|
||||
record_chain = chainon(record_chain,
|
||||
build_field(UNKNOWN_LOCATION, elna_string_type_node, "ptr", string_ptr_type));
|
||||
|
||||
TYPE_FIELDS(elna_string_type_node) = record_chain.head();
|
||||
TYPE_FIELDS(elna_string_type_node) = record_chain;
|
||||
layout_type(elna_string_type_node);
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* Data type conversion routines.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
#include "fold-const.h"
|
||||
#include "convert.h"
|
||||
|
||||
/* Creates an expression whose value is that of EXPR, converted to type TYPE.
|
||||
This function implements all reasonable scalar conversions. */
|
||||
|
||||
tree convert(tree /* type */, tree expr)
|
||||
{
|
||||
return expr;
|
||||
}
|
@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "stor-layout.h"
|
||||
#include "varasm.h"
|
||||
#include "fold-const.h"
|
||||
#include "langhooks.h"
|
||||
#include <set>
|
||||
|
||||
namespace elna
|
||||
@ -69,7 +70,7 @@ namespace gcc
|
||||
|
||||
if (return_type == void_type_node)
|
||||
{
|
||||
this->scope.front().append_statement(stmt);
|
||||
append_statement(stmt);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
@ -96,11 +97,6 @@ namespace gcc
|
||||
this->current_expression = build1(CONVERT_EXPR, elna_word_type_node, size_in_bytes(body_type));
|
||||
}
|
||||
|
||||
bool generic_visitor::is_numeric_type(tree type)
|
||||
{
|
||||
return is_integral_type(type) || type == elna_float_type_node;
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::program *program)
|
||||
{
|
||||
for (boot::constant_definition *const constant : program->constants)
|
||||
@ -119,11 +115,8 @@ namespace gcc
|
||||
{
|
||||
procedure->accept(this);
|
||||
}
|
||||
std::array<tree, 2> parameter_types{
|
||||
integer_type_node,
|
||||
build_pointer_type(build_pointer_type(char_type_node))
|
||||
};
|
||||
tree declaration_type = build_function_type_array(integer_type_node, 2, parameter_types.data());
|
||||
tree declaration_type = build_function_type_list(integer_type_node, integer_type_node,
|
||||
build_pointer_type(build_pointer_type(char_type_node)), NULL_TREE);
|
||||
tree fndecl = build_fn_decl("main", declaration_type);
|
||||
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
||||
@ -132,23 +125,21 @@ namespace gcc
|
||||
|
||||
push_struct_function(fndecl, false);
|
||||
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
|
||||
DECL_STRUCT_FUNCTION(fndecl)->language->binding_level = ggc_cleared_alloc<binding_level>();
|
||||
|
||||
enter_scope();
|
||||
|
||||
tree_chain argument_chain;
|
||||
for (std::size_t i = 0; i < 2; ++i)
|
||||
tree parameter_type = TYPE_ARG_TYPES(declaration_type);
|
||||
for (const char *argument_name : std::array<const char *, 2>{ "count", "parameters" })
|
||||
{
|
||||
std::string argument_name = i == 0 ? "count" : "parameters";
|
||||
tree argc_declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
|
||||
get_identifier(argument_name.c_str()), parameter_types[i]);
|
||||
DECL_CONTEXT(argc_declaration_tree) = fndecl;
|
||||
DECL_ARG_TYPE(argc_declaration_tree) = parameter_types[i];
|
||||
tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
|
||||
get_identifier(argument_name), TREE_VALUE(parameter_type));
|
||||
DECL_CONTEXT(declaration_tree) = fndecl;
|
||||
DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
|
||||
|
||||
argument_chain.append(argc_declaration_tree);
|
||||
this->symbol_map->enter(argument_name, declaration_tree);
|
||||
DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
|
||||
parameter_type = TREE_CHAIN(parameter_type);
|
||||
}
|
||||
DECL_ARGUMENTS(fndecl) = argument_chain.head();
|
||||
|
||||
for (boot::statement *const body_statement : program->body)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
@ -156,12 +147,12 @@ namespace gcc
|
||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
|
||||
build_int_cst_type(integer_type_node, 0));
|
||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||
this->scope.front().append_statement(return_stmt);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
append_statement(return_stmt);
|
||||
tree mapping = leave_scope();
|
||||
|
||||
BLOCK_SUPERCONTEXT(mapping.block()) = fndecl;
|
||||
DECL_INITIAL(fndecl) = mapping.block();
|
||||
DECL_SAVED_TREE(fndecl) = mapping.bind_expression();
|
||||
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
|
||||
DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
|
||||
DECL_SAVED_TREE(fndecl) = mapping;
|
||||
|
||||
DECL_EXTERNAL(fndecl) = 0;
|
||||
DECL_PRESERVE_P(fndecl) = 1;
|
||||
@ -189,14 +180,16 @@ namespace gcc
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
current_function_decl = fndecl;
|
||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, return_type);
|
||||
DECL_CONTEXT(resdecl) = fndecl;
|
||||
DECL_RESULT(fndecl) = resdecl;
|
||||
|
||||
push_struct_function(fndecl, false);
|
||||
DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
|
||||
|
||||
enter_scope();
|
||||
}
|
||||
tree_chain argument_chain;
|
||||
tree argument_chain = NULL_TREE;
|
||||
for (std::size_t i = 0; i < definition->parameters.size(); ++i)
|
||||
{
|
||||
auto parameter = definition->parameters.at(i);
|
||||
@ -210,24 +203,24 @@ namespace gcc
|
||||
{
|
||||
this->symbol_map->enter(parameter->identifier, declaration_tree);
|
||||
}
|
||||
argument_chain.append(declaration_tree);
|
||||
argument_chain = chainon(argument_chain, declaration_tree);
|
||||
}
|
||||
DECL_ARGUMENTS(fndecl) = argument_chain.head();
|
||||
DECL_ARGUMENTS(fndecl) = argument_chain;
|
||||
TREE_PUBLIC(fndecl) = definition->exported;
|
||||
|
||||
if (definition->body() != nullptr)
|
||||
{
|
||||
definition->body()->accept(this);
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
tree mapping = leave_scope();
|
||||
|
||||
BLOCK_SUPERCONTEXT(mapping.block()) = fndecl;
|
||||
DECL_INITIAL(fndecl) = mapping.block();
|
||||
DECL_SAVED_TREE(fndecl) = mapping.bind_expression();
|
||||
BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
|
||||
DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
|
||||
DECL_SAVED_TREE(fndecl) = mapping;
|
||||
|
||||
DECL_EXTERNAL(fndecl) = 0;
|
||||
DECL_PRESERVE_P(fndecl) = 1;
|
||||
|
||||
current_function_decl = NULL_TREE;
|
||||
pop_cfun();
|
||||
gimplify_function_tree(fndecl);
|
||||
cgraph_node::finalize_function(fndecl, true);
|
||||
}
|
||||
@ -239,30 +232,35 @@ namespace gcc
|
||||
|
||||
void generic_visitor::enter_scope()
|
||||
{
|
||||
scope.emplace_front();
|
||||
this->symbol_map = std::make_shared<boot::symbol_table<tree>>(this->symbol_map);
|
||||
|
||||
// Chain the binding levels.
|
||||
struct binding_level *new_level = ggc_cleared_alloc<binding_level>();
|
||||
new_level->level_chain = f_binding_level;
|
||||
new_level->statement_list = alloc_stmt_list();
|
||||
f_binding_level = new_level;
|
||||
}
|
||||
|
||||
tree_symbol_mapping generic_visitor::leave_scope()
|
||||
tree generic_visitor::leave_scope()
|
||||
{
|
||||
tree new_block = build_block(this->scope.front().variables.head(),
|
||||
this->scope.front().blocks.head(), NULL_TREE, NULL_TREE);
|
||||
// Variables are only defined in the top function scope.
|
||||
tree variables = f_binding_level->level_chain == nullptr ? f_names : NULL_TREE;
|
||||
tree new_block = build_block(variables, f_binding_level->blocks, NULL_TREE, NULL_TREE);
|
||||
|
||||
for (tree it = this->scope.front().blocks.head(); it != NULL_TREE; it = BLOCK_CHAIN(it))
|
||||
for (tree it = f_binding_level->blocks; it != NULL_TREE; it = BLOCK_CHAIN(it))
|
||||
{
|
||||
BLOCK_SUPERCONTEXT(it) = new_block;
|
||||
}
|
||||
tree bind_expr = build3(BIND_EXPR, void_type_node, this->scope.front().variables.head(),
|
||||
this->scope.front().chain_defer(), new_block);
|
||||
tree bind_expr = build3(BIND_EXPR, void_type_node, variables, chain_defer(), new_block);
|
||||
this->symbol_map = this->symbol_map->scope();
|
||||
|
||||
scope.pop_front();
|
||||
f_binding_level = f_binding_level->level_chain;
|
||||
|
||||
if (!scope.empty())
|
||||
if (f_binding_level != nullptr)
|
||||
{
|
||||
scope.front().blocks.append(new_block);
|
||||
f_binding_level->blocks = chainon(f_binding_level->blocks, new_block);
|
||||
}
|
||||
return tree_symbol_mapping{ bind_expr, new_block };
|
||||
return bind_expr;
|
||||
}
|
||||
|
||||
tree generic_visitor::lookup(const std::string& name)
|
||||
@ -295,16 +293,6 @@ namespace gcc
|
||||
{
|
||||
return elna_string_type_node;
|
||||
}
|
||||
if (current_function_decl != NULL_TREE)
|
||||
{
|
||||
for (tree decl = DECL_ARGUMENTS(current_function_decl); decl; decl = DECL_CHAIN(decl))
|
||||
{
|
||||
if (name == IDENTIFIER_POINTER(DECL_NAME(decl)))
|
||||
{
|
||||
return decl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return this->symbol_map->lookup(name);
|
||||
}
|
||||
|
||||
@ -392,11 +380,52 @@ namespace gcc
|
||||
expression, operator_code, left, right, elna_bool_type_node);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right)
|
||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression, tree left, tree right)
|
||||
{
|
||||
return build_binary_operation(true, expression,
|
||||
operator_code, left, right, elna_bool_type_node);
|
||||
location_t expression_location = get_location(&expression->position());
|
||||
tree_code equality_code, combination_code;
|
||||
|
||||
if (expression->operation() == boot::binary_operator::equals)
|
||||
{
|
||||
equality_code = EQ_EXPR;
|
||||
combination_code = TRUTH_ANDIF_EXPR;
|
||||
}
|
||||
else if (expression->operation() == boot::binary_operator::not_equals)
|
||||
{
|
||||
equality_code = NE_EXPR;
|
||||
combination_code = TRUTH_ORIF_EXPR;
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_unreachable();
|
||||
}
|
||||
if (TREE_TYPE(left) == elna_string_type_node)
|
||||
{
|
||||
tree length_field = TYPE_FIELDS(elna_string_type_node);
|
||||
tree ptr_field = TREE_CHAIN(length_field);
|
||||
|
||||
tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), left, length_field, NULL_TREE);
|
||||
tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), left, ptr_field, NULL_TREE);
|
||||
|
||||
tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(length_field), right, length_field, NULL_TREE);
|
||||
tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(ptr_field), right, ptr_field, NULL_TREE);
|
||||
|
||||
tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
|
||||
tree *memcmp = elna_global_decls->get("__builtin_memcmp");
|
||||
gcc_assert(memcmp != nullptr);
|
||||
|
||||
tree fndecl_type = build_function_type(integer_type_node, TYPE_ARG_TYPES(*memcmp));
|
||||
tree memcmp_addr = build1(ADDR_EXPR, build_pointer_type(fndecl_type), *memcmp);
|
||||
tree memcmp_call = build_call_nary(integer_type_node, memcmp_addr, 3, lhs_ptr, rhs_ptr, lhs_length);
|
||||
|
||||
tree equals_zero = build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node);
|
||||
|
||||
return build2(combination_code, elna_bool_type_node, length_equality, equals_zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
return build2_loc(expression_location, equality_code, elna_bool_type_node, left, right);
|
||||
}
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::binary_expression *expression)
|
||||
@ -473,10 +502,10 @@ namespace gcc
|
||||
this->current_expression = build_logic_operation(expression, TRUTH_ORIF_EXPR, left, right);
|
||||
break;
|
||||
case boot::binary_operator::equals:
|
||||
this->current_expression = build_equality_operation(expression, EQ_EXPR, left, right);
|
||||
this->current_expression = build_equality_operation(expression, left, right);
|
||||
break;
|
||||
case boot::binary_operator::not_equals:
|
||||
this->current_expression = build_equality_operation(expression, NE_EXPR, left, right);
|
||||
this->current_expression = build_equality_operation(expression, left, right);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -520,11 +549,11 @@ namespace gcc
|
||||
TREE_READONLY(definition_tree) = 1;
|
||||
TREE_PUBLIC(definition_tree) = definition->exported;
|
||||
|
||||
if (!scope.empty())
|
||||
if (!lang_hooks.decls.global_bindings_p())
|
||||
{
|
||||
auto declaration_statement = build1_loc(definition_location, DECL_EXPR,
|
||||
void_type_node, definition_tree);
|
||||
this->scope.front().append_statement(declaration_statement);
|
||||
append_statement(declaration_statement);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -599,7 +628,6 @@ namespace gcc
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree record_type_node = make_node(RECORD_TYPE);
|
||||
tree_chain record_chain;
|
||||
|
||||
for (auto& field : record_type->fields)
|
||||
{
|
||||
@ -617,9 +645,8 @@ namespace gcc
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
record_type_node, field.first, field_type);
|
||||
record_chain.append(field_declaration);
|
||||
TYPE_FIELDS(record_type_node) = chainon(TYPE_FIELDS(record_type_node), field_declaration);
|
||||
}
|
||||
TYPE_FIELDS(record_type_node) = record_chain.head();
|
||||
layout_type(record_type_node);
|
||||
|
||||
return record_type_node;
|
||||
@ -628,7 +655,6 @@ namespace gcc
|
||||
{
|
||||
std::set<std::string> field_names;
|
||||
tree union_type_node = make_node(UNION_TYPE);
|
||||
tree_chain union_chain;
|
||||
|
||||
for (auto& field : union_type->fields)
|
||||
{
|
||||
@ -646,9 +672,8 @@ namespace gcc
|
||||
}
|
||||
tree field_declaration = build_field(get_location(&field.second->position()),
|
||||
union_type_node, field.first, field_type);
|
||||
union_chain.append(field_declaration);
|
||||
TYPE_FIELDS(union_type_node) = chainon(TYPE_FIELDS(union_type_node), field_declaration);
|
||||
}
|
||||
TYPE_FIELDS(union_type_node) = union_chain.head();
|
||||
layout_type(union_type_node);
|
||||
|
||||
return union_type_node;
|
||||
@ -671,7 +696,7 @@ namespace gcc
|
||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||
declaration->identifier.c_str());
|
||||
}
|
||||
else if (current_function_decl == NULL_TREE)
|
||||
else if (lang_hooks.decls.global_bindings_p())
|
||||
{
|
||||
TREE_STATIC(declaration_tree) = 1;
|
||||
varpool_node::get_create(declaration_tree);
|
||||
@ -680,11 +705,11 @@ namespace gcc
|
||||
else
|
||||
{
|
||||
DECL_CONTEXT(declaration_tree) = current_function_decl;
|
||||
this->scope.front().variables.append(declaration_tree);
|
||||
f_names = chainon(f_names, declaration_tree);
|
||||
|
||||
auto declaration_statement = build1_loc(declaration_location, DECL_EXPR,
|
||||
void_type_node, declaration_tree);
|
||||
this->scope.front().append_statement(declaration_statement);
|
||||
append_statement(declaration_statement);
|
||||
}
|
||||
}
|
||||
|
||||
@ -779,7 +804,7 @@ namespace gcc
|
||||
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||
void_type_node, lvalue, this->current_expression);
|
||||
|
||||
this->scope.front().append_statement(assignment);
|
||||
append_statement(assignment);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
else
|
||||
@ -810,11 +835,11 @@ namespace gcc
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
scope.front().append_statement(mapping.bind_expression());
|
||||
tree mapping = leave_scope();
|
||||
append_statement(mapping);
|
||||
}
|
||||
tree endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
|
||||
this->scope.front().append_statement(endif_label_expr);
|
||||
append_statement(endif_label_expr);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
@ -837,22 +862,22 @@ namespace gcc
|
||||
tree goto_else = build1(GOTO_EXPR, void_type_node, else_label_decl);
|
||||
|
||||
auto cond_expr = build3(COND_EXPR, void_type_node, this->current_expression, goto_then, goto_else);
|
||||
this->scope.front().append_statement(cond_expr);
|
||||
append_statement(cond_expr);
|
||||
|
||||
tree then_label_expr = build1(LABEL_EXPR, void_type_node, then_label_decl);
|
||||
this->scope.front().append_statement(then_label_expr);
|
||||
append_statement(then_label_expr);
|
||||
enter_scope();
|
||||
|
||||
for (const auto body_statement : branch.statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
this->scope.front().append_statement(mapping.bind_expression());
|
||||
this->scope.front().append_statement(goto_endif);
|
||||
tree mapping = leave_scope();
|
||||
append_statement(mapping);
|
||||
append_statement(goto_endif);
|
||||
|
||||
tree else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
|
||||
this->scope.front().append_statement(else_label_expr);
|
||||
append_statement(else_label_expr);
|
||||
}
|
||||
|
||||
tree generic_visitor::build_label_decl(const char *name, location_t loc)
|
||||
@ -885,7 +910,7 @@ namespace gcc
|
||||
auto prerequisite_label_decl = build_label_decl("while_check", prerequisite_location);
|
||||
auto prerequisite_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
|
||||
void_type_node, prerequisite_label_decl);
|
||||
this->scope.front().append_statement(prerequisite_label_expr);
|
||||
append_statement(prerequisite_label_expr);
|
||||
|
||||
auto body_label_decl = build_label_decl("while_body", body_location);
|
||||
auto end_label_decl = build_label_decl("end_while", UNKNOWN_LOCATION);
|
||||
@ -897,24 +922,24 @@ namespace gcc
|
||||
|
||||
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
|
||||
void_type_node, this->current_expression, goto_body, goto_end);
|
||||
this->scope.front().append_statement(cond_expr);
|
||||
append_statement(cond_expr);
|
||||
|
||||
auto body_label_expr = build1_loc(body_location, LABEL_EXPR,
|
||||
void_type_node, body_label_decl);
|
||||
this->scope.front().append_statement(body_label_expr);
|
||||
append_statement(body_label_expr);
|
||||
|
||||
for (const auto body_statement : statement->body().statements)
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
this->scope.front().append_statement(mapping.bind_expression());
|
||||
tree mapping = leave_scope();
|
||||
append_statement(mapping);
|
||||
|
||||
auto goto_check = build1(GOTO_EXPR, void_type_node, prerequisite_label_decl);
|
||||
this->scope.front().append_statement(goto_check);
|
||||
append_statement(goto_check);
|
||||
|
||||
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, end_label_decl);
|
||||
this->scope.front().append_statement(endif_label_expr);
|
||||
append_statement(endif_label_expr);
|
||||
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
@ -922,7 +947,7 @@ namespace gcc
|
||||
void generic_visitor::visit(boot::call_statement *statement)
|
||||
{
|
||||
statement->body().accept(this);
|
||||
this->scope.front().append_statement(this->current_expression);
|
||||
append_statement(this->current_expression);
|
||||
this->current_expression = NULL_TREE;
|
||||
}
|
||||
|
||||
@ -939,7 +964,7 @@ namespace gcc
|
||||
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(current_function_decl),
|
||||
this->current_expression);
|
||||
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
|
||||
this->scope.front().append_statement(return_stmt);
|
||||
append_statement(return_stmt);
|
||||
}
|
||||
|
||||
void generic_visitor::visit(boot::defer_statement *statement)
|
||||
@ -949,8 +974,7 @@ namespace gcc
|
||||
{
|
||||
body_statement->accept(this);
|
||||
}
|
||||
tree_symbol_mapping mapping = leave_scope();
|
||||
scope.front().defer(mapping.bind_expression());
|
||||
defer(leave_scope());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "elna/gcc/elna-diagnostic.h"
|
||||
#include "elna/gcc/elna1.h"
|
||||
|
||||
#include "function.h"
|
||||
#include "stor-layout.h"
|
||||
#include "fold-const.h"
|
||||
#include "diagnostic-core.h"
|
||||
@ -39,6 +40,11 @@ namespace gcc
|
||||
return TREE_CODE(type) == INTEGER_TYPE;
|
||||
}
|
||||
|
||||
bool is_numeric_type(tree type)
|
||||
{
|
||||
return is_integral_type(type) || type == elna_float_type_node;
|
||||
}
|
||||
|
||||
bool are_compatible_pointers(tree lhs, tree rhs)
|
||||
{
|
||||
tree lhs_type = TREE_TYPE(lhs);
|
||||
@ -48,90 +54,42 @@ namespace gcc
|
||||
|| (is_pointer_type(lhs_type) && lhs_type == rhs_type);
|
||||
}
|
||||
|
||||
tree tree_chain_base::head()
|
||||
void append_statement(tree statement_tree)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
void tree_chain_base::append(tree t)
|
||||
{
|
||||
gcc_assert(t != NULL_TREE);
|
||||
|
||||
if (this->first == NULL_TREE)
|
||||
if (!vec_safe_is_empty(f_binding_level->defers))
|
||||
{
|
||||
this->first = this->last = t;
|
||||
append_to_statement_list(statement_tree, &f_binding_level->defers->begin()->try_statements);
|
||||
}
|
||||
else
|
||||
{
|
||||
chain(t);
|
||||
this->last = t;
|
||||
append_to_statement_list(statement_tree, &f_binding_level->statement_list);
|
||||
}
|
||||
}
|
||||
|
||||
void tree_chain::chain(tree t)
|
||||
void defer(tree statement_tree)
|
||||
{
|
||||
TREE_CHAIN(this->last) = t;
|
||||
defer_scope new_defer{ statement_tree, alloc_stmt_list() };
|
||||
vec_safe_insert(f_binding_level->defers, 0, new_defer);
|
||||
}
|
||||
|
||||
void block_chain::chain(tree t)
|
||||
tree chain_defer()
|
||||
{
|
||||
BLOCK_CHAIN(this->last) = t;
|
||||
}
|
||||
|
||||
tree_symbol_mapping::tree_symbol_mapping(tree bind_expression, tree block)
|
||||
: m_bind_expression(bind_expression), m_block(block)
|
||||
{
|
||||
}
|
||||
|
||||
tree tree_symbol_mapping::bind_expression()
|
||||
{
|
||||
return m_bind_expression;
|
||||
}
|
||||
|
||||
tree tree_symbol_mapping::block()
|
||||
{
|
||||
return m_block;
|
||||
}
|
||||
|
||||
block_scope::block_scope()
|
||||
: m_statement_list(alloc_stmt_list())
|
||||
{
|
||||
}
|
||||
|
||||
void block_scope::append_statement(tree statement_tree)
|
||||
{
|
||||
if (!defers.empty())
|
||||
if (vec_safe_is_empty(f_binding_level->defers))
|
||||
{
|
||||
append_to_statement_list(statement_tree, &this->defers.front().second);
|
||||
return f_binding_level->statement_list;
|
||||
}
|
||||
else
|
||||
{
|
||||
append_to_statement_list(statement_tree, &this->m_statement_list);
|
||||
}
|
||||
}
|
||||
defer_scope *defer_iterator = f_binding_level->defers->begin();
|
||||
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
|
||||
defer_iterator->try_statements, defer_iterator->defer_block);
|
||||
int i;
|
||||
|
||||
void block_scope::defer(tree statement_tree)
|
||||
{
|
||||
defers.push_front({ statement_tree, alloc_stmt_list() });
|
||||
}
|
||||
|
||||
tree block_scope::chain_defer()
|
||||
{
|
||||
if (this->defers.empty())
|
||||
FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
|
||||
{
|
||||
return m_statement_list;
|
||||
append_to_statement_list(defer_tree, &defer_iterator->try_statements);
|
||||
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
|
||||
defer_iterator->try_statements, defer_iterator->defer_block);
|
||||
}
|
||||
std::forward_list<std::pair<tree, tree>>::iterator defer_iterator =
|
||||
this->defers.begin();
|
||||
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
|
||||
|
||||
++defer_iterator;
|
||||
for (; defer_iterator != this->defers.end(); ++defer_iterator)
|
||||
{
|
||||
append_to_statement_list(defer_tree, &defer_iterator->second);
|
||||
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node, defer_iterator->second, defer_iterator->first);
|
||||
}
|
||||
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), m_statement_list, defer_tree);
|
||||
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
|
||||
}
|
||||
|
||||
tree build_field(location_t location, tree record_type, const std::string name, tree type)
|
||||
|
40
gcc/elna1.cc
40
gcc/elna1.cc
@ -1,5 +1,5 @@
|
||||
/* Language-dependent hooks for Elna.
|
||||
Copyright (C) 2006-2024 Free Software Foundation, Inc.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "parser.hh"
|
||||
|
||||
tree elna_global_trees[ELNA_TI_MAX];
|
||||
hash_map<nofree_string_hash, tree> *elna_global_decls = nullptr;
|
||||
|
||||
/* The resulting tree type. */
|
||||
|
||||
@ -53,7 +54,9 @@ union GTY ((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
|
||||
static bool elna_langhook_init(void)
|
||||
{
|
||||
build_common_tree_nodes(false);
|
||||
|
||||
elna::gcc::init_ttree();
|
||||
elna_global_decls = hash_map<nofree_string_hash, tree>::create_ggc(default_hash_map_size);
|
||||
|
||||
build_common_builtin_nodes();
|
||||
|
||||
@ -172,30 +175,32 @@ static bool global_bindings_p(void)
|
||||
return current_function_decl == NULL_TREE;
|
||||
}
|
||||
|
||||
tree getdecls(void)
|
||||
static tree pushdecl(tree decl)
|
||||
{
|
||||
if (current_function_decl != NULL_TREE)
|
||||
{
|
||||
return f_binding_level->names;
|
||||
}
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
tree pushdecl(tree decl)
|
||||
{
|
||||
if (current_function_decl != NULL_TREE)
|
||||
{
|
||||
TREE_CHAIN(decl) = f_binding_level->names;
|
||||
f_binding_level->names = decl;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
static tree elna_langhook_builtin_function(tree decl)
|
||||
{
|
||||
elna_global_decls->put(IDENTIFIER_POINTER(DECL_NAME(decl)), decl);
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Creates an expression whose value is that of EXPR, converted to type TYPE.
|
||||
This function implements all reasonable scalar conversions. */
|
||||
tree convert(tree type, tree expr)
|
||||
{
|
||||
if (error_operand_p(type) || error_operand_p(expr))
|
||||
{
|
||||
return error_mark_node;
|
||||
}
|
||||
if (TREE_TYPE(expr) == type)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
#undef LANG_HOOKS_NAME
|
||||
#define LANG_HOOKS_NAME "GNU Elna"
|
||||
|
||||
@ -208,6 +213,9 @@ static tree elna_langhook_builtin_function(tree decl)
|
||||
#undef LANG_HOOKS_TYPE_FOR_MODE
|
||||
#define LANG_HOOKS_TYPE_FOR_MODE elna_langhook_type_for_mode
|
||||
|
||||
#undef LANG_HOOKS_GETDECLS
|
||||
#define LANG_HOOKS_GETDECLS hook_tree_void_null
|
||||
|
||||
#undef LANG_HOOKS_BUILTIN_FUNCTION
|
||||
#define LANG_HOOKS_BUILTIN_FUNCTION elna_langhook_builtin_function
|
||||
|
||||
|
@ -1,3 +1,20 @@
|
||||
/* Builtin definitions.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
|
@ -36,7 +36,6 @@ namespace gcc
|
||||
{
|
||||
class generic_visitor final : public boot::empty_visitor
|
||||
{
|
||||
std::forward_list<block_scope> scope;
|
||||
tree current_expression{ NULL_TREE };
|
||||
std::shared_ptr<boot::symbol_table<tree>> symbol_map;
|
||||
|
||||
@ -44,22 +43,19 @@ namespace gcc
|
||||
tree build_type(boot::type_expression& type);
|
||||
|
||||
void enter_scope();
|
||||
tree_symbol_mapping leave_scope();
|
||||
tree leave_scope();
|
||||
|
||||
tree lookup(const std::string& name);
|
||||
|
||||
void make_if_branch(boot::conditional_statements& branch, tree goto_endif);
|
||||
|
||||
bool is_numeric_type(tree type);
|
||||
|
||||
tree build_arithmetic_operation(boot::binary_expression *expression,
|
||||
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_equality_operation(boot::binary_expression *expression,
|
||||
tree_code operator_code, tree left, tree right);
|
||||
tree build_equality_operation(boot::binary_expression *expression, tree left, tree right);
|
||||
|
||||
public:
|
||||
generic_visitor(std::shared_ptr<boot::symbol_table<tree>> symbol_table);
|
||||
|
@ -35,6 +35,7 @@ namespace gcc
|
||||
{
|
||||
bool is_pointer_type(tree type);
|
||||
bool is_integral_type(tree type);
|
||||
bool is_numeric_type(tree type);
|
||||
|
||||
/**
|
||||
* \param lhs Left hand value.
|
||||
@ -43,59 +44,9 @@ namespace gcc
|
||||
*/
|
||||
bool are_compatible_pointers(tree lhs, tree rhs);
|
||||
|
||||
class tree_chain_base
|
||||
{
|
||||
protected:
|
||||
tree first{};
|
||||
tree last{};
|
||||
|
||||
public:
|
||||
tree head();
|
||||
void append(tree t);
|
||||
|
||||
protected:
|
||||
virtual void chain(tree t) = 0;
|
||||
};
|
||||
|
||||
class tree_chain final : public tree_chain_base
|
||||
{
|
||||
protected:
|
||||
void chain(tree t) override;
|
||||
};
|
||||
|
||||
class block_chain final : public tree_chain_base
|
||||
{
|
||||
protected:
|
||||
void chain(tree t) override;
|
||||
};
|
||||
|
||||
class tree_symbol_mapping final
|
||||
{
|
||||
tree m_bind_expression;
|
||||
tree m_block;
|
||||
|
||||
public:
|
||||
tree_symbol_mapping(tree bind_expression, tree block);
|
||||
|
||||
tree bind_expression();
|
||||
tree block();
|
||||
};
|
||||
|
||||
class block_scope
|
||||
{
|
||||
tree m_statement_list{ NULL_TREE };
|
||||
std::forward_list<std::pair<tree, tree>> defers;
|
||||
|
||||
public:
|
||||
tree_chain variables;
|
||||
block_chain blocks;
|
||||
|
||||
block_scope();
|
||||
|
||||
void append_statement(tree statement_tree);
|
||||
void defer(tree statement_tree);
|
||||
tree chain_defer();
|
||||
};
|
||||
void append_statement(tree statement_tree);
|
||||
void defer(tree statement_tree);
|
||||
tree chain_defer();
|
||||
|
||||
tree do_pointer_arithmetic(boot::binary_operator binary_operator, tree left, tree right);
|
||||
tree build_binary_operation(bool condition, boot::binary_expression *expression,
|
||||
|
@ -1,3 +1,20 @@
|
||||
/* Language-dependent hooks for Elna.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
enum elna_tree_index
|
||||
{
|
||||
ELNA_TI_INT_TYPE,
|
||||
@ -11,6 +28,7 @@ enum elna_tree_index
|
||||
};
|
||||
|
||||
extern GTY(()) tree elna_global_trees[ELNA_TI_MAX];
|
||||
extern GTY(()) hash_map<nofree_string_hash, tree> *elna_global_decls;
|
||||
|
||||
#define elna_int_type_node elna_global_trees[ELNA_TI_INT_TYPE]
|
||||
#define elna_word_type_node elna_global_trees[ELNA_TI_WORD_TYPE]
|
||||
@ -30,18 +48,35 @@ struct GTY (()) lang_decl
|
||||
{
|
||||
};
|
||||
|
||||
struct GTY (()) binding_level
|
||||
struct GTY (()) defer_scope
|
||||
{
|
||||
// A chain of all declarations in this binding level.
|
||||
tree names;
|
||||
tree defer_block;
|
||||
tree try_statements;
|
||||
};
|
||||
|
||||
struct GTY ((chain_next ("%h.level_chain"))) binding_level
|
||||
{
|
||||
// A block chain is needed to call defer statements beloning to each block.
|
||||
tree blocks;
|
||||
|
||||
// Parent level.
|
||||
struct binding_level *level_chain;
|
||||
|
||||
// Statements before the first defer has been seen.
|
||||
tree statement_list;
|
||||
|
||||
// Defer statement coupled with statements following it.
|
||||
vec<defer_scope, va_gc> *defers;
|
||||
};
|
||||
|
||||
struct GTY (()) language_function
|
||||
{
|
||||
// Local variables and constants.
|
||||
tree names;
|
||||
|
||||
// Lexical scope.
|
||||
struct binding_level *binding_level;
|
||||
};
|
||||
|
||||
#define f_binding_level DECL_STRUCT_FUNCTION(current_function_decl)->language->binding_level
|
||||
|
||||
extern tree pushdecl(tree);
|
||||
extern tree getdecls(void);
|
||||
#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names
|
||||
|
72
source.elna
72
source.elna
@ -174,14 +174,6 @@ begin
|
||||
return c = ' ' or c = '\n' or c = '\t'
|
||||
end
|
||||
|
||||
proc string_equals(this: String, that: String): Bool;
|
||||
begin
|
||||
if this.length <> that.length then
|
||||
return false
|
||||
end;
|
||||
return strncmp(this.ptr, that.ptr, this.length) = 0
|
||||
end
|
||||
|
||||
proc open_substring(string: String, start: Word): String;
|
||||
begin
|
||||
string.ptr := string.ptr + start;
|
||||
@ -560,67 +552,67 @@ proc categorize_identifier(token_content: String): Token;
|
||||
var
|
||||
current_token: Token;
|
||||
begin
|
||||
if string_equals("if", token_content) then
|
||||
if "if" = token_content then
|
||||
current_token.kind := TOKEN_IF
|
||||
elsif string_equals("then", token_content) then
|
||||
elsif "then" = token_content then
|
||||
current_token.kind := TOKEN_THEN
|
||||
elsif string_equals("else", token_content) then
|
||||
elsif "else" = token_content then
|
||||
current_token.kind := TOKEN_ELSE
|
||||
elsif string_equals("elsif", token_content) then
|
||||
elsif "elsif" = token_content then
|
||||
current_token.kind := TOKEN_ELSIF
|
||||
elsif string_equals("while", token_content) then
|
||||
elsif "while" = token_content then
|
||||
current_token.kind := TOKEN_WHILE
|
||||
elsif string_equals("do", token_content) then
|
||||
elsif "do" = token_content then
|
||||
current_token.kind := TOKEN_DO
|
||||
elsif string_equals("proc", token_content) then
|
||||
elsif "proc" = token_content then
|
||||
current_token.kind := TOKEN_PROC
|
||||
elsif string_equals("begin", token_content) then
|
||||
elsif "begin" = token_content then
|
||||
current_token.kind := TOKEN_BEGIN
|
||||
elsif string_equals("end", token_content) then
|
||||
elsif "end" = token_content then
|
||||
current_token.kind := TOKEN_END
|
||||
elsif string_equals("extern", token_content) then
|
||||
elsif "extern" = token_content then
|
||||
current_token.kind := TOKEN_EXTERN
|
||||
elsif string_equals("const", token_content) then
|
||||
elsif "const" = token_content then
|
||||
current_token.kind := TOKEN_CONST
|
||||
elsif string_equals("var", token_content) then
|
||||
elsif "var" = token_content then
|
||||
current_token.kind := TOKEN_VAR
|
||||
elsif string_equals("array", token_content) then
|
||||
elsif "array" = token_content then
|
||||
current_token.kind := TOKEN_ARRAY
|
||||
elsif string_equals("of", token_content) then
|
||||
elsif "of" = token_content then
|
||||
current_token.kind := TOKEN_OF
|
||||
elsif string_equals("type", token_content) then
|
||||
elsif "type" = token_content then
|
||||
current_token.kind := TOKEN_TYPE
|
||||
elsif string_equals("record", token_content) then
|
||||
elsif "record" = token_content then
|
||||
current_token.kind := TOKEN_RECORD
|
||||
elsif string_equals("union", token_content) then
|
||||
elsif "union" = token_content then
|
||||
current_token.kind := TOKEN_UNION
|
||||
elsif string_equals("pointer", token_content) then
|
||||
elsif "pointer" = token_content then
|
||||
current_token.kind := TOKEN_POINTER
|
||||
elsif string_equals("to", token_content) then
|
||||
elsif "to" = token_content then
|
||||
current_token.kind := TOKEN_TO
|
||||
elsif string_equals("true", token_content) then
|
||||
elsif "true" = token_content then
|
||||
current_token.kind := TOKEN_BOOLEAN;
|
||||
current_token.value.boolean_value := true
|
||||
elsif string_equals("false", token_content) then
|
||||
elsif "false" = token_content then
|
||||
current_token.kind := TOKEN_BOOLEAN;
|
||||
current_token.value.boolean_value := false
|
||||
elsif string_equals("nil", token_content) then
|
||||
elsif "nil" = token_content then
|
||||
current_token.kind := TOKEN_NIL
|
||||
elsif string_equals("and", token_content) then
|
||||
elsif "and" = token_content then
|
||||
current_token.kind := TOKEN_AND
|
||||
elsif string_equals("or", token_content) then
|
||||
elsif "or" = token_content then
|
||||
current_token.kind := TOKEN_OR
|
||||
elsif string_equals("not", token_content) then
|
||||
elsif "not" = token_content then
|
||||
current_token.kind := TOKEN_NOT
|
||||
elsif string_equals("return", token_content) then
|
||||
elsif "return" = token_content then
|
||||
current_token.kind := TOKEN_RETURN
|
||||
elsif string_equals("cast", token_content) then
|
||||
elsif "cast" = token_content then
|
||||
current_token.kind := TOKEN_CAST
|
||||
elsif string_equals("as", token_content) then
|
||||
elsif "as" = token_content then
|
||||
current_token.kind := TOKEN_AS
|
||||
elsif string_equals("sizeof", token_content) then
|
||||
elsif "sizeof" = token_content then
|
||||
current_token.kind := TOKEN_SIZEOF
|
||||
elsif string_equals("defer", token_content) then
|
||||
elsif "defer" = token_content then
|
||||
current_token.kind := TOKEN_DEFER
|
||||
else
|
||||
current_token.kind := TOKEN_IDENTIFIER;
|
||||
@ -650,9 +642,7 @@ begin
|
||||
|
||||
if is_alpha(first_char) or first_char = '_' then
|
||||
lex_identifier(@source_code, @token_content);
|
||||
current_token^ := categorize_identifier(token_content);
|
||||
|
||||
source_code := advance_source(source_code, 1u)
|
||||
current_token^ := categorize_identifier(token_content)
|
||||
elsif is_digit(first_char) then
|
||||
token_end := nil;
|
||||
current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10);
|
||||
|
Loading…
x
Reference in New Issue
Block a user