Add an empty cstdlib.elna source file
This commit is contained in:
		| @@ -6,9 +6,7 @@ module; | ||||
| from Args import GetArg, Narg; | ||||
| from FIO import WriteString, WriteChar, WriteLine, StdErr; | ||||
| from Strings import CompareStr, Length; | ||||
| from MemUtils import MemZero; | ||||
|  | ||||
| from Common import ShortString; | ||||
| import cstdlib, common; | ||||
|  | ||||
| type | ||||
|   CommandLine = record | ||||
| @@ -29,26 +27,26 @@ begin | ||||
|   NEW(result); | ||||
|   result^.lex := false; | ||||
|   result^.parse := false; | ||||
|   MemZero(@result^.input, 256); | ||||
|   memset(@result^.input, 0, 256); | ||||
|   result^.output[1] := CHAR(0); | ||||
|  | ||||
|   while (i < Narg()) & (result <> nil) do | ||||
|     parsed := GetArg(parameter, i); | ||||
|     parsed := false; | ||||
|  | ||||
|     if CompareStr(parameter, '--lex') = 0 then | ||||
|     if CompareStr(parameter, "--lex") = 0 then | ||||
|       parsed := true; | ||||
|       result^.lex := true | ||||
|     end; | ||||
|     if CompareStr(parameter, '--parse') = 0 then | ||||
|     if CompareStr(parameter, "--parse") = 0 then | ||||
|       parsed := true; | ||||
|       result^.parse := true | ||||
|     end; | ||||
|     if CompareStr(parameter, '-o') = 0 then | ||||
|     if CompareStr(parameter, "-o") = 0 then | ||||
|       i := i + 1u; | ||||
|  | ||||
|       if i = Narg() then | ||||
|         WriteString(StdErr, 'Fatal error: expecting a file name following -o.'); | ||||
|         WriteString(StdErr, "Fatal error: expecting a file name following -o."); | ||||
|         result := nil | ||||
|       end; | ||||
|       if i < Narg() then | ||||
| @@ -57,15 +55,15 @@ begin | ||||
|       end; | ||||
|       parsed := true | ||||
|     end; | ||||
|     if (parameter[1] <> '-') & (parsed = false) then | ||||
|     if (parameter[1] <> "-") & (parsed = false) then | ||||
|       parsed := true; | ||||
|  | ||||
|       if Length(result^.input) > 0 then | ||||
|         WriteString(StdErr, 'Fatal error: only one source file can be compiled at once. First given "'); | ||||
|         WriteString(StdErr, "Fatal error: only one source file can be compiled at once. First given \""); | ||||
|         WriteString(StdErr, result^.input); | ||||
|         WriteString(StdErr, '", then "'); | ||||
|         WriteString(StdErr, "\", then \""); | ||||
|         WriteString(StdErr, parameter); | ||||
|         WriteString(StdErr, '".'); | ||||
|         WriteString(StdErr, "\"."); | ||||
|         WriteLine(StdErr); | ||||
|         result := nil | ||||
|       end; | ||||
| @@ -74,7 +72,7 @@ begin | ||||
|       end | ||||
|     end; | ||||
|     if parsed = false then | ||||
|       WriteString(StdErr, 'Fatal error: unknown command line options: '); | ||||
|       WriteString(StdErr, "Fatal error: unknown command line options: "); | ||||
|  | ||||
|       WriteString(StdErr, parameter); | ||||
|       WriteChar(StdErr, '.'); | ||||
| @@ -86,7 +84,7 @@ begin | ||||
|     i := i + 1 | ||||
|   end; | ||||
|   if (result <> nil) & (Length(result^.input) = 0) then | ||||
|     WriteString(StdErr, 'Fatal error: no input files.'); | ||||
|     WriteString(StdErr, "Fatal error: no input files."); | ||||
|     WriteLine(StdErr); | ||||
|     result := nil | ||||
|   end; | ||||
|   | ||||
| @@ -1,74 +0,0 @@ | ||||
| (* This Source Code Form is subject to the terms of the Mozilla Public License, | ||||
|   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/. *) | ||||
| program; | ||||
|  | ||||
| from FIO import Close, IsNoError, File, OpenToRead, OpenToWrite, StdErr, StdOut, WriteLine, WriteString; | ||||
| from M2RTS import HALT, ExitOnHalt; | ||||
|  | ||||
| from Lexer import Lexer, lexer_destroy, lexer_initialize; | ||||
| from Transpiler import transpile; | ||||
| from CommandLineInterface import CommandLine, parse_command_line; | ||||
| from Parser import AstModule, parse; | ||||
| from Strings import Length; | ||||
|  | ||||
| var | ||||
|   command_line: ^CommandLine; | ||||
|  | ||||
| proc compile_from_stream(); | ||||
| var | ||||
|   lexer: Lexer; | ||||
|   source_input: File; | ||||
|   source_output: File; | ||||
|   ast_module: ^AstModule; | ||||
| begin | ||||
|   source_input := OpenToRead(command_line^.input); | ||||
|  | ||||
|   if IsNoError(source_input) = false then | ||||
|     WriteString(StdErr, 'Fatal error: failed to read the input file "'); | ||||
|     WriteString(StdErr, command_line^.input); | ||||
|     WriteString(StdErr, '".'); | ||||
|     WriteLine(StdErr); | ||||
|  | ||||
|     ExitOnHalt(2) | ||||
|   end; | ||||
|   source_output := nil; | ||||
|  | ||||
|   if Length(command_line^.output) > 0 then | ||||
|     source_output := OpenToWrite(command_line^.output); | ||||
|  | ||||
|     if IsNoError(source_output) = false then | ||||
|       WriteString(StdErr, 'Fatal error: failed to create the output file "'); | ||||
|       WriteString(StdErr, command_line^.output); | ||||
|       WriteString(StdErr, '".'); | ||||
|       WriteLine(StdErr); | ||||
|       | ||||
|       ExitOnHalt(2) | ||||
|     end | ||||
|   end; | ||||
|  | ||||
|   if IsNoError(source_input) then | ||||
|     lexer_initialize(@lexer, source_input); | ||||
|  | ||||
|     ast_module := parse(@lexer); | ||||
|     transpile(ast_module, StdOut, source_output, command_line^.input); | ||||
|  | ||||
|     lexer_destroy(@lexer); | ||||
|  | ||||
|     Close(source_output); | ||||
|     Close(source_input) | ||||
|   end | ||||
| end; | ||||
|  | ||||
| begin | ||||
|   ExitOnHalt(0); | ||||
|   command_line := parse_command_line(); | ||||
|  | ||||
|   if command_line <> nil then | ||||
|     compile_from_stream() | ||||
|   end; | ||||
|   if command_line = nil then | ||||
|     ExitOnHalt(1) | ||||
|   end; | ||||
|   HALT() | ||||
| end. | ||||
| @@ -3,7 +3,7 @@ | ||||
|   obtain one at https://mozilla.org/MPL/2.0/. *) | ||||
| module; | ||||
|  | ||||
| import Common, cstdlib; | ||||
| import cstdio, cstring, common; | ||||
|  | ||||
| const | ||||
|   CHUNK_SIZE := 85536; | ||||
| @@ -293,7 +293,7 @@ begin | ||||
|   i := 129u; | ||||
|   while i <= 256u do | ||||
|     classification[i] := TransitionClass.other; | ||||
|     i := i + 1 | ||||
|     i := i + 1u | ||||
|   end | ||||
| end; | ||||
|  | ||||
| @@ -410,16 +410,16 @@ begin | ||||
|   if lexer^.start.iterator^ = '"' then | ||||
|     text_length := lexer^.current.iterator - lexer^.start.iterator + 1; | ||||
|  | ||||
|     MemZero(@token^.stringKind, #size(ShortString)); | ||||
|     MemCopy(lexer^.start.iterator, text_length, @token^.stringKind); | ||||
|     memset(@token^.stringKind, 0, #size(ShortString)); | ||||
|     memcpy(@token^.stringKind, lexer^.start.iterator, text_length); | ||||
|  | ||||
|     token^.kind := LexerKind.character | ||||
|   end; | ||||
|   if lexer^.start.iterator^ = "'" then | ||||
|     text_length := lexer^.current.iterator - lexer^.start.iterator + 1; | ||||
|  | ||||
|     MemZero(@token^.stringKind, #size(ShortString)); | ||||
|     MemCopy(lexer^.start.iterator, text_length, @token^.stringKind); | ||||
|     memset(@token^.stringKind, 0, #size(ShortString)); | ||||
|     memcpy(@token^.stringKind, lexer^.start.iterator, text_length); | ||||
|  | ||||
|     token^.kind := LexerKind.string | ||||
|   end; | ||||
| @@ -432,7 +432,7 @@ begin | ||||
|   token^.kind := LexerKind.identifier; | ||||
|  | ||||
|   token^.identifierKind[1] := cast(lexer^.current.iterator - lexer^.start.iterator: Char); | ||||
|   MemCopy(lexer^.start.iterator, ORD(token^.identifierKind[1]), @token^.identifierKind[2]); | ||||
|   memcpy(@token^.identifierKind[2], lexer^.start.iterator, ORD(token^.identifierKind[1])); | ||||
|  | ||||
|   if compare_keyword("program", lexer^.start, lexer^.current.iterator) then | ||||
|     token^.kind := LexerKind._program | ||||
| @@ -590,8 +590,8 @@ begin | ||||
|   token^.kind := LexerKind.integer; | ||||
|  | ||||
|   integer_length := lexer^.current.iterator - lexer^.start.iterator; | ||||
|   MemZero(@token^.identifierKind, #size(Identifier)); | ||||
|   MemCopy(lexer^.start.iterator, integer_length, @token^.identifierKind[1]); | ||||
|   memset(@token^.identifierKind, 0, #size(Identifier)); | ||||
|   memcpy(@token^.identifierKind[1], lexer^.start.iterator, integer_length); | ||||
|  | ||||
|   buffer := InitStringCharStar(@token^.identifierKind[1]); | ||||
|   token^.integerKind := StringToInteger(buffer, 10, found); | ||||
| @@ -889,7 +889,7 @@ begin | ||||
|   lexer^.length := 0; | ||||
|  | ||||
|   lexer^.buffer := malloc(CHUNK_SIZE); | ||||
|   MemZero(lexer^.buffer, CHUNK_SIZE); | ||||
|   memset(lexer^.buffer, 0, CHUNK_SIZE); | ||||
|   lexer^.size := CHUNK_SIZE | ||||
| end; | ||||
|  | ||||
|   | ||||
| @@ -3,11 +3,7 @@ | ||||
|   obtain one at https://mozilla.org/MPL/2.0/. *) | ||||
| module; | ||||
|  | ||||
| import cstdlib; | ||||
| from MemUtils import MemZero; | ||||
|  | ||||
| from Common import Identifier, ShortString; | ||||
| from Lexer import Lexer, LexerToken, lexer_current, lexer_lex; | ||||
| import cstdlib, common, Lexer; | ||||
|  | ||||
| type | ||||
|   Parser = record | ||||
| @@ -237,7 +233,7 @@ begin | ||||
|     end | ||||
|   end; | ||||
|   current_field := current_field + 1; | ||||
|   MemZero(current_field, #size(AstFieldDeclaration)); | ||||
|   memset(current_field, 0, #size(AstFieldDeclaration)); | ||||
|  | ||||
|   return field_declarations | ||||
| end; | ||||
| @@ -331,7 +327,7 @@ begin | ||||
|     token := parser_lex(parser^.lexer) | ||||
|   end; | ||||
|   current_case := current_case + 1; | ||||
|   MemZero(current_case, #size(Identifier)); | ||||
|   memset(current_case, 0, #size(Identifier)); | ||||
|  | ||||
|   return result | ||||
| end; | ||||
| @@ -608,7 +604,7 @@ begin | ||||
|     token := parser_lex(parser^.lexer) | ||||
|   end; | ||||
|   current_symbol := current_symbol + 1; | ||||
|   MemZero(current_symbol, #size(Identifier)); | ||||
|   memset(current_symbol, 0, #size(Identifier)); | ||||
|  | ||||
|   token := parser_lex(parser^.lexer); | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ module; | ||||
| from FIO import File, WriteNBytes, WriteLine, WriteChar, WriteString; | ||||
| from NumberIO import IntToStr; | ||||
|  | ||||
| from Common import Identifier, ShortString; | ||||
| import common; | ||||
| from Parser import AstLiteralKind, AstUnaryOperator, AstBinaryOperator, AstModule, AstExpression, AstLiteral, | ||||
|   AstConstantDeclaration, AstStatement, AstTypedDeclaration, AstCompoundStatement, AstProcedureDeclaration, | ||||
|   AstVariableDeclaration, AstImportStatement, AstTypeExpression, AstFieldDeclaration; | ||||
| @@ -26,7 +26,7 @@ begin | ||||
|   count := 0; | ||||
|  | ||||
|   while count < context^.indentation do | ||||
|     WriteString(context^.output, '  '); | ||||
|     WriteString(context^.output, "  "); | ||||
|     count := count + 1u | ||||
|   end | ||||
| end; | ||||
| @@ -43,17 +43,17 @@ var | ||||
|   written_bytes: Word; | ||||
|   current_symbol: ^Identifier; | ||||
| begin | ||||
|   WriteString(context^.output, 'FROM '); | ||||
|   WriteString(context^.output, "FROM "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(import_statement^.package[1]), @import_statement^.package[2]); | ||||
|  | ||||
|   WriteString(context^.output, ' IMPORT '); | ||||
|   WriteString(context^.output, " IMPORT "); | ||||
|  | ||||
|   current_symbol := import_statement^.symbols; | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(current_symbol^[1]), @current_symbol^[2]); | ||||
|   current_symbol := current_symbol + 1; | ||||
|  | ||||
|   while ORD(current_symbol^[1]) <> 0 do | ||||
|     WriteString(context^.output, ', '); | ||||
|     WriteString(context^.output, ", "); | ||||
|     written_bytes := WriteNBytes(context^.output, ORD(current_symbol^[1]), @current_symbol^[2]); | ||||
|     current_symbol := current_symbol + 1; | ||||
|   end; | ||||
| @@ -76,10 +76,10 @@ var | ||||
|   buffer: [20]CHAR; | ||||
|   written_bytes: Word; | ||||
| begin | ||||
|   WriteString(context^.output, '  '); | ||||
|   WriteString(context^.output, "  "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(declaration^.constant_name[1]), @declaration^.constant_name[2]); | ||||
|  | ||||
|   WriteString(context^.output, ' = '); | ||||
|   WriteString(context^.output, " = "); | ||||
|  | ||||
|   IntToStr(declaration^.constant_value, 0, buffer); | ||||
|   WriteString(context^.output, buffer); | ||||
| @@ -92,7 +92,7 @@ var | ||||
|   current_declaration: ^^AstConstantDeclaration; | ||||
| begin | ||||
|   if declarations^ <> nil then | ||||
|     WriteString(context^.output, 'CONST'); | ||||
|     WriteString(context^.output, "CONST"); | ||||
|     WriteLine(context^.output); | ||||
|  | ||||
|     current_declaration := declarations; | ||||
| @@ -110,9 +110,9 @@ end; | ||||
| proc transpile_module(context: ^TranspilerContext, result: ^AstModule); | ||||
| begin | ||||
|   if result^.main = false then | ||||
|     WriteString(context^.output, 'IMPLEMENTATION ') | ||||
|     WriteString(context^.output, "IMPLEMENTATION ") | ||||
|   end; | ||||
|   WriteString(context^.output, 'MODULE '); | ||||
|   WriteString(context^.output, "MODULE "); | ||||
|  | ||||
|   (* Write the module name and end the line with a semicolon and newline. *) | ||||
|   transpile_module_name(context); | ||||
| @@ -129,10 +129,10 @@ begin | ||||
|   transpile_procedure_part(context, result^.procedures); | ||||
|   transpile_statement_part(context, result^.statements); | ||||
|  | ||||
|   WriteString(context^.output, 'END '); | ||||
|   WriteString(context^.output, "END "); | ||||
|   transpile_module_name(context); | ||||
|  | ||||
|   WriteChar(context^.output, '.'); | ||||
|   WriteChar(context^.output, "."); | ||||
|   WriteLine(context^.output) | ||||
| end; | ||||
|  | ||||
| @@ -144,10 +144,10 @@ begin | ||||
|   current_field := fields; | ||||
|  | ||||
|   while ORD(current_field^.field_name[1]) <> 0 do | ||||
|     WriteString(context^.output, '    '); | ||||
|     WriteString(context^.output, "    "); | ||||
|     written_bytes := WriteNBytes(context^.output, ORD(current_field^.field_name[1]), @current_field^.field_name[2]); | ||||
|  | ||||
|     WriteString(context^.output, ': '); | ||||
|     WriteString(context^.output, ": "); | ||||
|     transpile_type_expression(context, current_field^.field_type); | ||||
|  | ||||
|     current_field := current_field + 1; | ||||
| @@ -161,15 +161,15 @@ end; | ||||
|  | ||||
| proc transpile_record_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); | ||||
| begin | ||||
|   WriteString(context^.output, 'RECORD'); | ||||
|   WriteString(context^.output, "RECORD"); | ||||
|   WriteLine(context^.output); | ||||
|   transpile_type_fields(context, type_expression^.fields); | ||||
|   WriteString(context^.output, '  END') | ||||
|   WriteString(context^.output, "  END") | ||||
| end; | ||||
|  | ||||
| proc transpile_pointer_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); | ||||
| begin | ||||
|   WriteString(context^.output, 'POINTER TO '); | ||||
|   WriteString(context^.output, "POINTER TO "); | ||||
|  | ||||
|   transpile_type_expression(context, type_expression^.target) | ||||
| end; | ||||
| @@ -178,17 +178,17 @@ proc transpile_array_type(context: ^TranspilerContext, type_expression: ^AstType | ||||
| var | ||||
|   buffer: [20]CHAR; | ||||
| begin | ||||
|   WriteString(context^.output, 'ARRAY'); | ||||
|   WriteString(context^.output, "ARRAY"); | ||||
|  | ||||
|   if type_expression^.length <> 0 then | ||||
|     WriteString(context^.output, '[1..'); | ||||
|     WriteString(context^.output, "[1.."); | ||||
|  | ||||
|     IntToStr(type_expression^.length, 0, buffer); | ||||
|     WriteString(context^.output, buffer); | ||||
|  | ||||
|     WriteChar(context^.output, ']') | ||||
|   end; | ||||
|   WriteString(context^.output, ' OF '); | ||||
|   WriteString(context^.output, " OF "); | ||||
|  | ||||
|   transpile_type_expression(context, type_expression^.base) | ||||
| end; | ||||
| @@ -200,22 +200,22 @@ var | ||||
| begin | ||||
|   current_case := type_expression^.cases; | ||||
|  | ||||
|   WriteString(context^.output, '('); | ||||
|   WriteString(context^.output, "("); | ||||
|   WriteLine(context^.output); | ||||
|   WriteString(context^.output, '    '); | ||||
|   WriteString(context^.output, "    "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(current_case^[1]), @current_case^[2]); | ||||
|   current_case := current_case + 1; | ||||
|  | ||||
|   while ORD(current_case^[1]) <> 0 do | ||||
|     WriteChar(context^.output, ','); | ||||
|     WriteLine(context^.output); | ||||
|     WriteString(context^.output, '    '); | ||||
|     WriteString(context^.output, "    "); | ||||
|     written_bytes := WriteNBytes(context^.output, ORD(current_case^[1]), @current_case^[2]); | ||||
|  | ||||
|     current_case := current_case + 1 | ||||
|   end; | ||||
|   WriteLine(context^.output); | ||||
|   WriteString(context^.output, '  )') | ||||
|   WriteString(context^.output, "  )") | ||||
| end; | ||||
|  | ||||
| proc transpile_named_type(context: ^TranspilerContext, type_expression: ^AstTypeExpression); | ||||
| @@ -231,7 +231,7 @@ var | ||||
|   current_parameter: ^^AstTypeExpression; | ||||
|   parameter_count: Word; | ||||
| begin | ||||
|   WriteString(context^.output, 'PROCEDURE('); | ||||
|   WriteString(context^.output, "PROCEDURE("); | ||||
|   current_parameter := type_expression^.parameters; | ||||
|  | ||||
|   while current_parameter^ <> nil do | ||||
| @@ -240,7 +240,7 @@ begin | ||||
|     current_parameter := current_parameter + 1; | ||||
|  | ||||
|     if current_parameter^ <> nil then | ||||
|       WriteString(context^.output, ', ') | ||||
|       WriteString(context^.output, ", ") | ||||
|     end | ||||
|   end; | ||||
|   WriteChar(context^.output, ')') | ||||
| @@ -272,10 +272,10 @@ proc transpile_type_declaration(context: ^TranspilerContext, declaration: ^AstTy | ||||
| var | ||||
|   written_bytes: Word; | ||||
| begin | ||||
|   WriteString(context^.output, '  '); | ||||
|   WriteString(context^.output, "  "); | ||||
|  | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(declaration^.identifier[1]), @declaration^.identifier[2]); | ||||
|   WriteString(context^.output, ' = '); | ||||
|   WriteString(context^.output, " = "); | ||||
|  | ||||
|   transpile_type_expression(context, declaration^.type_expression); | ||||
|   write_semicolon(context^.output) | ||||
| @@ -286,7 +286,7 @@ var | ||||
|   current_declaration: ^^AstTypedDeclaration; | ||||
| begin | ||||
|   if declarations^ <> nil then | ||||
|     WriteString(context^.output, 'TYPE'); | ||||
|     WriteString(context^.output, "TYPE"); | ||||
|     WriteLine(context^.output); | ||||
|  | ||||
|     current_declaration := declarations; | ||||
| @@ -303,10 +303,10 @@ proc transpile_variable_declaration(context: ^TranspilerContext, declaration: ^A | ||||
| var | ||||
|   written_bytes: Word; | ||||
| begin | ||||
|   WriteString(context^.output, '  '); | ||||
|   WriteString(context^.output, "  "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(declaration^.variable_name[1]), @declaration^.variable_name[2]); | ||||
|  | ||||
|   WriteString(context^.output, ': '); | ||||
|   WriteString(context^.output, ": "); | ||||
|  | ||||
|   transpile_type_expression(context, declaration^.variable_type); | ||||
|   write_semicolon(context^.output) | ||||
| @@ -317,7 +317,7 @@ var | ||||
|   current_declaration: ^^AstVariableDeclaration; | ||||
| begin | ||||
|   if declarations^ <> nil then | ||||
|     WriteString(context^.output, 'VAR'); | ||||
|     WriteString(context^.output, "VAR"); | ||||
|     WriteLine(context^.output); | ||||
|  | ||||
|     current_declaration := declarations; | ||||
| @@ -338,7 +338,7 @@ var | ||||
|   parameter_index: Word; | ||||
|   current_parameter: ^AstTypedDeclaration; | ||||
| begin | ||||
|   WriteString(context^.output, 'PROCEDURE '); | ||||
|   WriteString(context^.output, "PROCEDURE "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(declaration^.name[1]), @declaration^.name[2]); | ||||
|   WriteChar(context^.output, '('); | ||||
|  | ||||
| @@ -347,22 +347,22 @@ begin | ||||
|  | ||||
|   while parameter_index < declaration^.parameter_count do | ||||
|     written_bytes := WriteNBytes(context^.output, ORD(current_parameter^.identifier[1]), @current_parameter^.identifier[2]); | ||||
|     WriteString(context^.output, ': '); | ||||
|     WriteString(context^.output, ": "); | ||||
|     transpile_type_expression(context, current_parameter^.type_expression); | ||||
|  | ||||
|     parameter_index := parameter_index + 1u; | ||||
|     current_parameter := current_parameter + 1; | ||||
|  | ||||
|     if parameter_index <> declaration^.parameter_count then | ||||
|       WriteString(context^.output, '; ') | ||||
|       WriteString(context^.output, "; ") | ||||
|     end | ||||
|   end; | ||||
|  | ||||
|   WriteString(context^.output, ')'); | ||||
|   WriteString(context^.output, ")"); | ||||
|  | ||||
|   (* Check for the return type and write it. *) | ||||
|   if declaration^.return_type <> nil then | ||||
|     WriteString(context^.output, ': '); | ||||
|     WriteString(context^.output, ": "); | ||||
|     transpile_type_expression(context, declaration^.return_type) | ||||
|   end; | ||||
|   write_semicolon(context^.output) | ||||
| @@ -388,10 +388,10 @@ begin | ||||
| 	| AstBinaryOperator.not_equals: WriteChar(context^.output, '#') | ||||
| 	| AstBinaryOperator.less: WriteChar(context^.output, '<') | ||||
| 	| AstBinaryOperator.greater: WriteChar(context^.output, '>') | ||||
|   	| AstBinaryOperator.less_equal: WriteString(context^.output, '<=') | ||||
|   	| AstBinaryOperator.greater_equal: WriteString(context^.output, '>=') | ||||
|   	| AstBinaryOperator.disjunction: WriteString(context^.output, 'OR') | ||||
| 	| AstBinaryOperatorConjunction: WriteString(context^.output, 'AND') | ||||
|   	| AstBinaryOperator.less_equal: WriteString(context^.output, "<=") | ||||
|   	| AstBinaryOperator.greater_equal: WriteString(context^.output, ">=") | ||||
|   	| AstBinaryOperator.disjunction: WriteString(context^.output, "OR") | ||||
| 	| AstBinaryOperatorConjunction: WriteString(context^.output, "AND") | ||||
|   end | ||||
| end; | ||||
|  | ||||
| @@ -414,13 +414,13 @@ begin | ||||
|       WriteString(context^.output, literal^.string) | ||||
|     end; | ||||
|     if literal^.kind = AstLiteralKind.null then | ||||
|       WriteString(context^.output, 'NIL') | ||||
|       WriteString(context^.output, "NIL") | ||||
|     end; | ||||
|     if (literal^.kind = AstLiteralKind.boolean) & literal^.boolean then | ||||
|       WriteString(context^.output, 'TRUE') | ||||
|       WriteString(context^.output, "TRUE") | ||||
|     end; | ||||
|     if (literal^.kind = AstLiteralKind.boolean) & (literal^.boolean = false) then | ||||
|       WriteString(context^.output, 'FALSE') | ||||
|       WriteString(context^.output, "FALSE") | ||||
|     end | ||||
|   end; | ||||
|   if expression^.kind = astExpressionKindIdentifier then | ||||
| @@ -466,7 +466,7 @@ begin | ||||
|       current_argument := current_argument + 1; | ||||
|  | ||||
|       while argument_index < expression^.argument_count do | ||||
|         WriteString(context^.output, ', '); | ||||
|         WriteString(context^.output, ", "); | ||||
|  | ||||
|         transpile_expression(context, current_argument^); | ||||
|  | ||||
| @@ -480,44 +480,44 @@ end; | ||||
|  | ||||
| proc transpile_if_statement(context: ^TranspilerContext, statement: ^AstStatement); | ||||
| begin | ||||
|   WriteString(context^.output, 'IF '); | ||||
|   WriteString(context^.output, "IF "); | ||||
|   transpile_expression(context, statement^.if_condition); | ||||
|  | ||||
|   WriteString(context^.output, ' THEN'); | ||||
|   WriteString(context^.output, " THEN"); | ||||
|   WriteLine(context^.output); | ||||
|   context^.indentation := context^.indentation + 1u; | ||||
|  | ||||
|   transpile_compound_statement(context, statement^.if_branch); | ||||
|   context^.indentation := context^.indentation - 1u; | ||||
|   indent(context); | ||||
|   WriteString(context^.output, 'END') | ||||
|   WriteString(context^.output, "END") | ||||
| end; | ||||
|  | ||||
| proc transpile_while_statement(context: ^TranspilerContext, statement: ^AstStatement); | ||||
| begin | ||||
|   WriteString(context^.output, 'WHILE '); | ||||
|   WriteString(context^.output, "WHILE "); | ||||
|   transpile_expression(context, statement^.while_condition); | ||||
|  | ||||
|   WriteString(context^.output, ' DO'); | ||||
|   WriteString(context^.output, " DO"); | ||||
|   WriteLine(context^.output); | ||||
|   context^.indentation := context^.indentation + 1u; | ||||
|  | ||||
|   transpile_compound_statement(context, statement^.while_body); | ||||
|   context^.indentation := context^.indentation - 1u; | ||||
|   indent(context); | ||||
|   WriteString(context^.output, 'END') | ||||
|   WriteString(context^.output, "END") | ||||
| end; | ||||
|  | ||||
| proc transpile_assignment_statement(context: ^TranspilerContext, statement: ^AstStatement); | ||||
| begin | ||||
|   transpile_expression(context, statement^.assignee); | ||||
|   WriteString(context^.output, ' := '); | ||||
|   WriteString(context^.output, " := "); | ||||
|   transpile_expression(context, statement^.assignment) | ||||
| end; | ||||
|  | ||||
| proc transpile_return_statement(context: ^TranspilerContext, statement: ^AstStatement); | ||||
| begin | ||||
|   WriteString(context^.output, 'RETURN '); | ||||
|   WriteString(context^.output, "RETURN "); | ||||
|  | ||||
|   transpile_expression(context, statement^.returned) | ||||
| end; | ||||
| @@ -567,7 +567,7 @@ end; | ||||
| proc transpile_statement_part(context: ^TranspilerContext, compound: AstCompoundStatement); | ||||
| begin | ||||
|   if compound.count > 0 then | ||||
|     WriteString(context^.output, 'BEGIN'); | ||||
|     WriteString(context^.output, "BEGIN"); | ||||
|     WriteLine(context^.output); | ||||
|  | ||||
|     context^.indentation := context^.indentation + 1u; | ||||
| @@ -586,7 +586,7 @@ begin | ||||
|   transpile_variable_part(context, declaration^.variables, false); | ||||
|   transpile_statement_part(context, declaration^.statements); | ||||
|  | ||||
|   WriteString(context^.output, 'END '); | ||||
|   WriteString(context^.output, "END "); | ||||
|   written_bytes := WriteNBytes(context^.output, ORD(declaration^.name[1]), @declaration^.name[2]); | ||||
|  | ||||
|   write_semicolon(context^.output) | ||||
|   | ||||
							
								
								
									
										11
									
								
								source/cctype.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								source/cctype.elna
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| (* This Source Code Form is subject to the terms of the Mozilla Public License, | ||||
|   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/. *) | ||||
| module; | ||||
|  | ||||
| proc isdigit(c: Int ) -> Int; extern; | ||||
| proc isalnum(c: Int) -> Int; extern; | ||||
| proc isalpha(c: Int) -> Int; extern; | ||||
| proc isspace(c: Int) -> Int; extern; | ||||
|  | ||||
| end. | ||||
| @@ -10,6 +10,5 @@ type | ||||
|     line: Word; | ||||
|     column: Word | ||||
|   end; | ||||
|   FILE* = record end; | ||||
| 
 | ||||
| end. | ||||
							
								
								
									
										23
									
								
								source/cstdio.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								source/cstdio.elna
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| (* This Source Code Form is subject to the terms of the Mozilla Public License, | ||||
|   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/. *) | ||||
| module; | ||||
|  | ||||
| type | ||||
|   FILE* = record end; | ||||
|  | ||||
| proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern; | ||||
| proc fclose(stream: ^FILE) -> Int; extern; | ||||
| proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern; | ||||
| proc rewind(stream: ^FILE); extern; | ||||
| proc ftell(stream: ^FILE) -> Int; extern; | ||||
| proc fflush(stream: ^FILE) -> Int; extern; | ||||
|  | ||||
| proc fread(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern; | ||||
|  | ||||
| proc perror(s: ^Char); extern; | ||||
|  | ||||
| proc puts(s: ^Char) -> Int; extern; | ||||
| proc putchar(c: Int) -> Int; extern; | ||||
|  | ||||
| end. | ||||
							
								
								
									
										13
									
								
								source/cstdlib.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								source/cstdlib.elna
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| (* This Source Code Form is subject to the terms of the Mozilla Public License, | ||||
|   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/. *) | ||||
| module; | ||||
|  | ||||
| proc malloc(size: Word) -> Pointer; extern; | ||||
| proc free(ptr: Pointer); extern; | ||||
| proc calloc(nmemb: Word, size: Word) -> Pointer; extern; | ||||
| proc realloc(ptr: Pointer, size: Word) -> Pointer; extern; | ||||
|  | ||||
| proc exit(code: Int) -> !; extern; | ||||
|  | ||||
| end. | ||||
							
								
								
									
										15
									
								
								source/cstring.elna
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								source/cstring.elna
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| (* This Source Code Form is subject to the terms of the Mozilla Public License, | ||||
|   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/. *) | ||||
| module; | ||||
|  | ||||
| proc memset(ptr: Pointer, c: Int, n: Int) -> ^Char; extern; | ||||
| proc memcpy(dst: Pointer, src: Pointer, n: Word); extern; | ||||
|  | ||||
| proc strcmp(s1: ^Char, s2: ^Char) -> Int; extern; | ||||
| proc strncmp(s1: ^Char, s2: ^Char, n: Word) -> Int; extern; | ||||
| proc strncpy(dst: ^Char, src: ^Char, dsize: Word) -> ^Char; extern; | ||||
| proc strcpy(dst: ^Char, src: ^Char) -> ^Char; extern; | ||||
| proc strlen(ptr: ^Char) -> Word; extern; | ||||
|  | ||||
| end. | ||||
| @@ -3,7 +3,7 @@ | ||||
|   obtain one at https://mozilla.org/MPL/2.0/. *) | ||||
| program; | ||||
|  | ||||
| import Common, Lexer; | ||||
| import cstdlib, cstring, cstdio, cctype, common, Lexer; | ||||
|  | ||||
| const | ||||
|   SEEK_SET* := 0; | ||||
| @@ -127,30 +127,8 @@ type | ||||
|   External procedures. | ||||
| *) | ||||
|  | ||||
| proc fopen(pathname: ^Char, mode: ^Char) -> ^FILE; extern; | ||||
| proc fclose(stream: ^FILE) -> Int; extern; | ||||
| proc fseek(stream: ^FILE, off: Int, whence: Int) -> Int; extern; | ||||
| proc rewind(stream: ^FILE); extern; | ||||
| proc ftell(stream: ^FILE) -> Int; extern; | ||||
| proc fread(ptr: Pointer, size: Word, nmemb: Word, stream: ^FILE) -> Word; extern; | ||||
| proc write(fd: Int, buf: Pointer, Word: Int) -> Int; extern; | ||||
|  | ||||
| proc malloc(size: Word) -> Pointer; extern; | ||||
| proc free(ptr: Pointer); extern; | ||||
| proc calloc(nmemb: Word, size: Word) -> Pointer; extern; | ||||
| proc realloc(ptr: Pointer, size: Word) -> Pointer; extern; | ||||
|  | ||||
| proc memset(ptr: ^Char, c: Int, n: Int) -> ^Char; extern; | ||||
|  | ||||
| proc strcmp(s1: ^Char, s2: ^Char) -> Int; extern; | ||||
| proc strncmp(s1: ^Char, s2: ^Char, n: Word) -> Int; extern; | ||||
| proc strncpy(dst: ^Char, src: ^Char, dsize: Word) -> ^Char; extern; | ||||
| proc strcpy(dst: ^Char, src: ^Char) -> ^Char; extern; | ||||
| proc strlen(ptr: ^Char) -> Word; extern; | ||||
|  | ||||
| proc perror(s: ^Char); extern; | ||||
| proc exit(code: Int) -> !; extern; | ||||
|  | ||||
| (* | ||||
|   Standard procedures. | ||||
| *) | ||||
| @@ -161,12 +139,12 @@ end; | ||||
|  | ||||
| proc write_s(value: String); | ||||
| begin | ||||
|   write(0, cast(value.ptr: Pointer), cast(value.length: Int)) | ||||
|   write(1, cast(value.ptr: Pointer), cast(value.length: Int)) | ||||
| end; | ||||
|  | ||||
| proc write_z(value: ^Char); | ||||
| begin | ||||
|   write(0, cast(value: Pointer), cast(strlen(value): Int)) | ||||
|   write(1, cast(value: Pointer), cast(strlen(value): Int)) | ||||
| end; | ||||
|  | ||||
| proc write_b(value: Bool); | ||||
| @@ -180,7 +158,8 @@ end; | ||||
|  | ||||
| proc write_c(value: Char); | ||||
| begin | ||||
|   write(0, cast(@value: Pointer), 1) | ||||
|   putchar(cast(value: Int)); | ||||
|   fflush(nil) | ||||
| end; | ||||
|  | ||||
| proc write_i(value: Int); | ||||
| @@ -212,22 +191,6 @@ begin | ||||
|   write_i(cast(value: Int)) | ||||
| end; | ||||
|  | ||||
| proc is_digit(c: Char) -> Bool; | ||||
|   return cast(c: Int) >= cast('0': Int) & cast(c: Int) <= cast('9': Int) | ||||
| end; | ||||
|  | ||||
| proc is_alpha(c: Char) -> Bool; | ||||
|   return cast(c: Int) >= cast('A': Int) & cast(c: Int) <= cast('z': Int) | ||||
| end; | ||||
|  | ||||
| proc is_alnum(c: Char) -> Bool; | ||||
|   return is_digit(c) or is_alpha(c) | ||||
| end; | ||||
|  | ||||
| proc is_space(c: Char) -> Bool; | ||||
|   return c = ' ' or c = '\n' or c = '\t' | ||||
| end; | ||||
|  | ||||
| proc substring(string: String, start: Word, count: Word) -> String; | ||||
|   return String(string.ptr + start, count) | ||||
| end; | ||||
| @@ -412,7 +375,7 @@ proc lexer_spaces(source_code: ^SourceCode); | ||||
| var | ||||
|   current: Char; | ||||
| begin | ||||
|   while ~source_code_empty(source_code) & is_space(source_code_head(source_code^)) do | ||||
|   while ~source_code_empty(source_code) & isspace(cast(source_code_head(source_code^): Int)) <> 0 do | ||||
|     current := source_code_head(source_code^); | ||||
|  | ||||
|     if current = '\n' then | ||||
| @@ -424,7 +387,7 @@ end; | ||||
|  | ||||
| (* Checker whether the character is allowed in an identificator. *) | ||||
| proc lexer_is_ident(char: Char) -> Bool; | ||||
|   return is_alnum(char) or char = '_' | ||||
|   return isalnum(cast(char: Int)) <> 0 or char = '_' | ||||
| end; | ||||
|  | ||||
| proc lexer_identifier(source_code: ^SourceCode, token_content: ^StringBuffer); | ||||
| @@ -511,7 +474,7 @@ proc lexer_number(source_code: ^SourceCode, token_content: ^Int); | ||||
| begin | ||||
|   token_content^ := 0; | ||||
|  | ||||
|   while ~source_code_empty(source_code) & is_digit(source_code_head(source_code^)) do | ||||
|   while ~source_code_empty(source_code) & isdigit(cast(source_code_head(source_code^): Int)) <> 0 do | ||||
|     token_content^ := token_content^ * 10 + (cast(source_code_head(source_code^): Int) - cast('0': Int)); | ||||
|  | ||||
|     source_code_advance(source_code) | ||||
| @@ -607,7 +570,7 @@ begin | ||||
|  | ||||
|   first_char := source_code_head(source_code); | ||||
|  | ||||
|   if is_alpha(first_char) or first_char = '_' then | ||||
|   if isalpha(cast(first_char: Int)) <> 0 or first_char = '_' then | ||||
|     lexer_identifier(@source_code, token_buffer); | ||||
|     current_token := lexer_categorize(string_buffer_clear(token_buffer)) | ||||
|   elsif first_char = '#' then | ||||
| @@ -616,7 +579,7 @@ begin | ||||
|  | ||||
|     current_token.kind := TokenKind.trait; | ||||
|     current_token.value.string := string_dup(string_buffer_clear(token_buffer)) | ||||
|   elsif is_digit(first_char) then | ||||
|   elsif isdigit(cast(first_char: Int)) <> 0 then | ||||
|     lexer_number(@source_code, @current_token.value.int_value); | ||||
|  | ||||
|     if source_code_expect(@source_code, 'u') then | ||||
|   | ||||
		Reference in New Issue
	
	Block a user