1
0

Use buffered I/O

This commit is contained in:
2026-06-19 12:29:18 +02:00
parent b58f8a8c45
commit 9515e2f77e
2 changed files with 200 additions and 195 deletions
+5 -15
View File
@@ -36,28 +36,18 @@ 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/stage23/cl.elna', 'w') do |current_stage| File.open('boot/stage24/cl.elna', 'w') do |current_stage|
seen_proc = false seen_proc = false
File.readlines('boot/stage22/cl.elna').each do |line| File.readlines('boot/stage23/cl.elna').each do |line|
if line.start_with? 'proc' if line.start_with?('proc') && !seen_proc
seen_proc = true seen_proc = true
current_stage << line
elsif seen_proc && line.start_with?('begin')
seen_proc = false
current_stage << line
elsif !seen_proc && line.start_with?('begin')
current_stage << <<~CODE current_stage << <<~CODE
proc f() proc sprintf(buffer: Pointer, format: ^Char, number: Word)
begin extern
\tprintf("# %.*s %p %i\\n\\0".ptr, "location".length, "location".ptr, "location".ptr, "location".length)
end
CODE CODE
current_stage << line current_stage << line
current_stage << <<~CODE
\tf();
CODE
else else
current_stage << line current_stage << line
end end
+171 -156
View File
@@ -7,6 +7,8 @@ program;
(* Stage 23 compiler. *) (* Stage 23 compiler. *)
(* - Support extern procedure declarations. *)
type type
ElnaListNode = record ElnaListNode = record
next: Word next: Word
@@ -264,14 +266,21 @@ type
next: Word; next: Word;
name: String name: String
end end
ElnaTreeVariableDeclaration = record
kind: ElnaTreeKind;
next: Word;
name: String;
type_expression: ^ElnaTreeTypeExpression
end
ElnaTreeProcedureDeclaration = record ElnaTreeProcedureDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
next: Word; next: Word;
name: String; name: String;
body: ^ElnaTreeStatement; body: ^ElnaTreeStatement;
temporaries: Word; temporaries: ^ElnaTreeVariableDeclaration;
parameters: Word; parameters: ^ElnaTreeVariableDeclaration;
return_type: ^ElnaTreeTypeExpression return_type: ^ElnaTreeTypeExpression;
is_extern: Bool
end end
ElnaTreeModuleDeclaration = record ElnaTreeModuleDeclaration = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
@@ -286,12 +295,6 @@ type
name: String; name: String;
type_expression: ^ElnaTreeTypeExpression type_expression: ^ElnaTreeTypeExpression
end end
ElnaTreeVariableDeclaration = record
kind: ElnaTreeKind;
next: Word;
name: String;
type_expression: ^ElnaTreeTypeExpression
end
ElnaTreeExpressionList = record ElnaTreeExpressionList = record
expression: ^ElnaTreeBinaryExpression; expression: ^ElnaTreeBinaryExpression;
next: Word next: Word
@@ -674,6 +677,9 @@ var
temporary_variable_counter: Word temporary_variable_counter: Word
pseudo_counter: Word pseudo_counter: Word
stdout: Pointer
stderr: Pointer
proc free_and_nil(pointer: Pointer) -> Pointer proc free_and_nil(pointer: Pointer) -> Pointer
begin begin
free(pointer); free(pointer);
@@ -761,7 +767,7 @@ end
*) *)
proc _write_s(stream: Word, buffer: String) proc _write_s(stream: Word, buffer: String)
begin begin
write(stream, buffer.ptr, buffer.length) fwrite(buffer.ptr, 1, buffer.length, stream)
end end
(** (**
@@ -772,8 +778,7 @@ end
*) *)
proc _write_i(stream: Word, number: Word) proc _write_i(stream: Word, number: Word)
begin begin
dprintf(stream, "%i\0".ptr, number); fprintf(stream, "%i\0".ptr, number)
fflush(nil)
end end
(** (**
@@ -784,7 +789,12 @@ end
*) *)
proc _write_c(stream: Word, character: Word) proc _write_c(stream: Word, character: Word)
begin begin
write(stream, @character, 1) fputc(character, stream)
end
proc _write(stream: Word, buffer: ^Char, size: Word)
begin
fwrite(buffer, 1, size, stream)
end end
proc elna_list_initialize(list: ^ElnaList) proc elna_list_initialize(list: ^ElnaList)
@@ -1578,92 +1588,91 @@ var
begin begin
if instruction_kind = ElnaRtlOperator.li then if instruction_kind = ElnaRtlOperator.li then
argument_count := 2; argument_count := 2;
_write_s(1, "\tli") _write_s(stdout, "\tli")
elsif instruction_kind = ElnaRtlOperator.la then elsif instruction_kind = ElnaRtlOperator.la then
argument_count := 2; argument_count := 2;
_write_s(1, "\tla") _write_s(stdout, "\tla")
elsif instruction_kind = ElnaRtlOperator.add then elsif instruction_kind = ElnaRtlOperator.add then
argument_count := 3; argument_count := 3;
_write_s(1, "\tadd") _write_s(stdout, "\tadd")
elsif instruction_kind = ElnaRtlOperator.addi then elsif instruction_kind = ElnaRtlOperator.addi then
argument_count := 3; argument_count := 3;
_write_s(1, "\taddi") _write_s(stdout, "\taddi")
elsif instruction_kind = ElnaRtlOperator.lw then elsif instruction_kind = ElnaRtlOperator.lw then
argument_count := 2; argument_count := 2;
if source_type^.kind = ElnaRtlTypeKind.byte then if source_type^.kind = ElnaRtlTypeKind.byte then
_write_s(1, "\tlb") _write_s(stdout, "\tlb")
else else
_write_s(1, "\tlw") _write_s(stdout, "\tlw")
end end
elsif instruction_kind = ElnaRtlOperator.sw then elsif instruction_kind = ElnaRtlOperator.sw then
argument_count := 2; argument_count := 2;
if source_type^.kind = ElnaRtlTypeKind.byte then if source_type^.kind = ElnaRtlTypeKind.byte then
_write_s(1, "\tsb") _write_s(stdout, "\tsb")
else else
_write_s(1, "\tsw") _write_s(stdout, "\tsw")
end end
elsif instruction_kind = ElnaRtlOperator.jal then elsif instruction_kind = ElnaRtlOperator.jal then
argument_count := 1; argument_count := 1;
_write_s(1, "\tcall") _write_s(stdout, "\tcall")
elsif instruction_kind = ElnaRtlOperator.mv then elsif instruction_kind = ElnaRtlOperator.mv then
argument_count := 2; argument_count := 2;
_write_s(1, "\tmv") _write_s(stdout, "\tmv")
elsif instruction_kind = ElnaRtlOperator.sub then elsif instruction_kind = ElnaRtlOperator.sub then
argument_count := 3; argument_count := 3;
_write_s(1, "\tsub") _write_s(stdout, "\tsub")
elsif instruction_kind = ElnaRtlOperator.mul then elsif instruction_kind = ElnaRtlOperator.mul then
argument_count := 3; argument_count := 3;
_write_s(1, "\tmul") _write_s(stdout, "\tmul")
elsif instruction_kind = ElnaRtlOperator.div then elsif instruction_kind = ElnaRtlOperator.div then
argument_count := 3; argument_count := 3;
_write_s(1, "\tdiv") _write_s(stdout, "\tdiv")
elsif instruction_kind = ElnaRtlOperator.rem then elsif instruction_kind = ElnaRtlOperator.rem then
argument_count := 3; argument_count := 3;
_write_s(1, "\trem") _write_s(stdout, "\trem")
elsif instruction_kind = ElnaRtlOperator._xor then elsif instruction_kind = ElnaRtlOperator._xor then
argument_count := 3; argument_count := 3;
_write_s(1, "\txor") _write_s(stdout, "\txor")
elsif instruction_kind = ElnaRtlOperator.xori then elsif instruction_kind = ElnaRtlOperator.xori then
argument_count := 3; argument_count := 3;
_write_s(1, "\txori") _write_s(stdout, "\txori")
elsif instruction_kind = ElnaRtlOperator._or then elsif instruction_kind = ElnaRtlOperator._or then
argument_count := 3; argument_count := 3;
_write_s(1, "\tor") _write_s(stdout, "\tor")
elsif instruction_kind = ElnaRtlOperator.and then elsif instruction_kind = ElnaRtlOperator.and then
argument_count := 3; argument_count := 3;
_write_s(1, "\tand") _write_s(stdout, "\tand")
elsif instruction_kind = ElnaRtlOperator.seqz then elsif instruction_kind = ElnaRtlOperator.seqz then
argument_count := 2; argument_count := 2;
_write_s(1, "\tseqz") _write_s(stdout, "\tseqz")
elsif instruction_kind = ElnaRtlOperator.snez then elsif instruction_kind = ElnaRtlOperator.snez then
argument_count := 2; argument_count := 2;
_write_s(1, "\tsnez") _write_s(stdout, "\tsnez")
elsif instruction_kind = ElnaRtlOperator.slt then elsif instruction_kind = ElnaRtlOperator.slt then
argument_count := 3; argument_count := 3;
_write_s(1, "\tslt") _write_s(stdout, "\tslt")
elsif instruction_kind = ElnaRtlOperator.neg then elsif instruction_kind = ElnaRtlOperator.neg then
argument_count := 2; argument_count := 2;
_write_s(1, "\tneg") _write_s(stdout, "\tneg")
elsif instruction_kind = ElnaRtlOperator.not then elsif instruction_kind = ElnaRtlOperator.not then
argument_count := 2; argument_count := 2;
_write_s(1, "\tnot") _write_s(stdout, "\tnot")
elsif instruction_kind = ElnaRtlOperator.j then elsif instruction_kind = ElnaRtlOperator.j then
argument_count := 1; argument_count := 1;
_write_s(1, "\tj") _write_s(stdout, "\tj")
elsif instruction_kind = ElnaRtlOperator.beqz then elsif instruction_kind = ElnaRtlOperator.beqz then
argument_count := 2; argument_count := 2;
_write_s(1, "\tbeqz") _write_s(stdout, "\tbeqz")
elsif instruction_kind = ElnaRtlOperator.bnez then elsif instruction_kind = ElnaRtlOperator.bnez then
argument_count := 2; argument_count := 2;
_write_s(1, "\tbnez") _write_s(stdout, "\tbnez")
end; end;
return argument_count return argument_count
end end
proc elna_riscv_register(register: Word) proc elna_riscv_register(register: Word)
begin begin
printf("x%i\0".ptr, register - 1); fprintf(stdout, "x%i\0".ptr, register - 1);
fflush(nil)
end end
proc elna_riscv_operand(instruction: ^ElnaRtlInstruction, n: Word) proc elna_riscv_operand(instruction: ^ElnaRtlInstruction, n: Word)
@@ -1672,20 +1681,20 @@ var
begin begin
operand_type := instruction^.operands[n].kind; operand_type := instruction^.operands[n].kind;
_write_c(1, ' '); _write_c(stdout, ' ');
if operand_type = ElnaRtlKind.register then if operand_type = ElnaRtlKind.register then
elna_riscv_register(instruction^.operands[n].value) elna_riscv_register(instruction^.operands[n].value)
elsif operand_type = ElnaRtlKind.memory then elsif operand_type = ElnaRtlKind.memory then
_write_i(1, instruction^.operands[n].offset); _write_i(stdout, instruction^.operands[n].offset);
_write_c(1, '('); _write_c(stdout, '(');
elna_riscv_register(instruction^.operands[n].value); elna_riscv_register(instruction^.operands[n].value);
_write_c(1, ')') _write_c(stdout, ')')
elsif operand_type = ElnaRtlKind.data then elsif operand_type = ElnaRtlKind.data then
write(1, instruction^.operands[n].value, instruction^.operands[n].length) _write(stdout, instruction^.operands[n].value, instruction^.operands[n].length)
elsif instruction^.operands[n].length = 0 then (* ElnaRtlKind.immediate *) elsif instruction^.operands[n].length = 0 then (* ElnaRtlKind.immediate *)
_write_i(1, instruction^.operands[n].value) _write_i(stdout, instruction^.operands[n].value)
else else
write(1, instruction^.operands[n].value, instruction^.operands[n].length) _write(stdout, instruction^.operands[n].value, instruction^.operands[n].length)
end end
end end
@@ -2059,34 +2068,32 @@ begin
argument_count := 0; argument_count := 0;
if instruction^.operator = ElnaRtlOperator.label then if instruction^.operator = ElnaRtlOperator.label then
write(1, instruction^.operands[1].value, instruction^.operands[1].length); _write(stdout, instruction^.operands[1].value, instruction^.operands[1].length);
_write_c(1, ':') _write_c(stdout, ':')
elsif instruction^.operator = ElnaRtlOperator.allocate_stack then elsif instruction^.operator = ElnaRtlOperator.allocate_stack then
operand_value := instruction^.operands[1].value; operand_value := instruction^.operands[1].value;
fflush(nil);
(* Write the prologue. *) (* Write the prologue. *)
_write_s(1, "\taddi sp, sp, -"); _write_s(stdout, "\taddi sp, sp, -");
_write_i(1, operand_value); _write_i(stdout, operand_value);
_write_s(1, "\n\tsw ra, "); _write_s(stdout, "\n\tsw ra, ");
_write_i(1, operand_value - 4); _write_i(stdout, operand_value - 4);
_write_s(1, "(sp)\n\tsw s0, "); _write_s(stdout, "(sp)\n\tsw s0, ");
_write_i(1, operand_value - 8); _write_i(stdout, operand_value - 8);
_write_s(1, "(sp)\n\taddi s0, sp, "); _write_s(stdout, "(sp)\n\taddi s0, sp, ");
_write_i(1, operand_value); _write_i(stdout, operand_value);
_write_c(1, '\n') _write_c(stdout, '\n')
elsif instruction^.operator = ElnaRtlOperator.ret then elsif instruction^.operator = ElnaRtlOperator.ret then
operand_value := instruction^.operands[1].value; operand_value := instruction^.operands[1].value;
fflush(nil);
(* Write the epilogue. *) (* Write the epilogue. *)
_write_s(1, "\tlw ra, "); _write_s(stdout, "\tlw ra, ");
_write_i(1, operand_value - 4); _write_i(stdout, operand_value - 4);
_write_s(1, "(sp)\n\tlw s0, "); _write_s(stdout, "(sp)\n\tlw s0, ");
_write_i(1, operand_value - 8); _write_i(stdout, operand_value - 8);
_write_s(1, "(sp)\n\taddi sp, sp, "); _write_s(stdout, "(sp)\n\taddi sp, sp, ");
_write_i(1, operand_value); _write_i(stdout, operand_value);
_write_c(1, '\n') _write_c(stdout, '\n')
elsif instruction^.operator = ElnaRtlOperator.nop then elsif instruction^.operator = ElnaRtlOperator.nop then
else else
argument_count := elna_riscv_instruction_name(instruction^.operator, argument_count := elna_riscv_instruction_name(instruction^.operator,
@@ -2100,10 +2107,10 @@ begin
current_argument := current_argument + 1 current_argument := current_argument + 1
end; end;
if current_argument <= argument_count then if current_argument <= argument_count then
_write_c(1, ','); _write_c(stdout, ',');
goto elna_riscv_instruction_loop goto elna_riscv_instruction_loop
end; end;
_write_c(1, '\n') _write_c(stdout, '\n')
end end
proc elna_rtl_instructions(instructions: ^ElnaList, instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable) proc elna_rtl_instructions(instructions: ^ElnaList, instruction: ^ElnaTacInstruction, variable_map: ^ElnaSymbolTable)
@@ -2171,17 +2178,16 @@ begin
.elna_riscv_procedure_loop; .elna_riscv_procedure_loop;
(* Write .type _procedure_name, @function. *) (* Write .type _procedure_name, @function. *)
_write_s(1, ".type "); _write_s(stdout, ".type ");
_write_s(1, procedure^.name); _write_s(stdout, procedure^.name);
_write_s(1, ", @function\n"); _write_s(stdout, ", @function\n");
(* Write procedure label, _procedure_name: *) (* Write procedure label, _procedure_name: *)
_write_s(1, procedure^.name); _write_s(stdout, procedure^.name);
_write_s(1, ":\n"); _write_s(stdout, ":\n");
elna_riscv_instructions(procedure^.body.first); elna_riscv_instructions(procedure^.body.first);
fflush(nil); _write_s(stdout, "\tret\n");
_write_s(1, "\tret\n");
procedure := procedure^.next; procedure := procedure^.next;
if procedure <> nil then if procedure <> nil then
@@ -2193,14 +2199,14 @@ proc elna_riscv_variable(variable: ^ElnaRtlStaticVariable)
begin begin
.elna_riscv_variable_loop; .elna_riscv_variable_loop;
if variable <> nil then if variable <> nil then
_write_s(1, ".type "); _write_s(stdout, ".type ");
_write_s(1, variable^.name); _write_s(stdout, variable^.name);
_write_s(1, ", @object"); _write_s(stdout, ", @object");
_write_c(1, '\n'); _write_c(stdout, '\n');
_write_s(1, variable^.name); _write_s(stdout, variable^.name);
_write_s(1, ": .zero "); _write_s(stdout, ": .zero ");
_write_i(1, variable^.body); _write_i(stdout, variable^.body);
_write_c(1, '\n'); _write_c(stdout, '\n');
variable := variable^.next; variable := variable^.next;
@@ -2304,15 +2310,13 @@ var
compiler_strings_end: ^Char compiler_strings_end: ^Char
current_byte: Char current_byte: Char
begin begin
_write_s(1, ".globl main\n\n.section .data\n"); _write_s(stdout, ".globl main\n\n.section .data\n");
elna_riscv_variable(pair^.data); elna_riscv_variable(pair^.data);
fflush(nil);
_write_s(1, ".section .text\n\n"); _write_s(stdout, ".section .text\n\n");
elna_riscv_procedure(pair^.code); elna_riscv_procedure(pair^.code);
fflush(nil);
_write_s(1, ".section .rodata\n.type strings, @object\nstrings: .ascii \""); _write_s(stdout, ".section .rodata\n.type strings, @object\nstrings: .ascii \"");
compiler_strings_copy := @compiler_strings; compiler_strings_copy := @compiler_strings;
compiler_strings_end := compiler_strings_position; compiler_strings_end := compiler_strings_position;
@@ -2321,11 +2325,11 @@ begin
if compiler_strings_copy < compiler_strings_end then if compiler_strings_copy < compiler_strings_end then
current_byte := compiler_strings_copy^; current_byte := compiler_strings_copy^;
compiler_strings_copy := compiler_strings_copy + 1; compiler_strings_copy := compiler_strings_copy + 1;
_write_c(1, current_byte); _write_c(stdout, current_byte);
goto elna_riscv_module_loop goto elna_riscv_module_loop
end; end;
_write_s(1, "\"\n") _write_s(stdout, "\"\n")
end end
proc elna_parser_integer_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeIntegerLiteral proc elna_parser_integer_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeIntegerLiteral
@@ -3758,8 +3762,8 @@ end
*) *)
proc _write_register(register_character: Word, register_number: Word) proc _write_register(register_character: Word, register_number: Word)
begin begin
_write_c(1, register_character); _write_c(stdout, register_character);
_write_c(1, register_number + '0') _write_c(stdout, register_number + '0')
end end
proc elna_parser_record_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeRecordTypeExpression proc elna_parser_record_type_expression(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeRecordTypeExpression
@@ -4272,6 +4276,13 @@ begin
result^.return_type := nil result^.return_type := nil
end; end;
token := elna_lexer_peek(cursor);
result^.is_extern := token^.kind = ElnaLexerKind._extern;
if result^.is_extern then
elna_lexer_read(cursor);
result^.temporaries := nil;
result^.body := nil
else
result^.temporaries := elna_parser_var_part(cursor, error_list); result^.temporaries := elna_parser_var_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);
@@ -4297,6 +4308,7 @@ begin
if elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = false then if elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = false then
result := free_and_nil(result) result := free_and_nil(result)
end
end; end;
.elna_parser_procedure_declaration_end; .elna_parser_procedure_declaration_end;
@@ -4644,7 +4656,7 @@ begin
return first_copy return first_copy
end end
proc elna_tac_procedures(parser_node: ^ElnaTreeDeclaration) -> ^ElnaTacProcedure proc elna_tac_procedures(parser_node: ^ElnaTreeProcedureDeclaration) -> ^ElnaTacProcedure
var var
result: ^ElnaTacProcedure result: ^ElnaTacProcedure
current_procedure: ^ElnaTacProcedure current_procedure: ^ElnaTacProcedure
@@ -4656,14 +4668,15 @@ begin
if parser_node = nil then if parser_node = nil then
goto elna_tac_procedures_end goto elna_tac_procedures_end
end; end;
if parser_node^.is_extern = false then
result := elna_tac_procedure_declaration(parser_node); result := elna_tac_procedure_declaration(parser_node);
if first_procedure = nil then if first_procedure = nil then
first_procedure := result first_procedure := result
else else
current_procedure^.next := result current_procedure^.next := result
end; end;
current_procedure := result; current_procedure := result
end;
parser_node := parser_node^.next; parser_node := parser_node^.next;
goto elna_tac_procedures_loop; goto elna_tac_procedures_loop;
@@ -4801,7 +4814,7 @@ begin
return result return result
end end
proc elna_parser_var_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeDeclaration proc elna_parser_var_part(cursor: ^ElnaLexerCursor, error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration
var var
result: ^ElnaTreeDeclaration result: ^ElnaTreeDeclaration
variable_node: ^ElnaTreeDeclaration variable_node: ^ElnaTreeDeclaration
@@ -5522,105 +5535,105 @@ 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
_write_s(2, "IDENTIFIER") _write_s(stderr, "IDENTIFIER")
elsif kind = ElnaLexerKind._const then elsif kind = ElnaLexerKind._const then
_write_s(2, "\"const\"") _write_s(stderr, "\"const\"")
elsif kind = ElnaLexerKind._var then elsif kind = ElnaLexerKind._var then
_write_s(2, "\"var\"") _write_s(stderr, "\"var\"")
elsif kind = ElnaLexerKind._proc then elsif kind = ElnaLexerKind._proc then
_write_s(2, "\"proc\"") _write_s(stderr, "\"proc\"")
elsif kind = ElnaLexerKind._type then elsif kind = ElnaLexerKind._type then
_write_s(2, "\"type\"") _write_s(stderr, "\"type\"")
elsif kind = ElnaLexerKind._begin then elsif kind = ElnaLexerKind._begin then
_write_s(2, "\"begin\"") _write_s(stderr, "\"begin\"")
elsif kind = ElnaLexerKind._end then elsif kind = ElnaLexerKind._end then
_write_s(2, "\"end\"") _write_s(stderr, "\"end\"")
elsif kind = ElnaLexerKind._if then elsif kind = ElnaLexerKind._if then
_write_s(2, "\"if\"") _write_s(stderr, "\"if\"")
elsif kind = ElnaLexerKind._then then elsif kind = ElnaLexerKind._then then
_write_s(2, "\"then\"") _write_s(stderr, "\"then\"")
elsif kind = ElnaLexerKind._else then elsif kind = ElnaLexerKind._else then
_write_s(2, "\"else\"") _write_s(stderr, "\"else\"")
elsif kind = ElnaLexerKind._elsif then elsif kind = ElnaLexerKind._elsif then
_write_s(2, "\"elsif\"") _write_s(stderr, "\"elsif\"")
elsif kind = ElnaLexerKind._extern then elsif kind = ElnaLexerKind._extern then
_write_s(2, "\"extern\"") _write_s(stderr, "\"extern\"")
elsif kind = ElnaLexerKind._record then elsif kind = ElnaLexerKind._record then
_write_s(2, "\"record\"") _write_s(stderr, "\"record\"")
elsif kind = ElnaLexerKind.boolean then elsif kind = ElnaLexerKind.boolean then
_write_s(2, "BOOLEAN") _write_s(stderr, "BOOLEAN")
elsif kind = ElnaLexerKind.null then elsif kind = ElnaLexerKind.null then
_write_s(2, "NIL") _write_s(stderr, "NIL")
elsif kind = ElnaLexerKind.and then elsif kind = ElnaLexerKind.and then
_write_s(2, "\"&\"") _write_s(stderr, "\"&\"")
elsif kind = ElnaLexerKind._or then elsif kind = ElnaLexerKind._or then
_write_s(2, "\"or\"") _write_s(stderr, "\"or\"")
elsif kind = ElnaLexerKind._xor then elsif kind = ElnaLexerKind._xor then
_write_s(2, "\"xor\"") _write_s(stderr, "\"xor\"")
elsif kind = ElnaLexerKind.not then elsif kind = ElnaLexerKind.not then
_write_s(2, "\"~\"") _write_s(stderr, "\"~\"")
elsif kind = ElnaLexerKind._return then elsif kind = ElnaLexerKind._return then
_write_s(2, "\"return\"") _write_s(stderr, "\"return\"")
elsif kind = ElnaLexerKind._program then elsif kind = ElnaLexerKind._program then
_write_s(2, "\"program\"") _write_s(stderr, "\"program\"")
elsif kind = ElnaLexerKind._cast then elsif kind = ElnaLexerKind._cast then
_write_s(2, "\"cast\"") _write_s(stderr, "\"cast\"")
elsif kind = ElnaLexerKind.trait then elsif kind = ElnaLexerKind.trait then
_write_s(2, "TRAIT") _write_s(stderr, "TRAIT")
elsif kind = ElnaLexerKind.left_paren then elsif kind = ElnaLexerKind.left_paren then
_write_s(2, "\"(\"") _write_s(stderr, "\"(\"")
elsif kind = ElnaLexerKind.right_paren then elsif kind = ElnaLexerKind.right_paren then
_write_s(2, "\")\"") _write_s(stderr, "\")\"")
elsif kind = ElnaLexerKind.left_square then elsif kind = ElnaLexerKind.left_square then
_write_s(2, "\"[\"") _write_s(stderr, "\"[\"")
elsif kind = ElnaLexerKind.right_square then elsif kind = ElnaLexerKind.right_square then
_write_s(2, "\"]\"") _write_s(stderr, "\"]\"")
elsif kind = ElnaLexerKind.greater_equal then elsif kind = ElnaLexerKind.greater_equal then
_write_s(2, "\">=\"") _write_s(stderr, "\">=\"")
elsif kind = ElnaLexerKind.less_equal then elsif kind = ElnaLexerKind.less_equal then
_write_s(2, "\"<=\"") _write_s(stderr, "\"<=\"")
elsif kind = ElnaLexerKind.greater_than then elsif kind = ElnaLexerKind.greater_than then
_write_s(2, "\">\"") _write_s(stderr, "\">\"")
elsif kind = ElnaLexerKind.less_than then elsif kind = ElnaLexerKind.less_than then
_write_s(2, "\"<\"") _write_s(stderr, "\"<\"")
elsif kind = ElnaLexerKind.not_equal then elsif kind = ElnaLexerKind.not_equal then
_write_s(2, "\"<>\"") _write_s(stderr, "\"<>\"")
elsif kind = ElnaLexerKind.equals then elsif kind = ElnaLexerKind.equals then
_write_s(2, "\"=\"") _write_s(stderr, "\"=\"")
elsif kind = ElnaLexerKind.semicolon then elsif kind = ElnaLexerKind.semicolon then
_write_s(2, "\";\"") _write_s(stderr, "\";\"")
elsif kind = ElnaLexerKind.dot then elsif kind = ElnaLexerKind.dot then
_write_s(2, "\".\"") _write_s(stderr, "\".\"")
elsif kind = ElnaLexerKind.comma then elsif kind = ElnaLexerKind.comma then
_write_s(2, "\",\"") _write_s(stderr, "\",\"")
elsif kind = ElnaLexerKind.plus then elsif kind = ElnaLexerKind.plus then
_write_s(2, "\"+\"") _write_s(stderr, "\"+\"")
elsif kind = ElnaLexerKind.arrow then elsif kind = ElnaLexerKind.arrow then
_write_s(2, "\"->\"") _write_s(stderr, "\"->\"")
elsif kind = ElnaLexerKind.minus then elsif kind = ElnaLexerKind.minus then
_write_s(2, "\"-\"") _write_s(stderr, "\"-\"")
elsif kind = ElnaLexerKind.multiplication then elsif kind = ElnaLexerKind.multiplication then
_write_s(2, "\"*\"") _write_s(stderr, "\"*\"")
elsif kind = ElnaLexerKind.division then elsif kind = ElnaLexerKind.division then
_write_s(2, "\"/\"") _write_s(stderr, "\"/\"")
elsif kind = ElnaLexerKind.remainder then elsif kind = ElnaLexerKind.remainder then
_write_s(2, "\"%\"") _write_s(stderr, "\"%\"")
elsif kind = ElnaLexerKind.assignment then elsif kind = ElnaLexerKind.assignment then
_write_s(2, "\":=\"") _write_s(stderr, "\":=\"")
elsif kind = ElnaLexerKind.colon then elsif kind = ElnaLexerKind.colon then
_write_s(2, "\":\"") _write_s(stderr, "\":\"")
elsif kind = ElnaLexerKind.hat then elsif kind = ElnaLexerKind.hat then
_write_s(2, "\"^\"") _write_s(stderr, "\"^\"")
elsif kind = ElnaLexerKind.at then elsif kind = ElnaLexerKind.at then
_write_s(2, "\"@\"") _write_s(stderr, "\"@\"")
elsif kind = ElnaLexerKind.comment then elsif kind = ElnaLexerKind.comment then
_write_s(2, "COMMENT") _write_s(stderr, "COMMENT")
elsif kind = ElnaLexerKind.string then elsif kind = ElnaLexerKind.string then
_write_s(2, "STRING") _write_s(stderr, "STRING")
elsif kind = ElnaLexerKind.character then elsif kind = ElnaLexerKind.character then
_write_s(2, "CHARACTER") _write_s(stderr, "CHARACTER")
elsif kind = ElnaLexerKind.integer then elsif kind = ElnaLexerKind.integer then
_write_s(2, "INTEGER") _write_s(stderr, "INTEGER")
else else
elna_error_print_token2(kind) elna_error_print_token2(kind)
end end
@@ -5629,23 +5642,23 @@ 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.word then
_write_s(2, "WORD") _write_s(stderr, "WORD")
elsif kind = ElnaLexerKind._goto then elsif kind = ElnaLexerKind._goto then
_write_s(2, "\"goto\"") _write_s(stderr, "\"goto\"")
elsif kind = ElnaLexerKind.eof then elsif kind = ElnaLexerKind.eof then
_write_s(2, "EOF") _write_s(stderr, "EOF")
else else
_write_s(2, "UNKNOWN") _write_s(stderr, "UNKNOWN")
end end
end end
proc elna_error_print_unexpected_token(current_error: ^ElnaErrorUnexpectedToken) proc elna_error_print_unexpected_token(current_error: ^ElnaErrorUnexpectedToken)
begin begin
_write_s(2, "Parse error: Expecting token "); _write_s(stderr, "Parse error: Expecting token ");
elna_error_print_token1(current_error^.expected[1]); elna_error_print_token1(current_error^.expected[1]);
_write_s(2, "; got "); _write_s(stderr, "; got ");
elna_error_print_token1(current_error^.got); elna_error_print_token1(current_error^.got);
_write_s(2, ".\n") _write_s(stderr, ".\n")
end end
proc elna_error_print(current_error: ^ElnaError) proc elna_error_print(current_error: ^ElnaError)
@@ -5653,7 +5666,7 @@ begin
if current_error^.kind = ElnaErrorKind.unexpected_token then if current_error^.kind = ElnaErrorKind.unexpected_token then
elna_error_print_unexpected_token(current_error) elna_error_print_unexpected_token(current_error)
else else
_write_s(2, "Unknown error.\n") _write_s(stderr, "Unknown error.\n")
end end
end end
@@ -6525,6 +6538,8 @@ end
proc initialize_global_state() proc initialize_global_state()
begin begin
stdout := fdopen(1, "w\0");
stderr := fdopen(2, "w\0");
compiler_strings_position := @compiler_strings; compiler_strings_position := @compiler_strings;
source_code := malloc(495616) source_code := malloc(495616)
end end