Allow program module body

This commit is contained in:
2026-03-20 21:46:11 +01:00
parent 5230d65efd
commit cf23f77eac
2 changed files with 141 additions and 52 deletions

View File

@@ -36,22 +36,22 @@ end
desc 'Convert previous stage language into the current stage language' desc 'Convert previous stage language into the current stage language'
task :convert do task :convert do
File.open('boot/stage20/cl.elna', 'w') do |current_stage| File.open('boot/stage21/cl.elna', 'w') do |current_stage|
File.readlines('boot/stage19/cl.elna').each do |line| File.readlines('boot/stage20/cl.elna').each do |line|
current_stage << line current_stage << line
end end
current_stage << <<~FUN # current_stage << <<~FUN
#
proc f(m: ElnaInstructionModule); # proc f(m: ElnaInstructionModule);
begin # begin
end; # end;
#
proc g(); # proc g();
var # var
x: ElnaInstructionModule; # x: ElnaInstructionModule;
begin # begin
f(x) # f(x)
end; # end;
FUN # FUN
end end
end end

View File

@@ -7,6 +7,8 @@ program;
(* Stage 20 compiler. *) (* Stage 20 compiler. *)
(* - Allow program module body. *)
type type
ElnaListNode = record ElnaListNode = record
next: Word next: Word
@@ -261,22 +263,23 @@ type
name: Word; name: Word;
length: Word length: Word
end; end;
ElnaTreeModuleDeclaration = record
kind: ElnaTreeKind;
types: Word;
globals: Word;
procedures: Word
end;
ElnaTreeProcedureDeclaration = record ElnaTreeProcedureDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: Word;
name: Word; name: Word;
length: Word; length: Word;
body: Word; body: ^ElnaTreeStatement;
temporaries: Word; temporaries: Word;
parameters: Word; parameters: Word;
return_type: ^ElnaTreeNode return_type: ^ElnaTreeNode
end; end;
ElnaTreeModuleDeclaration = record
kind: ElnaTreeKind;
types: Word;
globals: Word;
procedures: ^ElnaTreeProcedureDeclaration;
body: ^ElnaTreeStatement
end;
ElnaTreeTypeDeclaration = record ElnaTreeTypeDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: Word;
@@ -844,7 +847,7 @@ begin
operand_value^ := buffer; operand_value^ := buffer;
operand_length^ := strlen(buffer); operand_length^ := strlen(buffer);
temporary_info := _temporary_info_create(1, word_type); temporary_info := temporary_info_create(1, word_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;
@@ -2923,7 +2926,7 @@ begin
return result return result
end; end;
proc elna_parser_statements(cursor: ^ElnaLexerCursor); proc elna_parser_statements(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStatement;
var var
previous_statement: ^ElnaTreeStatement; previous_statement: ^ElnaTreeStatement;
next_statement: ^ElnaTreeStatement; next_statement: ^ElnaTreeStatement;
@@ -3357,7 +3360,7 @@ begin
return result return result
end; end;
proc _type_info_create(type_representation: Word); proc type_info_create(type_representation: Word);
var var
result: ^ElnaSymbolTypeInfo; result: ^ElnaSymbolTypeInfo;
begin begin
@@ -3373,7 +3376,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: Word); proc temporary_info_create(attr: Word, temporary_type: Word);
var var
result: ^ElnaSymbolTemporaryInfo; result: ^ElnaSymbolTemporaryInfo;
begin begin
@@ -3391,7 +3394,7 @@ end;
* Parameters: * Parameters:
* symbol_table - Local symbol table. * symbol_table - Local symbol table.
*) *)
proc _procedure_info_create(symbol_table: ^ElnaSymbolTable); proc procedure_info_create(symbol_table: ^ElnaSymbolTable);
var var
result: ^ElnaSymbolProcedureInfo; result: ^ElnaSymbolProcedureInfo;
begin begin
@@ -3413,7 +3416,7 @@ var
begin begin
variable_type := elna_name_type_expression(parser_node^._type); variable_type := elna_name_type_expression(parser_node^._type);
info := _temporary_info_create(0, variable_type); info := temporary_info_create(0, variable_type);
elna_symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info) elna_symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info)
end; end;
@@ -3428,7 +3431,7 @@ begin
end end
end; end;
proc elna_parser_procedure_declaration(cursor: ^ElnaLexerCursor); proc elna_parser_procedure_declaration(cursor: ^ElnaLexerCursor) -> ^ElnaTreeProcedureDeclaration;
var var
next_declaration: ^ElnaTreeDeclaration; next_declaration: ^ElnaTreeDeclaration;
current_declaration: ^ElnaTreeDeclaration; current_declaration: ^ElnaTreeDeclaration;
@@ -3718,7 +3721,7 @@ begin
return result return result
end; end;
proc elna_parser_procedures(cursor: ^ElnaLexerCursor); proc elna_parser_procedures(cursor: ^ElnaLexerCursor) -> ^ElnaTreeDeclaration;
var var
parser_node: ^ElnaTreeDeclaration; parser_node: ^ElnaTreeDeclaration;
result: ^ElnaTreeDeclaration; result: ^ElnaTreeDeclaration;
@@ -3804,7 +3807,7 @@ begin
return first_copy return first_copy
end; end;
proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration); proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration) -> ^ElnaTacProcedure;
var var
result: ^ElnaTacProcedure; result: ^ElnaTacProcedure;
current_procedure: ^ElnaTacProcedure; current_procedure: ^ElnaTacProcedure;
@@ -3880,7 +3883,7 @@ begin
parser_node := parser_node^._type; parser_node := parser_node^._type;
type_info := elna_name_type_expression(parser_node); type_info := elna_name_type_expression(parser_node);
type_info := _type_info_create(type_info); type_info := type_info_create(type_info);
elna_symbol_table_enter(@symbol_table_global, type_name, name_length, type_info) elna_symbol_table_enter(@symbol_table_global, type_name, name_length, type_info)
end; end;
@@ -4032,7 +4035,22 @@ begin
return first_variable return first_variable
end; end;
proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList); proc elna_parser_program_body(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStatement;
var
result: ^ElnaTreeStatement;
token: ^ElnaLexerToken;
begin
result := nil;
token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind._begin then
elna_lexer_read(cursor);
result := elna_parser_statements(cursor);
end;
return result
end;
proc elna_parser_module_declaration(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration;
var var
parser_node: Word; parser_node: Word;
result: ^ElnaTreeModuleDeclaration; result: ^ElnaTreeModuleDeclaration;
@@ -4057,19 +4075,63 @@ begin
result^.types := elna_parser_type_part(cursor); result^.types := elna_parser_type_part(cursor);
result^.globals := elna_parser_var_part(cursor); result^.globals := elna_parser_var_part(cursor);
result^.procedures := elna_parser_procedures(cursor) result^.procedures := elna_parser_procedures(cursor);
result^.body := elna_parser_program_body(cursor)
end; end;
return result return result
end; end;
proc elna_tac_program_body(parser_node: ^ElnaTreeStatement);
var
result: ^ElnaTacProcedure;
symbol_info: ^ElnaSymbolProcedureInfo;
begin
result := malloc(#size(ElnaTacProcedure));
result^.next := nil;
elna_list_initialize(@result^.body);
result^.name := "main";
result^.length := 4;
symbol_info := elna_symbol_table_lookup(@symbol_table_global, "main", 4);
result^.symbol_table := symbol_info^.symbol_table;
result^.parameters := nil;
result^.count := 0;
elna_tac_statements(@result^.body, parser_node, result^.symbol_table);
return result
end;
proc elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration); proc elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration);
var var
result: ^ElnaInstructionModule; result: ^ElnaInstructionModule;
code: ^ElnaTacProcedure;
begin begin
result := malloc(#size(ElnaInstructionModule)); result := malloc(#size(ElnaInstructionModule));
result^.data := elna_tac_var_part(parser_node^.globals); result^.data := elna_tac_var_part(parser_node^.globals);
result^.code := elna_tac_procedures(parser_node^.procedures); result^.code := elna_tac_procedures(parser_node^.procedures);
if parser_node^.body <> nil then
code := result^.code;
if code = nil then
result^.code := elna_tac_program_body(parser_node^.body);
goto elna_tac_module_declaration_end
end;
.elna_tac_module_declaration_loop;
if code^.next = nil then
code^.next := elna_tac_program_body(parser_node^.body)
else
code := code^.next;
goto elna_tac_module_declaration_loop
end
end;
.elna_tac_module_declaration_end;
return result return result
end; end;
@@ -4079,7 +4141,7 @@ var
symbol_info: Word; symbol_info: Word;
begin begin
new_symbol_table := elna_symbol_table_create(); new_symbol_table := elna_symbol_table_create();
symbol_info := _procedure_info_create(new_symbol_table); symbol_info := procedure_info_create(new_symbol_table);
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);
@@ -4087,6 +4149,17 @@ begin
elna_symbol_table_enter(@symbol_table_global, parser_node^.name, parser_node^.length, symbol_info) elna_symbol_table_enter(@symbol_table_global, parser_node^.name, parser_node^.length, symbol_info)
end; end;
proc elna_name_program_body(parser_node: ^ElnaTreeStatement);
var
new_symbol_table: ^ElnaSymbolTable;
symbol_info: Word;
begin
new_symbol_table := elna_symbol_table_create();
symbol_info := procedure_info_create(new_symbol_table);
elna_symbol_table_enter(@symbol_table_global, "main", 4, symbol_info)
end;
proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable); proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable);
begin begin
.elna_type_conditional_statements_loop; .elna_type_conditional_statements_loop;
@@ -4392,6 +4465,9 @@ begin
current_part := current_part^.next; current_part := current_part^.next;
goto elna_name_module_declaration_procedure goto elna_name_module_declaration_procedure
end;
if parser_node^.body <> nil then
elna_name_program_body(parser_node^.body)
end end
end; end;
@@ -4418,17 +4494,19 @@ begin
end end
end; end;
proc _compile(cursor: ^ElnaLexerCursor); proc compile();
var var
parser_node: Word; parser_node: Word;
tac: Word; tac: Word;
rtl: Word; rtl: Word;
error_list: ElnaList; error_list: ElnaList;
compiled: Word; compiled: Word;
lexer_state: ElnaLexerCursor;
begin begin
elna_lexer_initialize(@lexer_state, source_code);
elna_list_initialize(@error_list); elna_list_initialize(@error_list);
parser_node := elna_parser_module_declaration(cursor, @error_list); parser_node := elna_parser_module_declaration(@lexer_state, @error_list);
compiled := error_list.first = nil; compiled := error_list.first = nil;
if compiled then if compiled then
@@ -4559,22 +4637,30 @@ 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 := type_info_create(word_type);
elna_symbol_table_enter(@symbol_table_global, "Word", 4, current_info); elna_symbol_table_enter(@symbol_table_global, "Word", 4, 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 := type_info_create(current_type);
elna_symbol_table_enter(@symbol_table_global, "Pointer", 7, current_info); elna_symbol_table_enter(@symbol_table_global, "Pointer", 7, 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 := 1; current_type^.size := 1;
current_type^.alignment := 1; current_type^.alignment := 1;
current_info := _type_info_create(current_type); current_info := type_info_create(current_type);
elna_symbol_table_enter(@symbol_table_global, "Bool", 4, current_info); elna_symbol_table_enter(@symbol_table_global, "Bool", 4, current_info);
current_type := malloc(#size(ElnaType));
current_type^.kind := ElnaTypeKind.primitive;
current_type^.size := 1;
current_type^.alignment := 1;
current_info := type_info_create(current_type);
elna_symbol_table_enter(@symbol_table_global, "Char", 4, current_info);
end; end;
(** (**
@@ -5235,25 +5321,17 @@ begin
return token return token
end; end;
proc _initialize_global_state(); proc initialize_global_state();
begin begin
compiler_strings_position := @compiler_strings; compiler_strings_position := @compiler_strings;
source_code := malloc(495616) source_code := malloc(495616)
end; end;
(* proc read_source();
* Entry point.
*)
proc main();
var var
last_read: Word; last_read: Word;
offset: Word; offset: Word;
lexer_state: ElnaLexerCursor;
begin begin
_initialize_global_state();
elna_lexer_initialize(@lexer_state, source_code);
elna_symbol_table_build();
(* Read the source from the standard input. *) (* Read the source from the standard input. *)
offset := source_code; offset := source_code;
@@ -5263,8 +5341,19 @@ begin
if last_read > 0 then if last_read > 0 then
offset := offset + last_read; offset := offset + last_read;
goto start_read goto start_read
end; end
if _compile(@lexer_state) then end;
(*
* Entry point.
*)
proc main();
begin
initialize_global_state();
elna_symbol_table_build();
read_source();
if compile() then
exit(0) exit(0)
else else
exit(4) exit(4)