Allow program module body
This commit is contained in:
30
Rakefile
30
Rakefile
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user