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