1
0

Collect declarations before doing name analysis

This commit is contained in:
2026-06-21 23:15:51 +02:00
parent c8cddbe271
commit b891573bbc
2 changed files with 488 additions and 328 deletions
+260 -164
View File
@@ -3,11 +3,15 @@
* v. 2.0. If a copy of the MPL was not distributed with this file, You can * v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at https://mozilla.org/MPL/2.0/. * obtain one at https://mozilla.org/MPL/2.0/.
*) *)
program; program;
(* Stage 23 compiler. *) (* Stage 23 compiler. *)
(* - Support extern procedure declarations. *) (* - Support extern procedure declarations. *)
(* - Do not require program keyword in the beginning of a module. *)
(* - Support records refencing themselves in their fields. *)
(* - Types can be referenced even if they are declared later. *)
type type
ElnaListNode = record ElnaListNode = record
@@ -35,12 +39,18 @@ type
end end
(* Type representation. *) (* Type representation. *)
ElnaTypeKind = (primitive, enumeration, _record, pointer, array) ElnaTypeKind = (primitive, enumeration, _record, pointer, array, alias)
ElnaType = record ElnaType = record
kind: ElnaTypeKind; kind: ElnaTypeKind;
size: Word; size: Word;
alignment: Word alignment: Word
end end
ElnaTypeAlias = record
kind: ElnaTypeKind;
size: Word;
alignment: Word;
base: ^ElnaType
end
ElnaTypeEnumeration = record ElnaTypeEnumeration = record
kind: ElnaTypeKind; kind: ElnaTypeKind;
size: Word; size: Word;
@@ -333,7 +343,8 @@ type
ElnaSymbolProcedureInfo = record ElnaSymbolProcedureInfo = record
kind: ElnaSymbolInfoKind; kind: ElnaSymbolInfoKind;
symbol_table: ^ElnaSymbolTable; symbol_table: ^ElnaSymbolTable;
return_type: ^ElnaType return_type: ^ElnaType;
is_extern: Bool
end end
ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited) ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited)
@@ -865,7 +876,7 @@ begin
operand^.value := buffer; operand^.value := buffer;
operand^.length := strlen(buffer); operand^.length := strlen(buffer);
temporary_info := temporary_info_create(1, variable_type); temporary_info := elna_symbol_temporary_info_create(1, variable_type);
elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info) elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info)
end end
@@ -3897,15 +3908,13 @@ end
* *
* Returns enumeration type description. * Returns enumeration type description.
*) *)
proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression) -> ^ElnaTypeEnumeration proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression,
result: ^ElnaTypeEnumeration)
var var
result: ^ElnaTypeEnumeration
memory_start: ^ElnaTreeEnumeration memory_start: ^ElnaTreeEnumeration
member_count: Word member_count: Word
member_array_current: ^String member_array_current: ^String
begin begin
result := malloc(#size(ElnaTypeEnumeration));
memory_start := parser_node^.members; memory_start := parser_node^.members;
member_count := parser_node^.length; member_count := parser_node^.length;
@@ -3922,58 +3931,43 @@ begin
member_count := member_count - 1; member_count := member_count - 1;
goto elna_name_type_enumeration_loop goto elna_name_type_enumeration_loop
end; end;
result^.kind := ElnaTypeKind.enumeration;
result^.size := 4; result^.size := 4;
result^.alignment := 4; result^.alignment := 4;
result^.length := parser_node^.length; result^.length := parser_node^.length
return result
end end
proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression) -> ^ElnaTypePointer proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression,
var result: ^ElnaTypePointer)
result: ^ElnaTypePointer
begin begin
result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer;
result^.size := 4; result^.size := 4;
result^.alignment := 4; result^.alignment := 4;
result^.base := elna_name_type_expression(parser_node^.base); result^.base := elna_name_type_expression(parser_node^.base)
return result
end end
proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression) -> ^ElnaTypeArray proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression,
result: ^ElnaTypeArray)
var var
base: ^ElnaType base: ^ElnaType
result: ^ElnaTypeArray
length: ^ElnaTreeIntegerLiteral length: ^ElnaTreeIntegerLiteral
begin begin
result := malloc(#size(ElnaTypeArray));
base := elna_name_type_expression(parser_node^.base); base := elna_name_type_expression(parser_node^.base);
length := parser_node^.length; length := parser_node^.length;
result^.kind := ElnaTypeKind.array;
(* Array size in bytes. *) (* Array size in bytes. *)
result^.size := base^.size * length^.value; result^.size := base^.size * length^.value;
result^.alignment := base^.alignment; result^.alignment := base^.alignment;
result^.base := base; result^.base := base;
result^.length := length^.value; result^.length := length^.value
return result
end end
proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression) -> ^ElnaTypeRecord proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression,
result: ^ElnaTypeRecord)
var var
result: ^ElnaTypeRecord result: ^ElnaTypeRecord
tree_field: ^ElnaTreeField tree_field: ^ElnaTreeField
member_array_current: ^ElnaTypeField member_array_current: ^ElnaTypeField
field_type: ^ElnaType field_type: ^ElnaType
begin begin
result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record;
result^.size := 0; result^.size := 0;
result^.alignment := 0; result^.alignment := 0;
result^.length := 0; result^.length := 0;
@@ -3998,9 +3992,7 @@ begin
tree_field := tree_field^.next; tree_field := tree_field^.next;
result^.length := result^.length + 1; result^.length := result^.length + 1;
goto elna_name_type_record_loop goto elna_name_type_record_loop
end; end
return result
end end
proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression
@@ -4091,7 +4083,21 @@ begin
return result return result
end end
proc elna_name_type_expression(parser_node: ^ElnaTreeNode) -> ^ElnaType proc elna_name_alias_type_expression(parser_node: ^ElnaTreeNamedTypeExpression, result: ^ElnaTypeAlias)
var
type_symbol: ^ElnaSymbolTypeInfo
aliased_type: ^ElnaType
begin
type_symbol := elna_symbol_table_lookup(symbol_table_global,
parser_node^.name.ptr, parser_node^.name.length);
aliased_type := type_symbol^._type;
result^.size := aliased_type^.size;
result^.alignment := aliased_type^.alignment;
result^.base := aliased_type
end
proc elna_name_type_expression(parser_node: ^ElnaTreeTypeExpression) -> ^ElnaType
var var
named_type_expression: ^ElnaTreeNamedTypeExpression named_type_expression: ^ElnaTreeNamedTypeExpression
type_symbol: ^ElnaSymbolTypeInfo type_symbol: ^ElnaSymbolTypeInfo
@@ -4104,19 +4110,31 @@ begin
named_type_expression^.name.ptr, named_type_expression^.name.length); named_type_expression^.name.ptr, named_type_expression^.name.length);
result := type_symbol^._type result := type_symbol^._type
elsif parser_node^.kind = ElnaTreeKind.enumeration_type_expression then elsif parser_node^.kind = ElnaTreeKind.enumeration_type_expression then
result := elna_name_enumeration_type_expression(parser_node) result := malloc(#size(ElnaTypeEnumeration));
result^.kind := ElnaTypeKind.enumeration;
elna_name_enumeration_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.record_type_expression then elsif parser_node^.kind = ElnaTreeKind.record_type_expression then
result := elna_name_record_type_expression(parser_node) result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record;
elna_name_record_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then
result := elna_name_pointer_type_expression(parser_node) result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer;
elna_name_pointer_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.array_type_expression then elsif parser_node^.kind = ElnaTreeKind.array_type_expression then
result := elna_name_array_type_expression(parser_node) result := malloc(#size(ElnaTypeArray));
result^.kind := ElnaTypeKind.array;
elna_name_array_type_expression(parser_node, result)
end; end;
return result return result
end end
proc type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo proc elna_symbol_type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo
var var
result: ^ElnaSymbolTypeInfo result: ^ElnaSymbolTypeInfo
begin begin
@@ -4132,7 +4150,7 @@ end
* attr - Local variable attributes. * attr - Local variable attributes.
* temporary_type - Local variable type. * temporary_type - Local variable type.
*) *)
proc temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo proc elna_symbol_temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo
var var
result: ^ElnaSymbolTemporaryInfo result: ^ElnaSymbolTemporaryInfo
begin begin
@@ -4150,14 +4168,14 @@ end
* Parameters: * Parameters:
* symbol_table - Local symbol table. * symbol_table - Local symbol table.
*) *)
proc procedure_info_create(symbol_table: ^ElnaSymbolTable, return_type: ^ElnaRtlType) -> ^ElnaSymbolProcedureInfo proc elna_symbol_procedure_info_create(return_type: ^ElnaRtlType, is_extern: Bool) -> ^ElnaSymbolProcedureInfo
var var
result: ^ElnaSymbolProcedureInfo result: ^ElnaSymbolProcedureInfo
begin begin
result := malloc(#size(ElnaSymbolProcedureInfo)); result := malloc(#size(ElnaSymbolProcedureInfo));
result^.kind := ElnaSymbolInfoKind.procedure_info; result^.kind := ElnaSymbolInfoKind.procedure_info;
result^.symbol_table := symbol_table;
result^.return_type := return_type; result^.return_type := return_type;
result^.is_extern := is_extern;
return result return result
end end
@@ -4168,12 +4186,12 @@ end
*) *)
proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable) proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable)
var var
info: Word info: ^ElnaSymbolTemporaryInfo
variable_type: Word variable_type: ^ElnaType
begin begin
variable_type := elna_name_type_expression(parser_node^.type_expression); variable_type := elna_name_type_expression(parser_node^.type_expression);
info := temporary_info_create(0, variable_type); info := elna_symbol_temporary_info_create(0, variable_type);
elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info) elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info)
end end
@@ -4725,17 +4743,25 @@ end
proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration)
var var
symbol_type: ^ElnaType
type_info: ^ElnaSymbolTypeInfo type_info: ^ElnaSymbolTypeInfo
type_stub: ^ElnaType
type_expression: ^ElnaTreeTypeExpression
begin begin
symbol_type := elna_name_type_expression(parser_node^.type_expression); type_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
type_info := type_info_create(symbol_type); type_stub := type_info^._type;
type_expression := parser_node^.type_expression;
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info) if type_stub^.kind = ElnaTypeKind.alias then
end elna_name_alias_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.enumeration then
proc elna_type_type_declaration(parser_node: Word) elna_name_enumeration_type_expression(type_expression, type_stub)
begin elsif type_stub^.kind = ElnaTypeKind._record then
elna_name_record_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.pointer then
elna_name_pointer_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.array then
elna_name_array_type_expression(type_expression, type_stub)
end
end end
proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration
@@ -4935,37 +4961,40 @@ end
proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration
var var
token: ^ElnaLexerToken
result: ^ElnaTreeModuleDeclaration result: ^ElnaTreeModuleDeclaration
begin begin
result := nil; elna_lexer_skip_empty_lines(cursor);
if elna_parser_expect(cursor, ElnaLexerKind._program, error_list) <> nil then token := elna_lexer_peek(cursor);
if elna_parser_expect(cursor, ElnaLexerKind.semicolon, error_list) <> nil then if token^.kind = ElnaLexerKind._program then
result := malloc(#size(ElnaTreeModuleDeclaration)); elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.module_declaration; elna_lexer_read(cursor)
end;
result^.types := elna_parser_type_part(cursor, error_list); result := malloc(#size(ElnaTreeModuleDeclaration));
if elna_list_empty(error_list) = false then result^.kind := ElnaTreeKind.module_declaration;
result := free_and_nil(result)
end; result^.types := elna_parser_type_part(cursor, error_list);
if result <> nil then if elna_list_empty(error_list) = false then
result^.globals := elna_parser_var_part(cursor, error_list); result := free_and_nil(result)
end; end;
if elna_list_empty(error_list) = false then if result <> nil then
result := free_and_nil(result) result^.globals := elna_parser_var_part(cursor, error_list);
end; end;
if result <> nil then if elna_list_empty(error_list) = false then
result^.procedures := elna_parser_procedures(cursor, error_list); result := free_and_nil(result)
end; end;
if elna_list_empty(error_list) = false then if result <> nil then
result := free_and_nil(result) result^.procedures := elna_parser_procedures(cursor, error_list);
end; end;
if result <> nil then if elna_list_empty(error_list) = false then
result^.body := elna_parser_program_body(cursor, error_list) result := free_and_nil(result)
end; end;
if elna_list_empty(error_list) = false then if result <> nil then
result := free_and_nil(result) result^.body := elna_parser_program_body(cursor, error_list)
end end;
end if elna_list_empty(error_list) = false then
result := free_and_nil(result)
end; end;
return result return result
end end
@@ -5022,90 +5051,104 @@ begin
return result return result
end end
proc elna_name_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression) proc elna_name_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_designator(parser_node^.pointer) elna_name_designator(parser_node^.pointer, symbol_table)
end end
proc elna_name_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression) proc elna_name_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_designator(parser_node^.aggregate) elna_name_designator(parser_node^.aggregate, symbol_table)
end end
proc elna_name_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression) proc elna_name_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_designator(parser_node^.array); elna_name_designator(parser_node^.array, symbol_table);
elna_name_binary_expression(parser_node^.index) elna_name_binary_expression(parser_node^.index, symbol_table)
end end
proc elna_name_cast_expression(parser_node: ^ElnaTreeCastExpression) proc elna_name_cast_expression(parser_node: ^ElnaTreeCastExpression, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_binary_expression(parser_node^.expression); elna_name_binary_expression(parser_node^.expression);
parser_node^.type_decoration := elna_name_type_expression(parser_node^.type_expression) parser_node^.type_decoration := elna_name_type_expression(parser_node^.type_expression)
end end
proc elna_name_simple_expression(parser_node: ^ElnaTreeNode) proc elna_name_variable_expression(parser_node: ^ElnaTreeVariableExpression, symbol_table: ^ElnaSymbolTable)
begin begin
(* Not interested in literals and variable expressions. *) end
proc elna_name_simple_expression(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable)
begin
(* Not interested in literals. *)
if parser_node^.kind = ElnaTreeKind._cast then if parser_node^.kind = ElnaTreeKind._cast then
elna_name_cast_expression(parser_node) elna_name_cast_expression(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.variable_expression then
elna_name_variable_expression(parser_node, symbol_table)
end end
end end
proc elna_name_call(parser_node: ^ElnaTreeCall) proc elna_name_call(parser_node: ^ElnaTreeCall, symbol_table: ^ElnaSymbolTable)
var var
argument_tree: ^ElnaTreeExpressionList argument_tree: ^ElnaTreeExpressionList
callee_symbol: ^ElnaSymbolProcedureInfo
begin begin
callee_symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.callee^.name.ptr, parser_node^.callee^.name.length);
if callee_symbol = nil then
(* DEBUG *)
_write_s(stdout, "# Undefined symbol ");
_write_s(stdout, parser_node^.callee^.name);
_write_s(stdout, ".\n")
end;
argument_tree := parser_node^.arguments; argument_tree := parser_node^.arguments;
.elna_name_call_argument; .elna_name_call_argument;
if argument_tree <> nil then if argument_tree <> nil then
elna_name_binary_expression(argument_tree^.expression); elna_name_binary_expression(argument_tree^.expression, symbol_table);
argument_tree := argument_tree^.next; argument_tree := argument_tree^.next;
goto elna_name_call_argument goto elna_name_call_argument
end end
end end
proc elna_name_designator(parser_node: ^ElnaTreeNode) proc elna_name_designator(parser_node: ^ElnaTreeNode, symbol_table: ^ElnaSymbolTable)
begin begin
if parser_node^.kind = ElnaTreeKind.dereference_expression then if parser_node^.kind = ElnaTreeKind.dereference_expression then
elna_name_dereference_expression(parser_node) elna_name_dereference_expression(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.field_access_expression then elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
elna_name_field_access_expression(parser_node) elna_name_field_access_expression(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.array_access_expression then elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
elna_name_array_access_expression(parser_node) elna_name_array_access_expression(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.call then elsif parser_node^.kind = ElnaTreeKind.call then
elna_name_call(parser_node) elna_name_call(parser_node, symbol_table)
else else
elna_name_simple_expression(parser_node) elna_name_simple_expression(parser_node, symbol_table)
end end
end end
proc elna_name_unary_expression(parser_node: ^ElnaTreeUnaryExpression) proc elna_name_unary_expression(parser_node: ^ElnaTreeUnaryExpression, symbol_table: ^ElnaSymbolTable)
begin begin
if parser_node^.kind = ElnaTreeKind.unary_expression then if parser_node^.kind = ElnaTreeKind.unary_expression then
elna_name_designator(parser_node^.operand) elna_name_designator(parser_node^.operand, symbol_table)
else else
elna_name_designator(parser_node) elna_name_designator(parser_node, symbol_table)
end end
end end
proc elna_name_binary_expression(parser_node: ^ElnaTreeBinaryExpression) proc elna_name_binary_expression(parser_node: ^ElnaTreeBinaryExpression, symbol_table: ^ElnaSymbolTable)
begin begin
if parser_node^.kind = ElnaTreeKind.binary_expression then if parser_node^.kind = ElnaTreeKind.binary_expression then
elna_name_unary_expression(parser_node^.lhs); elna_name_unary_expression(parser_node^.lhs, symbol_table);
elna_name_unary_expression(parser_node^.rhs) elna_name_unary_expression(parser_node^.rhs, symbol_table)
else else
elna_name_unary_expression(parser_node) elna_name_unary_expression(parser_node, symbol_table)
end end
end end
proc elna_name_conditional_statements(parser_node: ^ElnaTreeConditionalStatements) proc elna_name_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable)
begin begin
.elna_name_conditional_statements_loop; .elna_name_conditional_statements_loop;
elna_name_binary_expression(parser_node^.condition); elna_name_binary_expression(parser_node^.condition, symbol_table);
elna_name_statements(parser_node^.statements); elna_name_statements(parser_node^.statements, symbol_table);
parser_node := parser_node^.next; parser_node := parser_node^.next;
if parser_node <> nil then if parser_node <> nil then
@@ -5113,14 +5156,14 @@ begin
end end
end end
proc elna_name_if_statement(parser_node: ^ElnaTreeIfStatement) proc elna_name_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: ^ElnaSymbolTable)
var var
block: ^ElnaTreeConditionalStatements block: ^ElnaTreeConditionalStatements
begin begin
block := parser_node^.conditionals; block := parser_node^.conditionals;
.elna_name_if_statement_conditionals; .elna_name_if_statement_conditionals;
elna_name_conditional_statements(block); elna_name_conditional_statements(block, symbol_table);
block := block^.next; block := block^.next;
if block <> nil then if block <> nil then
@@ -5128,40 +5171,40 @@ begin
end; end;
block := parser_node^._else; block := parser_node^._else;
if block <> nil then if block <> nil then
elna_name_statements(block) elna_name_statements(block, symbol_table)
end end
end end
proc elna_name_return_statement(parser_node: ^ElnaTreeReturnStatement) proc elna_name_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_binary_expression(parser_node^.returned) elna_name_binary_expression(parser_node^.returned, symbol_table)
end end
proc elna_name_assign_statement(parser_node: ^ElnaTreeAssignStatement) proc elna_name_assign_statement(parser_node: ^ElnaTreeAssignStatement, symbol_table: ^ElnaSymbolTable)
begin begin
elna_name_designator(parser_node^.assignee); elna_name_designator(parser_node^.assignee, symbol_table);
elna_name_binary_expression(parser_node^.assignment) elna_name_binary_expression(parser_node^.assignment, symbol_table)
end end
proc elna_name_statement(parser_node: ^ElnaTreeStatement) proc elna_name_statement(parser_node: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable)
begin begin
(* Skipping goto and label declarations. *) (* Skipping goto and label declarations. *)
if parser_node^.kind = ElnaTreeKind.if_statement then if parser_node^.kind = ElnaTreeKind.if_statement then
elna_name_if_statement(parser_node) elna_name_if_statement(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.return_statement then elsif parser_node^.kind = ElnaTreeKind.return_statement then
elna_name_return_statement(parser_node) elna_name_return_statement(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.call then elsif parser_node^.kind = ElnaTreeKind.call then
elna_name_call(parser_node) elna_name_call(parser_node, symbol_table)
elsif parser_node^.kind = ElnaTreeKind.assign_statement then elsif parser_node^.kind = ElnaTreeKind.assign_statement then
elna_name_assign_statement(parser_node) elna_name_assign_statement(parser_node, symbol_table)
end end
end end
proc elna_name_statements(parser_node: ^ElnaTreeStatement) proc elna_name_statements(parser_node: ^ElnaTreeStatement, symbol_table: ^ElnaSymbolTable)
begin begin
.elna_name_statements_loop; .elna_name_statements_loop;
if parser_node <> nil then if parser_node <> nil then
elna_name_statement(parser_node); elna_name_statement(parser_node, symbol_table);
parser_node := parser_node^.next; parser_node := parser_node^.next;
goto elna_name_statements_loop goto elna_name_statements_loop
@@ -5174,28 +5217,23 @@ var
symbol_info: ^ElnaSymbolProcedureInfo symbol_info: ^ElnaSymbolProcedureInfo
return_type: ^ElnaType return_type: ^ElnaType
begin begin
if parser_node^.return_type = nil then symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
return_type := nil if symbol_info^.is_extern = false then
else new_symbol_table := elna_symbol_table_create(symbol_table_global);
return_type := elna_name_type_expression(parser_node^.return_type); symbol_info^.symbol_table := new_symbol_table;
end;
new_symbol_table := elna_symbol_table_create(symbol_table_global);
symbol_info := procedure_info_create(new_symbol_table, return_type);
elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table);
elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table); elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table);
elna_name_statements(parser_node^.body); elna_name_statements(parser_node^.body, new_symbol_table)
end
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info)
end end
proc elna_name_program_body(parser_node: ^ElnaTreeStatement) proc elna_name_program_body(parser_node: ^ElnaTreeStatement)
var var
new_symbol_table: ^ElnaSymbolTable symbol_info: ^ElnaSymbolProcedureInfo
symbol_info: Word
begin begin
new_symbol_table := elna_symbol_table_create(symbol_table_global); symbol_info := elna_symbol_procedure_info_create(nil, false);
symbol_info := procedure_info_create(new_symbol_table); symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info) elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info)
end end
@@ -5514,15 +5552,6 @@ proc elna_type_module_declaration(parser_node: ^ElnaTreeModuleDeclaration)
var var
current_part: ^ElnaTreeDeclaration current_part: ^ElnaTreeDeclaration
begin begin
current_part := parser_node^.types;
.elna_type_module_declaration_type;
if current_part <> nil then
elna_type_type_declaration(current_part);
current_part := current_part^.next;
goto elna_type_module_declaration_type
end;
current_part := parser_node^.procedures; current_part := parser_node^.procedures;
.elna_type_module_declaration_procedure; .elna_type_module_declaration_procedure;
if current_part <> nil then if current_part <> nil then
@@ -5533,6 +5562,74 @@ begin
end end
end end
proc elna_declaration_type_declaration(parser_node: ^ElnaTreeTypeDeclaration)
var
type_info: ^ElnaSymbolTypeInfo
result: ^ElnaType
type_expression: ^ElnaTreeTypeExpression
begin
type_expression := parser_node^.type_expression;
if type_expression^.kind = ElnaTreeKind.named_type_expression then
result := malloc(#size(ElnaTypeAlias));
result^.kind := ElnaTypeKind.alias
elsif type_expression^.kind = ElnaTreeKind.enumeration_type_expression then
result := malloc(#size(ElnaTypeEnumeration));
result^.kind := ElnaTypeKind.enumeration
elsif type_expression^.kind = ElnaTreeKind.record_type_expression then
result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record
elsif type_expression^.kind = ElnaTreeKind.pointer_type_expression then
result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer
elsif type_expression^.kind = ElnaTreeKind.array_type_expression then
result := malloc(#size(ElnaTypeArray));
result^.kind := ElnaTypeKind.array
end;
type_info := elna_symbol_type_info_create(result);
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info)
end
proc elna_declaration_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration)
var
symbol_info: ^ElnaSymbolProcedureInfo
return_type: ^ElnaType
begin
if parser_node^.return_type = nil then
return_type := nil
else
return_type := elna_name_type_expression(parser_node^.return_type);
end;
symbol_info := elna_symbol_procedure_info_create(return_type, parser_node^.is_extern);
symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info)
end
proc elna_declaration_module_declaration(parser_node: ^ElnaTreeModuleDeclaration)
var
current_part: ^ElnaTreeDeclaration
begin
current_part := parser_node^.types;
.elna_declaration_module_declaration_type;
if current_part <> nil then
elna_declaration_type_declaration(current_part);
current_part := current_part^.next;
goto elna_declaration_module_declaration_type
end;
current_part := parser_node^.procedures;
.elna_declaration_module_declaration_procedure;
if current_part <> nil then
elna_declaration_procedure_declaration(current_part);
current_part := current_part^.next;
goto elna_declaration_module_declaration_procedure
end
end
proc elna_error_print_token1(kind: ElnaLexerKind) proc elna_error_print_token1(kind: ElnaLexerKind)
begin begin
if kind = ElnaLexerKind.identifier then if kind = ElnaLexerKind.identifier then
@@ -5575,8 +5672,6 @@ begin
_write_s(stderr, "\"~\"") _write_s(stderr, "\"~\"")
elsif kind = ElnaLexerKind._return then elsif kind = ElnaLexerKind._return then
_write_s(stderr, "\"return\"") _write_s(stderr, "\"return\"")
elsif kind = ElnaLexerKind._program then
_write_s(stderr, "\"program\"")
elsif kind = ElnaLexerKind._cast then elsif kind = ElnaLexerKind._cast then
_write_s(stderr, "\"cast\"") _write_s(stderr, "\"cast\"")
elsif kind = ElnaLexerKind.trait then elsif kind = ElnaLexerKind.trait then
@@ -5635,6 +5730,8 @@ begin
_write_s(stderr, "CHARACTER") _write_s(stderr, "CHARACTER")
elsif kind = ElnaLexerKind.integer then elsif kind = ElnaLexerKind.integer then
_write_s(stderr, "INTEGER") _write_s(stderr, "INTEGER")
elsif kind = ElnaLexerKind.word then
_write_s(stderr, "WORD")
else else
elna_error_print_token2(kind) elna_error_print_token2(kind)
end end
@@ -5642,9 +5739,7 @@ end
proc elna_error_print_token2(kind: ElnaLexerKind) proc elna_error_print_token2(kind: ElnaLexerKind)
begin begin
if kind = ElnaLexerKind.word then if kind = ElnaLexerKind._goto then
_write_s(stderr, "WORD")
elsif kind = ElnaLexerKind._goto then
_write_s(stderr, "\"goto\"") _write_s(stderr, "\"goto\"")
elsif kind = ElnaLexerKind.eof then elsif kind = ElnaLexerKind.eof then
_write_s(stderr, "EOF") _write_s(stderr, "EOF")
@@ -5688,6 +5783,7 @@ begin
compiled := elna_list_empty(@error_list); compiled := elna_list_empty(@error_list);
if compiled then if compiled then
elna_declaration_module_declaration(parser_node);
elna_name_module_declaration(parser_node); elna_name_module_declaration(parser_node);
elna_type_module_declaration(parser_node); elna_type_module_declaration(parser_node);
tac := elna_tac_module_declaration(parser_node); tac := elna_tac_module_declaration(parser_node);
@@ -5713,9 +5809,9 @@ end
* *
* Returns the symbol pointer or nil. * Returns the symbol pointer or nil.
*) *)
proc elna_symbol_table_lookup(symbol_table: ^ElnaSymbolTable, symbol_name: Word, name_length: Word) proc elna_symbol_table_lookup(symbol_table: ^ElnaSymbolTable, symbol_name: ^Char, name_length: Word) -> Pointer
var var
result: Word result: Pointer
symbol_table_length: Word symbol_table_length: Word
current_entry: ^ElnaSymbolEntry current_entry: ^ElnaSymbolEntry
begin begin
@@ -5832,39 +5928,39 @@ begin
word_type^.kind := ElnaTypeKind.primitive; word_type^.kind := ElnaTypeKind.primitive;
word_type^.size := 4; word_type^.size := 4;
word_type^.alignment := 4; word_type^.alignment := 4;
current_info := type_info_create(word_type); current_info := elna_symbol_type_info_create(word_type);
elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info);
int_type := malloc(#size(ElnaType)); int_type := malloc(#size(ElnaType));
int_type^.kind := ElnaTypeKind.primitive; int_type^.kind := ElnaTypeKind.primitive;
int_type^.size := 4; int_type^.size := 4;
int_type^.alignment := 4; int_type^.alignment := 4;
current_info := type_info_create(int_type); current_info := elna_symbol_type_info_create(int_type);
elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info); elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info);
current_type := malloc(#size(ElnaType)); current_type := malloc(#size(ElnaType));
current_type^.kind := ElnaTypeKind.primitive; current_type^.kind := ElnaTypeKind.primitive;
current_type^.size := 4; current_type^.size := 4;
current_type^.alignment := 4; current_type^.alignment := 4;
current_info := type_info_create(current_type); current_info := elna_symbol_type_info_create(current_type);
elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info); elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info);
bool_type := malloc(#size(ElnaType)); bool_type := malloc(#size(ElnaType));
bool_type^.kind := ElnaTypeKind.primitive; bool_type^.kind := ElnaTypeKind.primitive;
bool_type^.size := 1; bool_type^.size := 1;
bool_type^.alignment := 1; bool_type^.alignment := 1;
current_info := type_info_create(bool_type); current_info := elna_symbol_type_info_create(bool_type);
elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info);
char_type := malloc(#size(ElnaType)); char_type := malloc(#size(ElnaType));
char_type^.kind := ElnaTypeKind.primitive; char_type^.kind := ElnaTypeKind.primitive;
char_type^.size := 1; char_type^.size := 1;
char_type^.alignment := 1; char_type^.alignment := 1;
current_info := type_info_create(char_type); current_info := elna_symbol_type_info_create(char_type);
elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info);
elna_symbol_string_build(); elna_symbol_string_build();
current_info := type_info_create(string_type); current_info := elna_symbol_type_info_create(string_type);
elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info) elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info)
end end
+228 -164
View File
@@ -3,15 +3,14 @@
* v. 2.0. If a copy of the MPL was not distributed with this file, You can * v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at https://mozilla.org/MPL/2.0/. * obtain one at https://mozilla.org/MPL/2.0/.
*) *)
program;
(* Stage 23 compiler. *) (* Stage 24 compiler. *)
(* - Support extern procedure declarations. *) (* - Support records refencing themselves in their fields. *)
type type
ElnaListNode = record ElnaListNode = record
next: Word next: ^ElnaListNode
end end
ElnaList = record ElnaList = record
first: ^ElnaListNode; first: ^ElnaListNode;
@@ -35,12 +34,18 @@ type
end end
(* Type representation. *) (* Type representation. *)
ElnaTypeKind = (primitive, enumeration, _record, pointer, array) ElnaTypeKind = (primitive, enumeration, _record, pointer, array, alias)
ElnaType = record ElnaType = record
kind: ElnaTypeKind; kind: ElnaTypeKind;
size: Word; size: Word;
alignment: Word alignment: Word
end end
ElnaTypeAlias = record
kind: ElnaTypeKind;
size: Word;
alignment: Word;
base: ^ElnaType
end
ElnaTypeEnumeration = record ElnaTypeEnumeration = record
kind: ElnaTypeKind; kind: ElnaTypeKind;
size: Word; size: Word;
@@ -174,33 +179,42 @@ type
*) *)
ElnaTreeStatement = record ElnaTreeStatement = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word next: ^ElnaTreeStatement
end
(**
* Conditional statements is a list of pairs: condition and statements.
* Used for example to represent if and elsif blocks with beloning statements.
*)
ElnaTreeConditionalStatements = record
condition: ^ElnaTreeExpression;
statements: ^ElnaTreeStatement;
next: ^ElnaTreeConditionalStatements
end end
ElnaTreeIfStatement = record ElnaTreeIfStatement = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
conditionals: Word; conditionals: ^ElnaTreeConditionalStatements;
_else: ^ElnaTreeStatement _else: ^ElnaTreeStatement
end end
ElnaTreeGotoStatement = record ElnaTreeGotoStatement = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
label: String label: String
end end
ElnaTreeAssignStatement = record ElnaTreeAssignStatement = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
assignee: Word; assignee: Word;
assignment: ^ElnaTreeExpression assignment: ^ElnaTreeExpression
end end
ElnaTreeReturnStatement = record ElnaTreeReturnStatement = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
returned: ^ElnaTreeExpression returned: ^ElnaTreeExpression
end end
ElnaTreeLabelDeclaration = record ElnaTreeLabelDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
label: String label: String
end end
ElnaTreeFieldAccessExpression = record ElnaTreeFieldAccessExpression = record
@@ -217,17 +231,17 @@ type
end end
ElnaTreeEnumeration = record ElnaTreeEnumeration = record
name: String; name: String;
next: Word next: ^ElnaTreeEnumeration
end end
ElnaTreeEnumerationTypeExpression = record ElnaTreeEnumerationTypeExpression = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
members: Word; members: ^ElnaTreeEnumeration;
length: Word length: Word
end end
ElnaTreeField = record ElnaTreeField = record
name: String; name: String;
type_expression: ^ElnaTreeTypeExpression; type_expression: ^ElnaTreeTypeExpression;
next: Word next: ^ElnaTreeField
end end
ElnaTreeRecordTypeExpression = record ElnaTreeRecordTypeExpression = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
@@ -250,31 +264,22 @@ type
ElnaTreeTraitExpression = record ElnaTreeTraitExpression = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
name: String; name: String;
argument: Word argument: ^ElnaTreeTypeExpression
end
(**
* Conditional statements is a list of pairs: condition and statements.
* Used for example to represent if and elsif blocks with beloning statements.
*)
ElnaTreeConditionalStatements = record
condition: ^ElnaTreeExpression;
statements: ^ElnaTreeStatement;
next: Word
end end
ElnaTreeDeclaration = record ElnaTreeDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeDeclaration;
name: String name: String
end end
ElnaTreeVariableDeclaration = record ElnaTreeVariableDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeDeclaration;
name: String; name: String;
type_expression: ^ElnaTreeTypeExpression type_expression: ^ElnaTreeTypeExpression
end end
ElnaTreeProcedureDeclaration = record ElnaTreeProcedureDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeDeclaration;
name: String; name: String;
body: ^ElnaTreeStatement; body: ^ElnaTreeStatement;
temporaries: ^ElnaTreeVariableDeclaration; temporaries: ^ElnaTreeVariableDeclaration;
@@ -284,24 +289,24 @@ type
end end
ElnaTreeModuleDeclaration = record ElnaTreeModuleDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
types: Word; types: ^ElnaTreeDeclaration;
globals: Word; globals: ^ElnaTreeVariableDeclaration;
procedures: ^ElnaTreeProcedureDeclaration; procedures: ^ElnaTreeProcedureDeclaration;
body: ^ElnaTreeStatement body: ^ElnaTreeStatement
end end
ElnaTreeTypeDeclaration = record ElnaTreeTypeDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeDeclaration;
name: String; name: String;
type_expression: ^ElnaTreeTypeExpression type_expression: ^ElnaTreeTypeExpression
end end
ElnaTreeExpressionList = record ElnaTreeExpressionList = record
expression: ^ElnaTreeBinaryExpression; expression: ^ElnaTreeBinaryExpression;
next: Word next: ^ElnaTreeExpressionList
end end
ElnaTreeCall = record ElnaTreeCall = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: ^ElnaTreeStatement;
callee: ^ElnaTreeVariableExpression; callee: ^ElnaTreeVariableExpression;
arguments: ^ElnaTreeExpressionList; arguments: ^ElnaTreeExpressionList;
count: Word count: Word
@@ -310,11 +315,11 @@ type
(* Symbol table information. *) (* Symbol table information. *)
ElnaSymbolEntry = record ElnaSymbolEntry = record
name: String; name: String;
symbol_info: Word symbol_info: ^ElnaSymbolInfo
end end
ElnaSymbolTable = record ElnaSymbolTable = record
count: Word; count: Word;
parent: Word; parent: ^ElnaSymbolTable;
symbols: ^ElnaSymbolEntry symbols: ^ElnaSymbolEntry
end end
ElnaSymbolInfoKind = (type_info, temporary_info, procedure_info) ElnaSymbolInfoKind = (type_info, temporary_info, procedure_info)
@@ -414,7 +419,6 @@ type
_xor, _xor,
not, not,
_return, _return,
_program,
_cast, _cast,
trait, trait,
left_paren, left_paren,
@@ -506,20 +510,20 @@ type
length: Word length: Word
end end
ElnaTacInstruction = record ElnaTacInstruction = record
next: Word; next: ^ElnaListNode;
operator: ElnaTacOperator; operator: ElnaTacOperator;
operands: [4]ElnaTacOperand operands: [4]ElnaTacOperand
end end
ElnaTacProcedure = record ElnaTacProcedure = record
next: Word; next: ^ElnaTacProcedure;
name: String; name: String;
body: ElnaList; body: ElnaList;
parameters: Word; parameters: ^String;
count: Word; count: Word;
symbol_table: ^ElnaSymbolTable symbol_table: ^ElnaSymbolTable
end end
ElnaTacStaticVariable = record ElnaTacStaticVariable = record
next: Word; next: ^ElnaTacStaticVariable;
name: String; name: String;
body: Word body: Word
end end
@@ -567,12 +571,12 @@ type
offset: Word offset: Word
end end
ElnaRtlStaticVariable = record ElnaRtlStaticVariable = record
next: Word; next: ^ElnaRtlStaticVariable;
name: String; name: String;
body: Word body: Word
end end
ElnaRtlProcedure = record ElnaRtlProcedure = record
next: Word; next: ^ElnaRtlProcedure;
name: String; name: String;
body: ElnaList; body: ElnaList;
variable_map: ^ElnaSymbolTable variable_map: ^ElnaSymbolTable
@@ -590,7 +594,7 @@ type
alignment: Word alignment: Word
end end
ElnaRtlInstruction = record ElnaRtlInstruction = record
next: Word; next: ^ElnaListNode;
operator: ElnaRtlOperator; operator: ElnaRtlOperator;
operands: [3]ElnaRtlOperand; operands: [3]ElnaRtlOperand;
types: [2]^ElnaRtlType types: [2]^ElnaRtlType
@@ -646,12 +650,12 @@ type
ElnaErrorKind = (unexpected_token) ElnaErrorKind = (unexpected_token)
ElnaError = record ElnaError = record
next: Word; next: ^ElnaListNode;
kind: ElnaErrorKind; kind: ElnaErrorKind;
position: ElnaPosition position: ElnaPosition
end end
ElnaErrorUnexpectedToken = record ElnaErrorUnexpectedToken = record
next: Word; next: ^ElnaListNode;
kind: ElnaErrorKind; kind: ElnaErrorKind;
position: ElnaPosition; position: ElnaPosition;
expected: ^ElnaLexerKind; expected: ^ElnaLexerKind;
@@ -905,7 +909,7 @@ begin
operand^.value := buffer; operand^.value := buffer;
operand^.length := strlen(buffer); operand^.length := strlen(buffer);
temporary_info := temporary_info_create(1, variable_type); temporary_info := elna_symbol_temporary_info_create(1, variable_type);
elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info) elna_symbol_table_enter(symbol_table, buffer, operand^.length, temporary_info)
end end
@@ -3937,15 +3941,13 @@ end
* *
* Returns enumeration type description. * Returns enumeration type description.
*) *)
proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression) -> ^ElnaTypeEnumeration proc elna_name_enumeration_type_expression(parser_node: ^ElnaTreeEnumerationTypeExpression,
result: ^ElnaTypeEnumeration)
var var
result: ^ElnaTypeEnumeration
memory_start: ^ElnaTreeEnumeration memory_start: ^ElnaTreeEnumeration
member_count: Word member_count: Word
member_array_current: ^String member_array_current: ^String
begin begin
result := malloc(#size(ElnaTypeEnumeration));
memory_start := parser_node^.members; memory_start := parser_node^.members;
member_count := parser_node^.length; member_count := parser_node^.length;
@@ -3962,58 +3964,43 @@ begin
member_count := member_count - 1; member_count := member_count - 1;
goto elna_name_type_enumeration_loop goto elna_name_type_enumeration_loop
end; end;
result^.kind := ElnaTypeKind.enumeration;
result^.size := 4; result^.size := 4;
result^.alignment := 4; result^.alignment := 4;
result^.length := parser_node^.length; result^.length := parser_node^.length
return result
end end
proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression) -> ^ElnaTypePointer proc elna_name_pointer_type_expression(parser_node: ^ElnaTreePointerTypeExpression,
var result: ^ElnaTypePointer)
result: ^ElnaTypePointer
begin begin
result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer;
result^.size := 4; result^.size := 4;
result^.alignment := 4; result^.alignment := 4;
result^.base := elna_name_type_expression(parser_node^.base); result^.base := elna_name_type_expression(parser_node^.base)
return result
end end
proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression) -> ^ElnaTypeArray proc elna_name_array_type_expression(parser_node: ^ElnaTreeArrayTypeExpression,
result: ^ElnaTypeArray)
var var
base: ^ElnaType base: ^ElnaType
result: ^ElnaTypeArray
length: ^ElnaTreeIntegerLiteral length: ^ElnaTreeIntegerLiteral
begin begin
result := malloc(#size(ElnaTypeArray));
base := elna_name_type_expression(parser_node^.base); base := elna_name_type_expression(parser_node^.base);
length := parser_node^.length; length := parser_node^.length;
result^.kind := ElnaTypeKind.array;
(* Array size in bytes. *) (* Array size in bytes. *)
result^.size := base^.size * length^.value; result^.size := base^.size * length^.value;
result^.alignment := base^.alignment; result^.alignment := base^.alignment;
result^.base := base; result^.base := base;
result^.length := length^.value; result^.length := length^.value
return result
end end
proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression) -> ^ElnaTypeRecord proc elna_name_record_type_expression(parser_node: ^ElnaTreeRecordTypeExpression,
result: ^ElnaTypeRecord)
var var
result: ^ElnaTypeRecord result: ^ElnaTypeRecord
tree_field: ^ElnaTreeField tree_field: ^ElnaTreeField
member_array_current: ^ElnaTypeField member_array_current: ^ElnaTypeField
field_type: ^ElnaType field_type: ^ElnaType
begin begin
result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record;
result^.size := 0; result^.size := 0;
result^.alignment := 0; result^.alignment := 0;
result^.length := 0; result^.length := 0;
@@ -4038,9 +4025,7 @@ begin
tree_field := tree_field^.next; tree_field := tree_field^.next;
result^.length := result^.length + 1; result^.length := result^.length + 1;
goto elna_name_type_record_loop goto elna_name_type_record_loop
end; end
return result
end end
proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression
@@ -4131,7 +4116,21 @@ begin
return result return result
end end
proc elna_name_type_expression(parser_node: ^ElnaTreeNode) -> ^ElnaType proc elna_name_alias_type_expression(parser_node: ^ElnaTreeNamedTypeExpression, result: ^ElnaTypeAlias)
var
type_symbol: ^ElnaSymbolTypeInfo
aliased_type: ^ElnaType
begin
type_symbol := elna_symbol_table_lookup(symbol_table_global,
parser_node^.name.ptr, parser_node^.name.length);
aliased_type := type_symbol^._type;
result^.size := aliased_type^.size;
result^.alignment := aliased_type^.alignment;
result^.base := aliased_type
end
proc elna_name_type_expression(parser_node: ^ElnaTreeTypeExpression) -> ^ElnaType
var var
named_type_expression: ^ElnaTreeNamedTypeExpression named_type_expression: ^ElnaTreeNamedTypeExpression
type_symbol: ^ElnaSymbolTypeInfo type_symbol: ^ElnaSymbolTypeInfo
@@ -4144,19 +4143,31 @@ begin
named_type_expression^.name.ptr, named_type_expression^.name.length); named_type_expression^.name.ptr, named_type_expression^.name.length);
result := type_symbol^._type result := type_symbol^._type
elsif parser_node^.kind = ElnaTreeKind.enumeration_type_expression then elsif parser_node^.kind = ElnaTreeKind.enumeration_type_expression then
result := elna_name_enumeration_type_expression(parser_node) result := malloc(#size(ElnaTypeEnumeration));
result^.kind := ElnaTypeKind.enumeration;
elna_name_enumeration_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.record_type_expression then elsif parser_node^.kind = ElnaTreeKind.record_type_expression then
result := elna_name_record_type_expression(parser_node) result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record;
elna_name_record_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then elsif parser_node^.kind = ElnaTreeKind.pointer_type_expression then
result := elna_name_pointer_type_expression(parser_node) result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer;
elna_name_pointer_type_expression(parser_node, result)
elsif parser_node^.kind = ElnaTreeKind.array_type_expression then elsif parser_node^.kind = ElnaTreeKind.array_type_expression then
result := elna_name_array_type_expression(parser_node) result := malloc(#size(ElnaTypeArray));
result^.kind := ElnaTypeKind.array;
elna_name_array_type_expression(parser_node, result)
end; end;
return result return result
end end
proc type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo proc elna_symbol_type_info_create(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo
var var
result: ^ElnaSymbolTypeInfo result: ^ElnaSymbolTypeInfo
begin begin
@@ -4172,7 +4183,7 @@ end
* attr - Local variable attributes. * attr - Local variable attributes.
* temporary_type - Local variable type. * temporary_type - Local variable type.
*) *)
proc temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo proc elna_symbol_temporary_info_create(attr: Word, temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo
var var
result: ^ElnaSymbolTemporaryInfo result: ^ElnaSymbolTemporaryInfo
begin begin
@@ -4190,14 +4201,12 @@ end
* Parameters: * Parameters:
* symbol_table - Local symbol table. * symbol_table - Local symbol table.
*) *)
proc procedure_info_create(symbol_table: ^ElnaSymbolTable, return_type: ^ElnaRtlType, proc elna_symbol_procedure_info_create(return_type: ^ElnaRtlType, is_extern: Bool) -> ^ElnaSymbolProcedureInfo
is_extern: Bool) -> ^ElnaSymbolProcedureInfo
var var
result: ^ElnaSymbolProcedureInfo result: ^ElnaSymbolProcedureInfo
begin begin
result := malloc(#size(ElnaSymbolProcedureInfo)); result := malloc(#size(ElnaSymbolProcedureInfo));
result^.kind := ElnaSymbolInfoKind.procedure_info; result^.kind := ElnaSymbolInfoKind.procedure_info;
result^.symbol_table := symbol_table;
result^.return_type := return_type; result^.return_type := return_type;
result^.is_extern := is_extern; result^.is_extern := is_extern;
@@ -4210,12 +4219,12 @@ end
*) *)
proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable) proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: ^ElnaSymbolTable)
var var
info: Word info: ^ElnaSymbolTemporaryInfo
variable_type: Word variable_type: ^ElnaType
begin begin
variable_type := elna_name_type_expression(parser_node^.type_expression); variable_type := elna_name_type_expression(parser_node^.type_expression);
info := temporary_info_create(0, variable_type); info := elna_symbol_temporary_info_create(0, variable_type);
elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info) elna_symbol_table_enter(symbol_table, parser_node^.name.ptr, parser_node^.name.length, info)
end end
@@ -4767,17 +4776,25 @@ end
proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration) proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration)
var var
symbol_type: ^ElnaType
type_info: ^ElnaSymbolTypeInfo type_info: ^ElnaSymbolTypeInfo
type_stub: ^ElnaType
type_expression: ^ElnaTreeTypeExpression
begin begin
symbol_type := elna_name_type_expression(parser_node^.type_expression); type_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
type_info := type_info_create(symbol_type); type_stub := type_info^._type;
type_expression := parser_node^.type_expression;
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info) if type_stub^.kind = ElnaTypeKind.alias then
end elna_name_alias_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.enumeration then
proc elna_type_type_declaration(parser_node: Word) elna_name_enumeration_type_expression(type_expression, type_stub)
begin elsif type_stub^.kind = ElnaTypeKind._record then
elna_name_record_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.pointer then
elna_name_pointer_type_expression(type_expression, type_stub)
elsif type_stub^.kind = ElnaTypeKind.array then
elna_name_array_type_expression(type_expression, type_stub)
end
end end
proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration proc elna_parser_type_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration
@@ -4979,35 +4996,30 @@ proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaL
var var
result: ^ElnaTreeModuleDeclaration result: ^ElnaTreeModuleDeclaration
begin begin
result := nil; result := malloc(#size(ElnaTreeModuleDeclaration));
if elna_parser_expect(cursor, ElnaLexerKind._program, error_list) <> nil then result^.kind := ElnaTreeKind.module_declaration;
if elna_parser_expect(cursor, ElnaLexerKind.semicolon, error_list) <> nil then
result := malloc(#size(ElnaTreeModuleDeclaration));
result^.kind := ElnaTreeKind.module_declaration;
result^.types := elna_parser_type_part(cursor, error_list); result^.types := elna_parser_type_part(cursor, error_list);
if elna_list_empty(error_list) = false then if elna_list_empty(error_list) = false then
result := free_and_nil(result) result := free_and_nil(result)
end; end;
if result <> nil then if result <> nil then
result^.globals := elna_parser_var_part(cursor, error_list); result^.globals := elna_parser_var_part(cursor, error_list);
end; end;
if elna_list_empty(error_list) = false then if elna_list_empty(error_list) = false then
result := free_and_nil(result) result := free_and_nil(result)
end; end;
if result <> nil then if result <> nil then
result^.procedures := elna_parser_procedures(cursor, error_list); result^.procedures := elna_parser_procedures(cursor, error_list);
end; end;
if elna_list_empty(error_list) = false then if elna_list_empty(error_list) = false then
result := free_and_nil(result) result := free_and_nil(result)
end; end;
if result <> nil then if result <> nil then
result^.body := elna_parser_program_body(cursor, error_list) result^.body := elna_parser_program_body(cursor, error_list)
end; end;
if elna_list_empty(error_list) = false then if elna_list_empty(error_list) = false then
result := free_and_nil(result) result := free_and_nil(result)
end
end
end; end;
return result return result
end end
@@ -5107,6 +5119,7 @@ var
begin begin
callee_symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.callee^.name.ptr, parser_node^.callee^.name.length); callee_symbol := elna_symbol_table_lookup(symbol_table_global, parser_node^.callee^.name.ptr, parser_node^.callee^.name.length);
if callee_symbol = nil then if callee_symbol = nil then
(* DEBUG *)
_write_s(stdout, "# Undefined symbol "); _write_s(stdout, "# Undefined symbol ");
_write_s(stdout, parser_node^.callee^.name); _write_s(stdout, parser_node^.callee^.name);
_write_s(stdout, ".\n") _write_s(stdout, ".\n")
@@ -5229,28 +5242,23 @@ var
symbol_info: ^ElnaSymbolProcedureInfo symbol_info: ^ElnaSymbolProcedureInfo
return_type: ^ElnaType return_type: ^ElnaType
begin begin
if parser_node^.return_type = nil then symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length);
return_type := nil if symbol_info^.is_extern = false then
else new_symbol_table := elna_symbol_table_create(symbol_table_global);
return_type := elna_name_type_expression(parser_node^.return_type); symbol_info^.symbol_table := new_symbol_table;
end;
new_symbol_table := elna_symbol_table_create(symbol_table_global);
symbol_info := procedure_info_create(new_symbol_table, return_type, parser_node^.is_extern);
elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table); elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table);
elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table); elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table);
elna_name_statements(parser_node^.body, new_symbol_table); elna_name_statements(parser_node^.body, new_symbol_table)
end
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info)
end end
proc elna_name_program_body(parser_node: ^ElnaTreeStatement) proc elna_name_program_body(parser_node: ^ElnaTreeStatement)
var var
new_symbol_table: ^ElnaSymbolTable symbol_info: ^ElnaSymbolProcedureInfo
symbol_info: Word
begin begin
new_symbol_table := elna_symbol_table_create(symbol_table_global); symbol_info := elna_symbol_procedure_info_create(nil, false);
symbol_info := procedure_info_create(new_symbol_table, nil, false); symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info) elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info)
end end
@@ -5569,15 +5577,6 @@ proc elna_type_module_declaration(parser_node: ^ElnaTreeModuleDeclaration)
var var
current_part: ^ElnaTreeDeclaration current_part: ^ElnaTreeDeclaration
begin begin
current_part := parser_node^.types;
.elna_type_module_declaration_type;
if current_part <> nil then
elna_type_type_declaration(current_part);
current_part := current_part^.next;
goto elna_type_module_declaration_type
end;
current_part := parser_node^.procedures; current_part := parser_node^.procedures;
.elna_type_module_declaration_procedure; .elna_type_module_declaration_procedure;
if current_part <> nil then if current_part <> nil then
@@ -5588,6 +5587,74 @@ begin
end end
end end
proc elna_declaration_type_declaration(parser_node: ^ElnaTreeTypeDeclaration)
var
type_info: ^ElnaSymbolTypeInfo
result: ^ElnaType
type_expression: ^ElnaTreeTypeExpression
begin
type_expression := parser_node^.type_expression;
if type_expression^.kind = ElnaTreeKind.named_type_expression then
result := malloc(#size(ElnaTypeAlias));
result^.kind := ElnaTypeKind.alias
elsif type_expression^.kind = ElnaTreeKind.enumeration_type_expression then
result := malloc(#size(ElnaTypeEnumeration));
result^.kind := ElnaTypeKind.enumeration
elsif type_expression^.kind = ElnaTreeKind.record_type_expression then
result := malloc(#size(ElnaTypeRecord));
result^.kind := ElnaTypeKind._record
elsif type_expression^.kind = ElnaTreeKind.pointer_type_expression then
result := malloc(#size(ElnaTypePointer));
result^.kind := ElnaTypeKind.pointer
elsif type_expression^.kind = ElnaTreeKind.array_type_expression then
result := malloc(#size(ElnaTypeArray));
result^.kind := ElnaTypeKind.array
end;
type_info := elna_symbol_type_info_create(result);
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, type_info)
end
proc elna_declaration_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration)
var
symbol_info: ^ElnaSymbolProcedureInfo
return_type: ^ElnaType
begin
if parser_node^.return_type = nil then
return_type := nil
else
return_type := elna_name_type_expression(parser_node^.return_type);
end;
symbol_info := elna_symbol_procedure_info_create(return_type, parser_node^.is_extern);
symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
elna_symbol_table_enter(symbol_table_global, parser_node^.name.ptr, parser_node^.name.length, symbol_info)
end
proc elna_declaration_module_declaration(parser_node: ^ElnaTreeModuleDeclaration)
var
current_part: ^ElnaTreeDeclaration
begin
current_part := parser_node^.types;
.elna_declaration_module_declaration_type;
if current_part <> nil then
elna_declaration_type_declaration(current_part);
current_part := current_part^.next;
goto elna_declaration_module_declaration_type
end;
current_part := parser_node^.procedures;
.elna_declaration_module_declaration_procedure;
if current_part <> nil then
elna_declaration_procedure_declaration(current_part);
current_part := current_part^.next;
goto elna_declaration_module_declaration_procedure
end
end
proc elna_error_print_token1(kind: ElnaLexerKind) proc elna_error_print_token1(kind: ElnaLexerKind)
begin begin
if kind = ElnaLexerKind.identifier then if kind = ElnaLexerKind.identifier then
@@ -5630,8 +5697,6 @@ begin
_write_s(stderr, "\"~\"") _write_s(stderr, "\"~\"")
elsif kind = ElnaLexerKind._return then elsif kind = ElnaLexerKind._return then
_write_s(stderr, "\"return\"") _write_s(stderr, "\"return\"")
elsif kind = ElnaLexerKind._program then
_write_s(stderr, "\"program\"")
elsif kind = ElnaLexerKind._cast then elsif kind = ElnaLexerKind._cast then
_write_s(stderr, "\"cast\"") _write_s(stderr, "\"cast\"")
elsif kind = ElnaLexerKind.trait then elsif kind = ElnaLexerKind.trait then
@@ -5690,6 +5755,8 @@ begin
_write_s(stderr, "CHARACTER") _write_s(stderr, "CHARACTER")
elsif kind = ElnaLexerKind.integer then elsif kind = ElnaLexerKind.integer then
_write_s(stderr, "INTEGER") _write_s(stderr, "INTEGER")
elsif kind = ElnaLexerKind.word then
_write_s(stderr, "WORD")
else else
elna_error_print_token2(kind) elna_error_print_token2(kind)
end end
@@ -5697,9 +5764,7 @@ end
proc elna_error_print_token2(kind: ElnaLexerKind) proc elna_error_print_token2(kind: ElnaLexerKind)
begin begin
if kind = ElnaLexerKind.word then if kind = ElnaLexerKind._goto then
_write_s(stderr, "WORD")
elsif kind = ElnaLexerKind._goto then
_write_s(stderr, "\"goto\"") _write_s(stderr, "\"goto\"")
elsif kind = ElnaLexerKind.eof then elsif kind = ElnaLexerKind.eof then
_write_s(stderr, "EOF") _write_s(stderr, "EOF")
@@ -5743,6 +5808,7 @@ begin
compiled := elna_list_empty(@error_list); compiled := elna_list_empty(@error_list);
if compiled then if compiled then
elna_declaration_module_declaration(parser_node);
elna_name_module_declaration(parser_node); elna_name_module_declaration(parser_node);
elna_type_module_declaration(parser_node); elna_type_module_declaration(parser_node);
tac := elna_tac_module_declaration(parser_node); tac := elna_tac_module_declaration(parser_node);
@@ -5887,39 +5953,39 @@ begin
word_type^.kind := ElnaTypeKind.primitive; word_type^.kind := ElnaTypeKind.primitive;
word_type^.size := 4; word_type^.size := 4;
word_type^.alignment := 4; word_type^.alignment := 4;
current_info := type_info_create(word_type); current_info := elna_symbol_type_info_create(word_type);
elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info);
int_type := malloc(#size(ElnaType)); int_type := malloc(#size(ElnaType));
int_type^.kind := ElnaTypeKind.primitive; int_type^.kind := ElnaTypeKind.primitive;
int_type^.size := 4; int_type^.size := 4;
int_type^.alignment := 4; int_type^.alignment := 4;
current_info := type_info_create(int_type); current_info := elna_symbol_type_info_create(int_type);
elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info); elna_symbol_table_enter(symbol_table_global, "Int".ptr, 3, current_info);
current_type := malloc(#size(ElnaType)); current_type := malloc(#size(ElnaType));
current_type^.kind := ElnaTypeKind.primitive; current_type^.kind := ElnaTypeKind.primitive;
current_type^.size := 4; current_type^.size := 4;
current_type^.alignment := 4; current_type^.alignment := 4;
current_info := type_info_create(current_type); current_info := elna_symbol_type_info_create(current_type);
elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info); elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info);
bool_type := malloc(#size(ElnaType)); bool_type := malloc(#size(ElnaType));
bool_type^.kind := ElnaTypeKind.primitive; bool_type^.kind := ElnaTypeKind.primitive;
bool_type^.size := 1; bool_type^.size := 1;
bool_type^.alignment := 1; bool_type^.alignment := 1;
current_info := type_info_create(bool_type); current_info := elna_symbol_type_info_create(bool_type);
elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info);
char_type := malloc(#size(ElnaType)); char_type := malloc(#size(ElnaType));
char_type^.kind := ElnaTypeKind.primitive; char_type^.kind := ElnaTypeKind.primitive;
char_type^.size := 1; char_type^.size := 1;
char_type^.alignment := 1; char_type^.alignment := 1;
current_info := type_info_create(char_type); current_info := elna_symbol_type_info_create(char_type);
elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info); elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info);
elna_symbol_string_build(); elna_symbol_string_build();
current_info := type_info_create(string_type); current_info := elna_symbol_type_info_create(string_type);
elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info) elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info)
end end
@@ -6359,8 +6425,6 @@ begin
result^.kind := ElnaLexerKind._or result^.kind := ElnaLexerKind._or
elsif string_compare(position_start, result_length, "xor") then elsif string_compare(position_start, result_length, "xor") then
result^.kind := ElnaLexerKind._xor result^.kind := ElnaLexerKind._xor
elsif string_compare(position_start, result_length, "program") then
result^.kind := ElnaLexerKind._program
elsif string_compare(position_start, result_length, "nil") then elsif string_compare(position_start, result_length, "nil") then
result^.kind := ElnaLexerKind.null result^.kind := ElnaLexerKind.null
elsif string_compare(position_start, result_length, "true") then elsif string_compare(position_start, result_length, "true") then