aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/ast.elna270
-rw-r--r--source/command_line_interface.elna89
-rw-r--r--source/common.elna88
-rw-r--r--source/diagnostic.elna241
-rw-r--r--source/lexer.elna815
-rw-r--r--source/main.elna138
-rw-r--r--source/name_analysis.elna539
-rw-r--r--source/parser.elna1162
-rw-r--r--source/qbe.elna635
-rw-r--r--source/symbol.elna200
-rw-r--r--source/sys/posix/cctype.elna24
-rw-r--r--source/sys/posix/cstdio.elna59
-rw-r--r--source/sys/posix/cstdlib.elna24
-rw-r--r--source/sys/posix/cstring.elna30
-rw-r--r--source/tac.elna1074
-rw-r--r--source/type_check.elna315
16 files changed, 1 insertions, 5702 deletions
diff --git a/source/ast.elna b/source/ast.elna
deleted file mode 100644
index ddae997..0000000
--- a/source/ast.elna
+++ /dev/null
@@ -1,270 +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/. *)
-module
-import common, lexer
-
-type
- ElnaListNode* = record
- next: ^ElnaListNode
- end
- ElnaList* = record
- first: ^ElnaListNode;
- last: ^ElnaListNode
- end
-
- (* Type representation. *)
- ElnaTypeKind* = (primitive, enumeration, _record, pointer, array, alias, procedure)
- ElnaType* = record
- kind: ElnaTypeKind;
- size: Word;
- alignment: Word
- end
- ElnaTypeAlias* = record(ElnaType)
- base: ^ElnaType
- end
- ElnaTypeEnumeration* = record(ElnaType)
- members: ^[]const Word8;
- length: Word
- end
- ElnaTypeField* = record
- name: []const Word8;
- field_type: ^ElnaType
- end
- ElnaTypeRecord* = record(ElnaType)
- members: ^ElnaTypeField;
- length: Word
- end
- ElnaTypePointer* = record(ElnaType)
- base: ^ElnaType
- end
- ElnaTypeArray* = record(ElnaType)
- base: ^ElnaType;
- length: Word
- end
- ElnaTypeProcedure* = record(ElnaType)
- return_type: ^ElnaType
- end
-
- (* Abstract syntax tree nodes. *)
- ElnaTreeKind* = (
- integer_literal,
- string_literal,
- character_literal,
- boolean_literal,
- variable_expression,
- field_access_expression,
- dereference_expression,
- unary_expression,
- binary_expression,
- call,
- call_statement,
- goto_statement,
- label_declaration,
- return_statement,
- assign_statement,
- if_statement,
- procedure_declaration,
- variable_declaration,
- enumeration_type_expression,
- named_type_expression,
- type_declaration,
- module_declaration,
- record_type_expression,
- pointer_type_expression,
- array_type_expression,
- null,
- trait_expression,
- array_access_expression,
- _cast
- )
- ElnaTreeNode* = record
- kind: ElnaTreeKind;
- position: ElnaPosition
- end
- ElnaTreeTypeExpression* = record(ElnaTreeNode)
- end
- ElnaTreeExpression* = record(ElnaTreeNode)
- type_decoration: ^ElnaType
- end
- ElnaTreeIntegerLiteral* = record(ElnaTreeExpression)
- value: Word
- end
- ElnaTreeCharacterLiteral* = record(ElnaTreeExpression)
- value: Word8
- end
- ElnaTreeNilLiteral* = record(ElnaTreeExpression)
- end
- ElnaTreeBooleanLiteral* = record(ElnaTreeExpression)
- value: Bool
- end
- ElnaTreeStringLiteral* = record(ElnaTreeExpression)
- value: []const Word8
- end
- ElnaTreeVariableExpression* = record(ElnaTreeExpression)
- name: []const Word8
- end
- ElnaTreeCastExpression* = record(ElnaTreeExpression)
- expression: ^ElnaTreeExpression;
- type_expression: ^ElnaTreeTypeExpression
- end
- ElnaTreeDereferenceExpression* = record(ElnaTreeExpression)
- pointer: ^ElnaTreeExpression
- end
- ElnaTreeBinaryExpression* = record(ElnaTreeExpression)
- lhs: ^ElnaTreeExpression;
- rhs: ^ElnaTreeExpression;
- operator: ElnaLexerKind
- end
- ElnaTreeUnaryExpression* = record(ElnaTreeExpression)
- operand: ^ElnaTreeExpression;
- operator: ElnaLexerKind
- end
- ElnaTreeFieldAccessExpression* = record(ElnaTreeExpression)
- aggregate: ^ElnaTreeExpression;
- field: []const Word8
- end
- ElnaTreeArrayAccessExpression* = record(ElnaTreeExpression)
- array: ^ElnaTreeExpression;
- index: ^ElnaTreeExpression
- end
- ElnaTreeTraitExpression* = record(ElnaTreeExpression)
- name: []const Word8;
- argument: ^ElnaTreeTypeExpression
- end
- ElnaTreeExpressionList* = record
- expression: ^ElnaTreeExpression;
- next: ^ElnaTreeExpressionList
- end
- ElnaTreeCall* = record(ElnaTreeExpression)
- callee: ^ElnaTreeVariableExpression;
- arguments: ^ElnaTreeExpressionList;
- count: Word
- end
-
- (* Statements. *)
- ElnaTreeStatement* = record(ElnaTreeNode)
- next: ^ElnaTreeStatement
- end
- ElnaTreeConditionalStatements* = record
- condition: ^ElnaTreeExpression;
- statements: ^ElnaTreeStatement;
- next: ^ElnaTreeConditionalStatements
- end
- ElnaTreeIfStatement* = record(ElnaTreeStatement)
- conditionals: ^ElnaTreeConditionalStatements;
- _else: ^ElnaTreeStatement
- end
- ElnaTreeGotoStatement* = record(ElnaTreeStatement)
- label: []const Word8
- end
- ElnaTreeAssignStatement* = record(ElnaTreeStatement)
- assignee: ^ElnaTreeExpression;
- assignment: ^ElnaTreeExpression
- end
- ElnaTreeReturnStatement* = record(ElnaTreeStatement)
- returned: ^ElnaTreeExpression
- end
- ElnaTreeLabelDeclaration* = record(ElnaTreeStatement)
- label: []const Word8
- end
- ElnaTreeCallStatement* = record(ElnaTreeStatement)
- call: ^ElnaTreeCall
- end
-
- (* Type expressions. *)
- ElnaTreeEnumeration* = record
- name: []const Word8;
- next: ^ElnaTreeEnumeration
- end
- ElnaTreeEnumerationTypeExpression* = record(ElnaTreeTypeExpression)
- members: ^ElnaTreeEnumeration;
- length: Word
- end
- ElnaTreeField* = record
- name: []const Word8;
- type_expression: ^ElnaTreeTypeExpression;
- next: ^ElnaTreeField
- end
- ElnaTreeRecordTypeExpression* = record(ElnaTreeTypeExpression)
- members: ^ElnaTreeField;
- length: Word;
- parent: []const Word8
- end
- ElnaTreeNamedTypeExpression* = record(ElnaTreeTypeExpression)
- name: []const Word8
- end
- ElnaTreePointerTypeExpression* = record(ElnaTreeTypeExpression)
- base: ^ElnaTreeTypeExpression
- end
- ElnaTreeArrayTypeExpression* = record(ElnaTreeTypeExpression)
- base: ^ElnaTreeTypeExpression;
- length: ^ElnaTreeExpression
- end
-
- (* Declarations. *)
- ElnaTreeDeclaration* = record(ElnaTreeNode)
- next: ^ElnaTreeDeclaration;
- name: []const Word8
- end
- ElnaTreeVariableDeclaration* = record(ElnaTreeDeclaration)
- type_expression: ^ElnaTreeTypeExpression
- end
- ElnaTreeProcedureDeclaration* = record(ElnaTreeDeclaration)
- body: ^ElnaTreeStatement;
- temporaries: ^ElnaTreeVariableDeclaration;
- parameters: ^ElnaTreeVariableDeclaration;
- return_type: ^ElnaTreeTypeExpression;
- is_extern: Bool
- end
- ElnaTreeTypeDeclaration* = record(ElnaTreeDeclaration)
- type_expression: ^ElnaTreeTypeExpression
- end
- ElnaTreeModuleDeclaration* = record(ElnaTreeNode)
- types: ^ElnaTreeDeclaration;
- globals: ^ElnaTreeVariableDeclaration;
- procedures: ^ElnaTreeProcedureDeclaration;
- body: ^ElnaTreeStatement
- end
-
-proc elna_list_initialize*(list: ^ElnaList)
-begin
- list^.first := nil;
- list^.last := nil
-return
-
-proc elna_list_append*(list: ^ElnaList; element: ^ElnaListNode) -> ^ElnaListNode
-begin
- if element <> nil then
- if list^.first = nil then
- list^.first := element
- else
- list^.last^.next := element
- end;
- list^.last := element
- end
-return element
-
-proc elna_list_prepend*(list: ^ElnaList; element: ^ElnaListNode)
-begin
- element^.next := list^.first;
- list^.first := element;
- if list^.last = nil then
- list^.last := element
- end
-return
-
-proc elna_list_insert*(list: ^ElnaList; existing, new: ^ElnaListNode)
-begin
- if existing^.next = nil then
- list^.last := new
- else
- new^.next := existing^.next
- end;
- existing^.next := new
-return
-
-proc elna_list_empty*(list: ^ElnaList) -> Bool
-return list^.first = nil
-
-end.
diff --git a/source/command_line_interface.elna b/source/command_line_interface.elna
deleted file mode 100644
index 4c3c1a6..0000000
--- a/source/command_line_interface.elna
+++ /dev/null
@@ -1,89 +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/. *)
-(*
- Command line handling.
-*)
-module
-import sys.posix.cstdlib, sys.posix.cstring, common
-
-type
- CommandLine* = record
- input: ^Word8;
- output: ^Word8;
- lex: Bool;
- parse: Bool
- end
-
-proc parse_command_line*(argc: Int; argv: ^^Word8) -> ^CommandLine
-var
- parameter: ^Word8
- i: Int
- result: ^CommandLine
- parsed: Bool
-begin
- i := 1;
- result := malloc#[CommandLine](#size(CommandLine));
- result^.lex := false;
- result^.parse := false;
- result^.input := nil;
- result^.output := nil;
-
- while i < argc & result <> nil do
- parameter := (argv + i)^;
- parsed := false;
-
- if strcmp(parameter, "--lex\0".ptr) = 0 then
- parsed := true;
- result^.lex := true
- end;
- if strcmp(parameter, "--parse\0".ptr) = 0 then
- parsed := true;
- result^.parse := true
- end;
- if strcmp(parameter, "-o\0".ptr) = 0 then
- i := i + 1;
-
- if i = argc then
- write_s("Fatal error: expecting a file name following -o.");
- result := nil
- end;
- if i < argc then
- parameter := (argv + i)^;
- result^.output := parameter
- end;
- parsed := true
- end;
- if (parameter^ <> '-') & ~parsed then
- parsed := true;
-
- if result^.input <> nil then
- write_s("Fatal error: only one source file can be compiled at once. First given \"");
- write_z(result^.input);
- write_s("\", then \"");
- write_z(parameter);
- write_s("\".\n");
- result := nil
- end;
- if result <> nil then
- result^.input := parameter
- end
- end;
- if ~parsed then
- write_s("Fatal error: unknown command line options: ");
-
- write_z(parameter);
- write_s(".\n");
-
- result := nil
- end;
-
- i := i + 1
- end;
- if result <> nil & result^.input = nil then
- write_s("Fatal error: no input files.\n");
- result := nil
- end
-return result
-
-end.
diff --git a/source/common.elna b/source/common.elna
deleted file mode 100644
index 93b4363..0000000
--- a/source/common.elna
+++ /dev/null
@@ -1,88 +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/. *)
-module
-import sys.posix.cstring, sys.posix.cstdio, sys.posix.cstdlib
-
-type
- ElnaLocation* = record
- line: Word;
- column: Word
- end
- ElnaPosition* = record
- start_location: ElnaLocation;
- end_location: ElnaLocation
- end
-
-proc write*#[T](fd: Int; buf: ^const T; size: Word) -> Int
-extern
-
-proc write_s*(value: []const Word8)
- write(1, value.ptr, value.length)
-return
-
-proc write_z*(value: ^Word8)
- write(1, value, strlen(value))
-return
-
-proc write_b*(value: Bool)
- if value then
- write_s("true")
- else
- write_s("false")
- end
-return
-
-proc write_c*(value: Word8)
- putchar(cast(value: Int));
- fflush(nil)
-return
-
-proc write_i*(value: Int)
-var
- digit: Int
- n: Word
- buffer: [10]Word8
-begin
- n := 10u;
-
- if value = 0 then
- write_c('0')
- end;
- while value <> 0 do
- digit := value % 10;
- value := value / 10;
-
- buffer[n] := cast(cast('0': Int) + digit: Word8);
- n := n - 1u
- end;
- while n < 10u do
- n := n + 1u;
- write_c(buffer[n])
- end
-return
-
-proc write_u*(value: Word)
- write_i(cast(value: Int))
-return
-
-(* Returns true or false depending whether two strings are equal. *)
-proc string_compare*(lhs_pointer: ^Word8; lhs_length: Word; rhs_pointer: []const Word8) -> Bool
-var
- result: Bool
-begin
- if lhs_length = rhs_pointer.length then
- result := memcmp(lhs_pointer, rhs_pointer.ptr, lhs_length) = 0
- else
- result := false
- end
-return result
-
-proc free_and_nil*#[T](ptr: ^T) -> ^T
-begin
- if ptr <> nil then
- free(ptr)
- end
-return nil
-
-end.
diff --git a/source/diagnostic.elna b/source/diagnostic.elna
deleted file mode 100644
index 2356544..0000000
--- a/source/diagnostic.elna
+++ /dev/null
@@ -1,241 +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/. *)
-module
-import common, sys.posix.cstdio, sys.posix.cstdlib, lexer, ast
-
-type
- ElnaErrorKind* = (
- unexpected_token,
- undefined_symbol,
- undefined_member,
- duplicate_declaration
- )
- ElnaError* = record(ElnaListNode)
- kind: ElnaErrorKind;
- position: ElnaPosition
- end
- ElnaErrorUnexpectedToken* = record(ElnaError)
- expected: [16]ElnaLexerKind;
- possibilities: Word;
- got: ElnaLexerKind
- end
- ElnaErrorUndefinedSymbol* = record(ElnaError)
- symbol_name: []const Word8
- end
- ElnaErrorUndefinedMember* = record(ElnaError)
- aggregate_name: []const Word8;
- member_name: []const Word8
- end
- ElnaErrorDuplicateDeclaration* = record(ElnaError)
- symbol_name: []const Word8
- end
-
-proc elna_error_unexpected_token_create*(cursor: ^ElnaLexerCursor; number_of_expected: Word) -> ^ElnaErrorUnexpectedToken
-var
- parser_error: ^ElnaErrorUnexpectedToken
-begin
- parser_error := malloc#[ElnaErrorUnexpectedToken](#size(ElnaErrorUnexpectedToken));
- parser_error^.next := nil;
- parser_error^.kind := ElnaErrorKind.unexpected_token;
- parser_error^.position := cursor^.position;
- parser_error^.possibilities := number_of_expected;
- parser_error^.got := cursor^.token^.kind
-return parser_error
-
-proc elna_error_duplicate_declaration_create*(position: ElnaPosition; symbol_name: []const Word8) -> ^ElnaErrorDuplicateDeclaration
-var
- declaration_error: ^ElnaErrorDuplicateDeclaration
-begin
- declaration_error := malloc#[ElnaErrorDuplicateDeclaration](#size(ElnaErrorDuplicateDeclaration));
- declaration_error^.next := nil;
- declaration_error^.kind := ElnaErrorKind.duplicate_declaration;
- declaration_error^.position := position;
- declaration_error^.symbol_name := symbol_name
-return declaration_error
-
-proc elna_error_undefined_symbol_create*(position: ElnaPosition; symbol_name: []const Word8) -> ^ElnaErrorUndefinedSymbol
-var
- result: ^ElnaErrorUndefinedSymbol
-begin
- result := malloc#[ElnaErrorUndefinedSymbol](#size(ElnaErrorUndefinedSymbol));
- result^.next := nil;
- result^.kind := ElnaErrorKind.undefined_symbol;
- result^.position := position;
- result^.symbol_name := symbol_name
-return result
-
-proc elna_error_undefined_member_create*(position: ElnaPosition; aggregate, member: []const Word8) -> ^ElnaErrorUndefinedMember
-var
- result: ^ElnaErrorUndefinedMember
-begin
- result := malloc#[ElnaErrorUndefinedMember](#size(ElnaErrorUndefinedMember));
- result^.next := nil;
- result^.kind := ElnaErrorKind.undefined_member;
- result^.position := position;
- result^.aggregate_name := aggregate;
- result^.member_name := member
-return result
-
-proc elna_error_print_token*(kind: ElnaLexerKind)
-begin
- case kind of
- ElnaLexerKind._const:
- write_s("\"const\"")
- | ElnaLexerKind._var:
- write_s("\"var\"")
- | ElnaLexerKind._proc:
- write_s("\"proc\"")
- | ElnaLexerKind._type:
- write_s("\"type\"")
- | ElnaLexerKind._begin:
- write_s("\"begin\"")
- | ElnaLexerKind._end:
- write_s("\"end\"")
- | ElnaLexerKind._if:
- write_s("\"if\"")
- | ElnaLexerKind._then:
- write_s("\"then\"")
- | ElnaLexerKind._else:
- write_s("\"else\"")
- | ElnaLexerKind._elsif:
- write_s("\"elsif\"")
- | ElnaLexerKind._extern:
- write_s("\"extern\"")
- | ElnaLexerKind._record:
- write_s("\"record\"")
- | ElnaLexerKind.boolean:
- write_s("BOOLEAN")
- | ElnaLexerKind.null:
- write_s("NIL")
- | ElnaLexerKind.and:
- write_s("\"&\"")
- | ElnaLexerKind._or:
- write_s("\"or\"")
- | ElnaLexerKind._xor:
- write_s("\"xor\"")
- | ElnaLexerKind.not:
- write_s("\"~\"")
- | ElnaLexerKind._return:
- write_s("\"return\"")
- | ElnaLexerKind._cast:
- write_s("\"cast\"")
- | ElnaLexerKind.trait:
- write_s("TRAIT")
- | ElnaLexerKind.left_paren:
- write_s("\"(\"")
- | ElnaLexerKind.right_paren:
- write_s("\")\"")
- | ElnaLexerKind.left_square:
- write_s("\"[\"")
- | ElnaLexerKind.right_square:
- write_s("\"]\"")
- | ElnaLexerKind.greater_equal:
- write_s("\">=\"")
- | ElnaLexerKind.less_equal:
- write_s("\"<=\"")
- | ElnaLexerKind.greater_than:
- write_s("\">\"")
- | ElnaLexerKind.less_than:
- write_s("\"<\"")
- | ElnaLexerKind.not_equal:
- write_s("\"<>\"")
- | ElnaLexerKind.equals:
- write_s("\"=\"")
- | ElnaLexerKind.semicolon:
- write_s("\";\"")
- | ElnaLexerKind.dot:
- write_s("\".\"")
- | ElnaLexerKind.comma:
- write_s("\",\"")
- | ElnaLexerKind.plus:
- write_s("\"+\"")
- | ElnaLexerKind.arrow:
- write_s("\"->\"")
- | ElnaLexerKind.minus:
- write_s("\"-\"")
- | ElnaLexerKind.multiplication:
- write_s("\"*\"")
- | ElnaLexerKind.division:
- write_s("\"/\"")
- | ElnaLexerKind.remainder:
- write_s("\"%\"")
- | ElnaLexerKind.assignment:
- write_s("\":=\"")
- | ElnaLexerKind.colon:
- write_s("\":\"")
- | ElnaLexerKind.hat:
- write_s("\"^\"")
- | ElnaLexerKind.at:
- write_s("\"@\"")
- | ElnaLexerKind.comment:
- write_s("COMMENT")
- | ElnaLexerKind.string:
- write_s("STRING")
- | ElnaLexerKind.character:
- write_s("CHARACTER")
- | ElnaLexerKind.integer:
- write_s("INTEGER")
- | ElnaLexerKind.word:
- write_s("WORD")
- | ElnaLexerKind.eof:
- write_s("EOF")
- else
- write_s("UNKNOWN")
- end
-return
-
-proc elna_error_print_unexpected_token*(current_error: ^ElnaErrorUnexpectedToken)
-begin
- write_s("Parse error: Expecting token ");
- elna_error_print_token(current_error^.expected[1]);
- write_s("; got ");
- elna_error_print_token(current_error^.got);
- write_s(". ")
-return
-
-proc elna_error_print_undefined_member*(current_error: ^ElnaErrorUndefinedMember)
-begin
- write_s("Semantic error: Member \"");
- write_s(current_error^.member_name);
- write_s("\" is not accessible on \"");
- write_s(current_error^.aggregate_name);
- write_s("\". ")
-return
-
-proc elna_error_print_undefined_symbol*(current_error: ^ElnaErrorUndefinedSymbol)
-begin
- write_s("Semantic error: Undefined symbol \"");
- write_s(current_error^.symbol_name);
- write_s("\". ")
-return
-
-proc elna_error_print_duplicate_declaration*(current_error: ^ElnaErrorDuplicateDeclaration)
-begin
- write_s("Semantic error: Duplicate declaration \"");
- write_s(current_error^.symbol_name);
- write_s("\". ")
-return
-
-proc elna_error_print*(current_error: ^ElnaError)
-begin
- case current_error^.kind of
- ElnaErrorKind.unexpected_token:
- elna_error_print_unexpected_token(cast(current_error: ^ElnaErrorUnexpectedToken))
- | ElnaErrorKind.undefined_symbol:
- elna_error_print_undefined_symbol(cast(current_error: ^ElnaErrorUndefinedSymbol))
- | ElnaErrorKind.undefined_member:
- elna_error_print_undefined_member(cast(current_error: ^ElnaErrorUndefinedMember))
- | ElnaErrorKind.duplicate_declaration:
- elna_error_print_duplicate_declaration(cast(current_error: ^ElnaErrorDuplicateDeclaration))
- else
- write_s("Unknown error. ")
- end;
- write_s("Line ");
- write_u(current_error^.position.start_location.line);
- write_s(", column ");
- write_u(current_error^.position.start_location.column);
- write_s(".\n")
-return
-
-end.
diff --git a/source/lexer.elna b/source/lexer.elna
deleted file mode 100644
index 71e76a7..0000000
--- a/source/lexer.elna
+++ /dev/null
@@ -1,815 +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/. *)
-module
-import sys.posix.cstdio, common, sys.posix.cstdlib
-
-type
- ElnaLexerState* = (
- start,
- colon,
- identifier,
- decimal,
- leading_zero,
- greater,
- minus,
- left_paren,
- less,
- dot,
- comment,
- closing_comment,
- character,
- character_escape,
- string,
- string_escape,
- number_sign,
- trait,
- finish
- )
- ElnaLexerToken* = record
- kind: ElnaLexerKind;
- start: []const Word8;
- position: ElnaPosition
- end
- ElnaLexerBooleanToken* = record(ElnaLexerToken)
- value: Bool
- end
- ElnaLexerCharacterToken* = record(ElnaLexerToken)
- value: Word8
- end
- ElnaLexerStringToken* = record(ElnaLexerToken)
- value: []const Word8
- end
- ElnaLexerIntegerToken* = record(ElnaLexerToken)
- value: Int
- end
-
- TransitionAction = proc(lexer: ^Lexer; token: ^ElnaLexerToken)
- ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited)
-
- ElnaLexerTransition = record
- action: ElnaLexerAction;
- next_state: ElnaLexerState
- end
-
- ElnaLexerCursor* = record
- state: ElnaLexerState;
- start: ^Word8;
- finish: ^Word8;
- token: ^ElnaLexerToken;
- position: ElnaPosition
- end
-
- BufferPosition* = record
- iterator: ^Word8;
- location: ElnaLocation
- end
- Lexer* = record
- input: ^FILE;
- buffer: ^Word8;
- size: Word;
- length: Word;
- start: BufferPosition;
- current: BufferPosition
- end
- ElnaLexerKind* = (
- identifier,
- _const,
- _var,
- _proc,
- _type,
- _begin,
- _end,
- _if,
- _then,
- _else,
- _elsif,
- _extern,
- _record,
- boolean,
- null,
- and,
- _or,
- _xor,
- not,
- _return,
- _cast,
- trait,
- left_paren,
- right_paren,
- left_square,
- right_square,
- left_brace,
- right_brace,
- greater_equal,
- less_equal,
- greater_than,
- less_than,
- not_equal,
- equals,
- semicolon,
- dot,
- comma,
- plus,
- _import,
- minus,
- multiplication,
- division,
- remainder,
- assignment,
- colon,
- hat,
- at,
- comment,
- string,
- character,
- integer,
- word,
- _while,
- _defer,
- exclamation,
- shift_right,
- shift_left,
- pipe,
- _case,
- _do,
- _of,
- arrow,
- eof
- )
- (**
- * Classification table assigns each possible character to a group (class). All
- * characters of the same group a handled equivalently.
- *)
- ElnaLexerClass = (
- invalid,
- digit,
- alpha,
- space,
- colon,
- equals,
- left_paren,
- right_paren,
- asterisk,
- backslash,
- single,
- hex,
- zero,
- x,
- eof,
- dot,
- minus,
- single_quote,
- double_quote,
- greater,
- less,
- other,
- number_sign
- )
-
-var
- classification: [256]ElnaLexerClass
- transition_table: [19][23]ElnaLexerTransition
-
-proc elna_lexer_classifications1()
-begin
- classification[1] := ElnaLexerClass.eof;
- classification[10] := ElnaLexerClass.space;
- classification[11] := ElnaLexerClass.space;
- classification[14] := ElnaLexerClass.space;
- classification[33] := ElnaLexerClass.space;
- classification[34] := ElnaLexerClass.single
-return
-
-proc elna_lexer_classifications2()
-begin
- classification[35] := ElnaLexerClass.double_quote;
- classification[36] := ElnaLexerClass.number_sign;
- classification[37] := ElnaLexerClass.other;
- classification[38] := ElnaLexerClass.single;
- classification[39] := ElnaLexerClass.single;
- classification[40] := ElnaLexerClass.single_quote;
- classification[41] := ElnaLexerClass.left_paren;
- classification[42] := ElnaLexerClass.right_paren;
- classification[43] := ElnaLexerClass.asterisk;
- classification[44] := ElnaLexerClass.single;
- classification[45] := ElnaLexerClass.single;
- classification[46] := ElnaLexerClass.minus;
- classification[47] := ElnaLexerClass.dot;
- classification[48] := ElnaLexerClass.single;
- classification[49] := ElnaLexerClass.zero;
- classification[50] := ElnaLexerClass.digit;
- classification[51] := ElnaLexerClass.digit;
- classification[52] := ElnaLexerClass.digit;
- classification[53] := ElnaLexerClass.digit;
- classification[54] := ElnaLexerClass.digit;
- classification[55] := ElnaLexerClass.digit;
- classification[56] := ElnaLexerClass.digit;
- classification[57] := ElnaLexerClass.digit;
- classification[58] := ElnaLexerClass.digit;
- classification[59] := ElnaLexerClass.colon;
- classification[60] := ElnaLexerClass.single;
- classification[61] := ElnaLexerClass.less;
- classification[62] := ElnaLexerClass.equals;
- classification[63] := ElnaLexerClass.greater;
- classification[64] := ElnaLexerClass.other
-return
-
-proc elna_lexer_classifications3()
-begin
- classification[65] := ElnaLexerClass.single;
- classification[66] := ElnaLexerClass.alpha;
- classification[67] := ElnaLexerClass.alpha;
- classification[68] := ElnaLexerClass.alpha;
- classification[69] := ElnaLexerClass.alpha;
- classification[70] := ElnaLexerClass.alpha;
- classification[71] := ElnaLexerClass.alpha;
- classification[72] := ElnaLexerClass.alpha;
- classification[73] := ElnaLexerClass.alpha;
- classification[74] := ElnaLexerClass.alpha;
- classification[75] := ElnaLexerClass.alpha;
- classification[76] := ElnaLexerClass.alpha;
- classification[77] := ElnaLexerClass.alpha;
- classification[78] := ElnaLexerClass.alpha;
- classification[79] := ElnaLexerClass.alpha;
- classification[80] := ElnaLexerClass.alpha;
- classification[81] := ElnaLexerClass.alpha;
- classification[82] := ElnaLexerClass.alpha;
- classification[83] := ElnaLexerClass.alpha;
- classification[84] := ElnaLexerClass.alpha;
- classification[85] := ElnaLexerClass.alpha;
- classification[86] := ElnaLexerClass.alpha;
- classification[87] := ElnaLexerClass.alpha;
- classification[88] := ElnaLexerClass.alpha;
- classification[89] := ElnaLexerClass.alpha;
- classification[90] := ElnaLexerClass.alpha;
- classification[91] := ElnaLexerClass.alpha;
- classification[92] := ElnaLexerClass.single;
- classification[93] := ElnaLexerClass.backslash;
- classification[94] := ElnaLexerClass.single;
- classification[95] := ElnaLexerClass.single;
- classification[96] := ElnaLexerClass.alpha;
- classification[97] := ElnaLexerClass.other;
- classification[98] := ElnaLexerClass.hex
-return
-
-proc elna_lexer_classifications4()
-begin
- classification[99] := ElnaLexerClass.hex;
- classification[100] := ElnaLexerClass.hex;
- classification[101] := ElnaLexerClass.hex;
- classification[102] := ElnaLexerClass.hex;
- classification[103] := ElnaLexerClass.hex;
- classification[104] := ElnaLexerClass.alpha;
- classification[105] := ElnaLexerClass.alpha;
- classification[106] := ElnaLexerClass.alpha;
- classification[107] := ElnaLexerClass.alpha;
- classification[108] := ElnaLexerClass.alpha;
- classification[109] := ElnaLexerClass.alpha;
- classification[110] := ElnaLexerClass.alpha;
- classification[111] := ElnaLexerClass.alpha;
- classification[112] := ElnaLexerClass.alpha;
- classification[113] := ElnaLexerClass.alpha;
- classification[114] := ElnaLexerClass.alpha;
- classification[115] := ElnaLexerClass.alpha;
- classification[116] := ElnaLexerClass.alpha;
- classification[117] := ElnaLexerClass.alpha;
- classification[118] := ElnaLexerClass.alpha;
- classification[119] := ElnaLexerClass.alpha;
- classification[120] := ElnaLexerClass.alpha;
- classification[121] := ElnaLexerClass.x;
- classification[122] := ElnaLexerClass.alpha;
- classification[123] := ElnaLexerClass.alpha;
- classification[124] := ElnaLexerClass.other;
- classification[125] := ElnaLexerClass.single;
- classification[126] := ElnaLexerClass.other;
- classification[127] := ElnaLexerClass.single
-return
-
-(**
- * Initializes the array with character classes.
- *)
-proc elna_lexer_classifications()
-var
- code: Word
-begin
- code := 1u;
-
- (* Set everything by default to invalid. *)
- while code < 129u do
- classification[code] := ElnaLexerClass.invalid;
- code := code + 1u
- end;
-
- elna_lexer_classifications1();
- elna_lexer_classifications2();
- elna_lexer_classifications3();
- elna_lexer_classifications4();
-
- (* Set the remaining 129 - 256 bytes to transitionClassOther. *)
- while code < 257u do
- classification[code] := ElnaLexerClass.other;
- code := code + 1u
- end
-return
-
-proc elna_lexer_get_transition(current_state: ElnaLexerState; character_class: ElnaLexerClass) -> ^ElnaLexerTransition
- (* Each state is 8 bytes long (2 words: action and next state).
- There are 23 character classes, so a transition row 8 * 23 = 184 bytes long. *)
-return @transition_table[cast(current_state: Word)][cast(character_class: Word)]
-
-(**
- * Parameters:
- * current_state - First index into transitions table.
- * character_class - Second index into transitions table.
- * action - Action to assign.
- * next_state - Next state to assign.
- *)
-proc elna_lexer_set_transition(current_state: ElnaLexerState; character_class: ElnaLexerClass;
- action: ElnaLexerAction; next_state: ElnaLexerState)
-var
- transition: ^ElnaLexerTransition
-begin
- transition := elna_lexer_get_transition(current_state, character_class);
-
- transition^.action := action;
- transition^.next_state := next_state
-return
-
-(**
- * Sets same action and state transition for all character classes in one transition row.
- *
- * Parameters:
- * current_state - Current state (Transition state enumeration).
- * default_action - Default action (Callback).
- * next_state - Next state (Transition state enumeration).
- *)
-proc elna_lexer_default_transition(current_state: ElnaLexerState; default_action: ElnaLexerAction;
- next_state: ElnaLexerState)
-begin
- elna_lexer_set_transition(current_state, ElnaLexerClass.invalid, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.digit, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.alpha, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.space, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.colon, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.equals, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.left_paren, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.right_paren, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.asterisk, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.backslash, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.single, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.hex, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.zero, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.x, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.eof, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.dot, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.minus, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.single_quote, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.double_quote, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.greater, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.less, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.other, default_action, next_state);
- elna_lexer_set_transition(current_state, ElnaLexerClass.number_sign, default_action, next_state)
-return
-
-(**
- * The transition table describes transitions from one state to another, given
- * a symbol (character class).
- *
- * The table has m rows and n columns, where m is the amount of states and n is
- * the amount of classes. So given the current state and a classified character
- * the table can be used to look up the next state.
- *)
-proc elna_lexer_transitions()
-begin
- (* Start state. *)
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.decimal);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.space, ElnaLexerAction.skip, ElnaLexerState.start);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.colon, ElnaLexerAction.accumulate, ElnaLexerState.colon);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.equals, ElnaLexerAction.single, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.left_paren, ElnaLexerAction.accumulate, ElnaLexerState.left_paren);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.right_paren, ElnaLexerAction.single, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.asterisk, ElnaLexerAction.single, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.backslash, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.single, ElnaLexerAction.single, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.leading_zero);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.eof, ElnaLexerAction.eof, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.dot, ElnaLexerAction.single, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.minus, ElnaLexerAction.accumulate, ElnaLexerState.minus);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.single_quote, ElnaLexerAction.accumulate, ElnaLexerState.character);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.double_quote, ElnaLexerAction.accumulate, ElnaLexerState.string);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.greater, ElnaLexerAction.accumulate, ElnaLexerState.greater);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.less, ElnaLexerAction.accumulate, ElnaLexerState.less);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.other, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.number_sign, ElnaLexerAction.accumulate, ElnaLexerState.number_sign);
-
- (* Colon state. *)
- elna_lexer_default_transition(ElnaLexerState.colon, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.colon, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish);
-
- (* Identifier state. *)
- elna_lexer_default_transition(ElnaLexerState.identifier, ElnaLexerAction.key_id, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
- elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.identifier);
-
- (* Decimal state. *)
- elna_lexer_default_transition(ElnaLexerState.decimal, ElnaLexerAction.integer, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.decimal);
- elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.alpha, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.hex, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.decimal);
- elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.x, ElnaLexerAction.none, ElnaLexerState.finish);
-
- (* Leading zero. *)
- elna_lexer_default_transition(ElnaLexerState.leading_zero, ElnaLexerAction.integer, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.digit, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.alpha, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.hex, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.zero, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.x, ElnaLexerAction.none, ElnaLexerState.dot);
-
- (* Greater state. *)
- elna_lexer_default_transition(ElnaLexerState.greater, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.greater, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish);
-
- (* Minus state. *)
- elna_lexer_default_transition(ElnaLexerState.minus, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.minus, ElnaLexerClass.greater, ElnaLexerAction.composite, ElnaLexerState.finish);
-
- (* Left paren state. *)
- elna_lexer_default_transition(ElnaLexerState.left_paren, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.left_paren, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.comment);
-
- (* Less state. *)
- elna_lexer_default_transition(ElnaLexerState.less, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.less, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.less, ElnaLexerClass.greater, ElnaLexerAction.composite, ElnaLexerState.finish);
-
- (* Hexadecimal after 0x. *)
- elna_lexer_default_transition(ElnaLexerState.dot, ElnaLexerAction.finalize, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.dot, ElnaLexerClass.dot, ElnaLexerAction.composite, ElnaLexerState.finish);
-
- (* Comment. *)
- elna_lexer_default_transition(ElnaLexerState.comment, ElnaLexerAction.accumulate, ElnaLexerState.comment);
- elna_lexer_set_transition(ElnaLexerState.comment, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.closing_comment);
- elna_lexer_set_transition(ElnaLexerState.comment, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
-
- (* Closing comment. *)
- elna_lexer_default_transition(ElnaLexerState.closing_comment, ElnaLexerAction.accumulate, ElnaLexerState.comment);
- elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.right_paren, ElnaLexerAction.delimited, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.closing_comment);
- elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
-
- (* Character. *)
- elna_lexer_default_transition(ElnaLexerState.character, ElnaLexerAction.accumulate, ElnaLexerState.character);
- elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.single_quote, ElnaLexerAction.delimited, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.backslash, ElnaLexerAction.accumulate, ElnaLexerState.character_escape);
-
- (* Escape sequence in a character. *)
- elna_lexer_default_transition(ElnaLexerState.character_escape, ElnaLexerAction.accumulate, ElnaLexerState.character);
- elna_lexer_set_transition(ElnaLexerState.character_escape, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.character_escape, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
-
- (* String. *)
- elna_lexer_default_transition(ElnaLexerState.string, ElnaLexerAction.accumulate, ElnaLexerState.string);
- elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.double_quote, ElnaLexerAction.delimited, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.backslash, ElnaLexerAction.accumulate, ElnaLexerState.string_escape);
-
- (* Escape sequence in a string. *)
- elna_lexer_default_transition(ElnaLexerState.string_escape, ElnaLexerAction.accumulate, ElnaLexerState.string);
- elna_lexer_set_transition(ElnaLexerState.string_escape, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.string_escape, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish);
-
- (* Number sign state. *)
- elna_lexer_default_transition(ElnaLexerState.number_sign, ElnaLexerAction.key_id, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.trait);
-
- (* Trait state. *)
- elna_lexer_default_transition(ElnaLexerState.trait, ElnaLexerAction.key_id, ElnaLexerState.finish);
- elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.trait);
- elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.trait)
-return
-
-proc elna_lexer_advance(cursor: ^ElnaLexerCursor)
-begin
- cursor^.finish := cursor^.finish + 1;
- cursor^.position.end_location.column := cursor^.position.end_location.column + 1u
-return
-
-proc elna_lexer_classify_space(start_position: ^Word8; location: ^ElnaLocation)
-begin
- if start_position^ = '\n' then
- location^.line := location^.line + 1u;
- location^.column := 1u
- else
- location^.column := location^.column + 1u
- end
-return
-
-proc elna_lexer_token_create(kind: ElnaLexerKind; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- result: ^ElnaLexerToken
-begin
- result := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
- result^.kind := kind;
- result^.position := position^
-return result
-
-proc elna_lexer_classify_keyword(position_start, position_end: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- result: ^ElnaLexerToken
- result_length: Word
-begin
- result_length := cast(position_end - position_start: Word);
-
- result := elna_lexer_token_create(ElnaLexerKind.identifier, position);
- result^.start := position_start[1 to result_length];
-
- if position_start^ = '#' then
- result^.kind := ElnaLexerKind.trait
- elsif string_compare(position_start, result_length, "const") then
- result^.kind := ElnaLexerKind._const
- elsif string_compare(position_start, result_length, "var") then
- result^.kind := ElnaLexerKind._var
- elsif string_compare(position_start, result_length, "proc") then
- result^.kind := ElnaLexerKind._proc
- elsif string_compare(position_start, result_length, "type") then
- result^.kind := ElnaLexerKind._type
- elsif string_compare(position_start, result_length, "begin") then
- result^.kind := ElnaLexerKind._begin
- elsif string_compare(position_start, result_length, "end") then
- result^.kind := ElnaLexerKind._end
- elsif string_compare(position_start, result_length, "return") then
- result^.kind := ElnaLexerKind._return
- elsif string_compare(position_start, result_length, "defer") then
- result^.kind := ElnaLexerKind._defer
- elsif string_compare(position_start, result_length, "if") then
- result^.kind := ElnaLexerKind._if
- elsif string_compare(position_start, result_length, "extern") then
- result^.kind := ElnaLexerKind._extern
- elsif string_compare(position_start, result_length, "then") then
- result^.kind := ElnaLexerKind._then
- elsif string_compare(position_start, result_length, "else") then
- result^.kind := ElnaLexerKind._else
- elsif string_compare(position_start, result_length, "elsif") then
- result^.kind := ElnaLexerKind._elsif
- elsif string_compare(position_start, result_length, "record") then
- result^.kind := ElnaLexerKind._record
- elsif string_compare(position_start, result_length, "or") then
- result^.kind := ElnaLexerKind._or
- elsif string_compare(position_start, result_length, "xor") then
- result^.kind := ElnaLexerKind._xor
- elsif string_compare(position_start, result_length, "nil") then
- result^.kind := ElnaLexerKind.null
- elsif string_compare(position_start, result_length, "true") then
- result^.kind := ElnaLexerKind.boolean
- elsif string_compare(position_start, result_length, "false") then
- result^.kind := ElnaLexerKind.boolean
- elsif string_compare(position_start, result_length, "cast") then
- result^.kind := ElnaLexerKind._cast
- end
-return result
-
-proc elna_lexer_classify_delimited(start_position, end_position: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- delimiter: Word8
- result: ^ElnaLexerToken
-begin
- delimiter := start_position^;
-
- if delimiter = '(' then
- result := elna_lexer_token_create(ElnaLexerKind.comment, position)
- elsif delimiter = '\'' then
- result := elna_lexer_token_create(ElnaLexerKind.character, position)
- elsif delimiter = '"' then
- result := elna_lexer_token_create(ElnaLexerKind.string, position)
- end;
- result^.start := start_position[1 to cast(end_position - start_position: Word)]
-return result
-
-proc elna_lexer_classify_integer(start_position, end_position: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- result: ^ElnaLexerToken
-begin
- result := elna_lexer_token_create(ElnaLexerKind.integer, position);
- result^.start := start_position[1 to cast(end_position - start_position: Word)]
-return result
-
-proc elna_lexer_classify_finalize(start_position: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- character: Word8
- result: ^ElnaLexerToken
-begin
- character := start_position^;
-
- if character = ':' then
- result := elna_lexer_token_create(ElnaLexerKind.colon, position)
- elsif character = '.' then
- result := elna_lexer_token_create(ElnaLexerKind.dot, position)
- elsif character = '(' then
- result := elna_lexer_token_create(ElnaLexerKind.left_paren, position)
- elsif character = '-' then
- result := elna_lexer_token_create(ElnaLexerKind.minus, position)
- elsif character = '<' then
- result := elna_lexer_token_create(ElnaLexerKind.less_than, position)
- elsif character = '>' then
- result := elna_lexer_token_create(ElnaLexerKind.greater_than, position)
- end
-return result
-
-proc elna_lexer_classify_single(start_position: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- character: Word8
- result: ^ElnaLexerToken
-begin
- result := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
- character := start_position^;
-
- if character = ';' then
- result := elna_lexer_token_create(ElnaLexerKind.semicolon, position)
- elsif character = ',' then
- result := elna_lexer_token_create(ElnaLexerKind.comma, position)
- elsif character = ')' then
- result := elna_lexer_token_create(ElnaLexerKind.right_paren, position)
- elsif character = '@' then
- result := elna_lexer_token_create(ElnaLexerKind.at, position)
- elsif character = '~' then
- result := elna_lexer_token_create(ElnaLexerKind.not, position)
- elsif character = '&' then
- result := elna_lexer_token_create(ElnaLexerKind.and, position)
- elsif character = '+' then
- result := elna_lexer_token_create(ElnaLexerKind.plus, position)
- elsif character = '*' then
- result := elna_lexer_token_create(ElnaLexerKind.multiplication, position)
- elsif character = '=' then
- result := elna_lexer_token_create(ElnaLexerKind.equals, position)
- elsif character = '%' then
- result := elna_lexer_token_create(ElnaLexerKind.remainder, position)
- elsif character = '/' then
- result := elna_lexer_token_create(ElnaLexerKind.division, position)
- elsif character = '.' then
- result := elna_lexer_token_create(ElnaLexerKind.dot, position)
- elsif character = '^' then
- result := elna_lexer_token_create(ElnaLexerKind.hat, position)
- elsif character = '[' then
- result := elna_lexer_token_create(ElnaLexerKind.left_square, position)
- elsif character = ']' then
- result := elna_lexer_token_create(ElnaLexerKind.right_square, position)
- end
-return result
-
-proc elna_lexer_classify_composite(start_position, one_before_last: ^Word8; position: ^ElnaPosition) -> ^ElnaLexerToken
-var
- first_character: Word8
- last_character: Word8
- result: ^ElnaLexerToken
-begin
- first_character := start_position^;
- last_character := one_before_last^;
-
- if first_character = ':' then
- result := elna_lexer_token_create(ElnaLexerKind.assignment, position)
- elsif first_character = '<' then
- if last_character = '=' then
- result := elna_lexer_token_create(ElnaLexerKind.less_equal, position)
- elsif last_character = '>' then
- result := elna_lexer_token_create(ElnaLexerKind.not_equal, position)
- end
- elsif first_character = '>' then
- if last_character = '=' then
- result := elna_lexer_token_create(ElnaLexerKind.greater_equal, position)
- end
- elsif first_character = '-' then
- if last_character = '>' then
- result := elna_lexer_token_create(ElnaLexerKind.arrow, position)
- end
- end
-return result
-
-proc elna_lexer_execute_action(cursor: ^ElnaLexerCursor; action_to_perform: ElnaLexerAction) -> ^ElnaLexerToken
-var
- token: ^ElnaLexerToken
-begin
- token := nil;
-
- if action_to_perform = ElnaLexerAction.none then
- elsif action_to_perform = ElnaLexerAction.accumulate then
- elna_lexer_advance(cursor)
- elsif action_to_perform = ElnaLexerAction.skip then
- elna_lexer_classify_space(cursor^.start, @cursor^.position.end_location);
- cursor^.start := cursor^.start + 1;
- cursor^.finish := cursor^.finish + 1
- elsif action_to_perform = ElnaLexerAction.single then
- elna_lexer_advance(cursor);
-
- token := elna_lexer_classify_single(cursor^.start, @cursor^.position)
- elsif action_to_perform = ElnaLexerAction.eof then
- token := malloc#[ElnaLexerToken](#size(ElnaLexerToken));
- token^.kind := ElnaLexerKind.eof
- elsif action_to_perform = ElnaLexerAction.finalize then
- token := elna_lexer_classify_finalize(cursor^.start, @cursor^.position)
- elsif action_to_perform = ElnaLexerAction.composite then
- token := elna_lexer_classify_composite(cursor^.start, cursor^.finish, @cursor^.position);
-
- elna_lexer_advance(cursor)
- elsif action_to_perform = ElnaLexerAction.key_id then
- token := elna_lexer_classify_keyword(cursor^.start, cursor^.finish, @cursor^.position)
- elsif action_to_perform = ElnaLexerAction.integer then
- token := elna_lexer_classify_integer(cursor^.start, cursor^.finish, @cursor^.position)
- elsif action_to_perform = ElnaLexerAction.delimited then
- elna_lexer_advance(cursor);
-
- token := elna_lexer_classify_delimited(cursor^.start, cursor^.finish, @cursor^.position)
- end
-return token
-
-proc elna_lexer_execute_transition(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken
-var
- next_transition: ^ElnaLexerTransition
- current_character: Word8
-begin
- current_character := cursor^.finish^;
- next_transition := elna_lexer_get_transition(cursor^.state,
- classification[cast(current_character: Word) + 1u]);
- cursor^.state := next_transition^.next_state
-return elna_lexer_execute_action(cursor, next_transition^.action)
-
-(**
- * One time lexer initialization.
- *)
-proc elna_lexer_initialize*(cursor: ^ElnaLexerCursor; code_pointer: ^Word8)
-begin
- elna_lexer_classifications();
- elna_lexer_transitions();
-
- cursor^.start := code_pointer;
- cursor^.finish := code_pointer;
- cursor^.token := nil;
- cursor^.position.start_location := { ElnaLocation; line: 1u, column: 1u };
- cursor^.position.end_location := { ElnaLocation; line: 1u, column: 1u }
-return
-
-(**
- * Reads the next token and writes its type into the address in the kind parameter.
- * Resets the lexer state for reading the next token.
- *)
-proc elna_lexer_peek*(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken
-var
- token: ^ElnaLexerToken
-begin
- if cursor^.token = nil then
- cursor^.state := ElnaLexerState.start;
-
- while cursor^.state <> ElnaLexerState.finish do
- token := elna_lexer_execute_transition(cursor)
- end;
- cursor^.token := token
- end
-return cursor^.token
-
-(**
- * Reads the token and advance the lexer.
- *)
-proc elna_lexer_read*(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken
-var
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_peek(cursor);
- cursor^.token := nil;
- cursor^.start := cursor^.finish;
- cursor^.position.start_location := cursor^.position.end_location
-return token
-
-(**
- * Skips comments.
- *)
-proc elna_lexer_skip_empty_lines*(cursor: ^ElnaLexerCursor)
-var
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_peek(cursor);
-
- while token^.kind = ElnaLexerKind.comment do
- elna_lexer_read(cursor);
- token := elna_lexer_peek(cursor)
- end
-return
-
-end.
diff --git a/source/main.elna b/source/main.elna
index 3b78651..b45b283 100644
--- a/source/main.elna
+++ b/source/main.elna
@@ -1,142 +1,6 @@
(* 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()
-program(parameters)
-import
- sys.posix.cstdio, sys.posix.cstdlib, sys.posix.cstring, common, command_line_interface,
- lexer, ast, diagnostic, symbol, parser, name_analysis, type_check, tac, qbe
-
-proc read_file_to_buffer(filename: ^Word8) -> []const Word8
-var
- file_handle: ^FILE
- file_size: Int
- buffer: ^Word8
- bytes_read: Word
- result: []const Word8
-begin
- file_handle := fopen(filename, "rb\0".ptr);
- if file_handle = nil then
- perror(filename);
- exit(3)
- end;
- fseek(file_handle, 0, 2);
- file_size := ftell(file_handle);
- rewind(file_handle);
-
- buffer := malloc#[Word8](cast(file_size: Word) + 1u);
- bytes_read := fread#[Word8](buffer, 1u, cast(file_size: Word), file_handle);
- (buffer + bytes_read)^ := cast(0: Word8);
- fclose(file_handle);
-
- result := buffer[1u to bytes_read]
-return result
-
-proc print_errors(error_list: ^ElnaList)
-var
- node: ^ElnaListNode
-begin
- node := error_list^.first;
- while node <> nil do
- elna_error_print(cast(node: ^ElnaError));
- node := node^.next
- end
-return
-
-proc compile_file(command_line: ^CommandLine) -> Int
-var
- source_text: []const Word8
- lexer_cursor: ElnaLexerCursor
- error_list: ElnaList
- parser_node: ^ElnaTreeModuleDeclaration
- tac_module: ^ElnaInstructionModule
- out_file: ^FILE := stdout
- token: ^ElnaLexerToken
- return_code: Int := 0
-begin
- source_text := read_file_to_buffer(command_line^.input);
-
- if command_line^.lex then
- elna_lexer_initialize(@lexer_cursor, cast(source_text.ptr: ^Word8));
- token := elna_lexer_read(@lexer_cursor);
- while token^.kind <> ElnaLexerKind.eof do
- token := elna_lexer_read(@lexer_cursor)
- end
- else
- elna_list_initialize(@error_list);
- elna_symbol_table_build();
-
- elna_lexer_initialize(@lexer_cursor, cast(source_text.ptr: ^Word8));
- parser_node := elna_parser_module_declaration(@lexer_cursor, @error_list);
-
- if ~elna_list_empty(@error_list) then
- print_errors(@error_list);
- return_code := 1
- elsif ~command_line^.parse then
- elna_declaration_module_declaration(parser_node, @error_list);
- if ~elna_list_empty(@error_list) then
- print_errors(@error_list);
- return_code := 1
- else
- elna_name_module_declaration(parser_node, @error_list);
- if ~elna_list_empty(@error_list) then
- print_errors(@error_list);
- return_code := 1
- else
- elna_type_module_declaration(parser_node, @error_list);
- if ~elna_list_empty(@error_list) then
- print_errors(@error_list);
- return_code := 1
- else
- tac_module := elna_tac_module_declaration(parser_node);
-
- if command_line^.output <> nil then
- out_file := fopen(command_line^.output, "wb\0".ptr);
- if out_file = nil then
- perror(command_line^.output);
- return_code := 3
- end
- end;
-
- if return_code = 0 then
- elna_qbe_emit(tac_module, out_file);
-
- if command_line^.output <> nil & out_file <> stdout then
- fclose(out_file)
- end
- end
- end
- end
- end
- end
- end
-return return_code
-
-proc initialize_global_state()
-begin
- stdin := fdopen(0, "r\0".ptr);
- stdout := fdopen(1, "w\0".ptr);
- stderr := fdopen(2, "w\0".ptr)
-return
-
-proc process(argc: Int; argv: ^^Word8) -> Int
-var
- command_line: ^CommandLine
- return_code: Int := 0
-begin
- command_line := parse_command_line(argc, argv);
- if command_line = nil then
- return_code := 2
- elsif command_line^.input = nil then
- write_s("Fatal error: no input file provided.\n");
- return_code := 2
- else
- return_code := compile_file(command_line)
- end
-return return_code
-
-begin
- initialize_global_state();
-
- exit(process(cast(parameters.length: Int), parameters.ptr))
end.
diff --git a/source/name_analysis.elna b/source/name_analysis.elna
deleted file mode 100644
index cbb27c0..0000000
--- a/source/name_analysis.elna
+++ /dev/null
@@ -1,539 +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/. *)
-module
-import common, sys.posix.cstdlib, lexer, ast, symbol, diagnostic
-
-proc elna_name_type_expression*(parser_node: ^ElnaTreeTypeExpression; error_list: ^ElnaList) -> ^ElnaType
-var
- result: ^ElnaType := nil
-begin
- if parser_node <> nil then
- case parser_node^.kind of
- ElnaTreeKind.named_type_expression:
- result := elna_name_named_type_expression(cast(parser_node: ^ElnaTreeNamedTypeExpression), error_list)
- | ElnaTreeKind.enumeration_type_expression:
- result := malloc#[ElnaType](#size(ElnaTypeEnumeration));
- result^.kind := ElnaTypeKind.enumeration;
- elna_name_enumeration_type_expression(cast(parser_node: ^ElnaTreeEnumerationTypeExpression), error_list, cast(result: ^ElnaTypeEnumeration))
- | ElnaTreeKind.record_type_expression:
- result := malloc#[ElnaType](#size(ElnaTypeRecord));
- result^.kind := ElnaTypeKind._record;
- elna_name_record_type_expression(cast(parser_node: ^ElnaTreeRecordTypeExpression), error_list, cast(result: ^ElnaTypeRecord))
- | ElnaTreeKind.pointer_type_expression:
- result := malloc#[ElnaType](#size(ElnaTypePointer));
- result^.kind := ElnaTypeKind.pointer;
- elna_name_pointer_type_expression(cast(parser_node: ^ElnaTreePointerTypeExpression), error_list, cast(result: ^ElnaTypePointer))
- | ElnaTreeKind.array_type_expression:
- result := malloc#[ElnaType](#size(ElnaTypeArray));
- result^.kind := ElnaTypeKind.array;
- elna_name_array_type_expression(cast(parser_node: ^ElnaTreeArrayTypeExpression), error_list, cast(result: ^ElnaTypeArray))
- else
- end
- end
-return result
-
-proc elna_name_named_type_expression*(parser_node: ^ElnaTreeNamedTypeExpression; error_list: ^ElnaList) -> ^ElnaType
-var
- symbol_info: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- undefined_symbol: ^ElnaErrorUndefinedSymbol
- result: ^ElnaType := nil
-begin
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
- if symbol_info <> nil then
- type_info := cast(symbol_info: ^ElnaSymbolTypeInfo);
- result := type_info^._type
- else
- undefined_symbol := elna_error_undefined_symbol_create(parser_node^.position, parser_node^.name);
- elna_list_append(error_list, cast(undefined_symbol: ^ElnaListNode))
- end
-return result
-
-proc elna_name_alias_type_expression*(parser_node: ^ElnaTreeNamedTypeExpression;
- error_list: ^ElnaList; result: ^ElnaTypeAlias)
-var
- base: ^ElnaType
-begin
- base := elna_name_named_type_expression(parser_node, error_list);
- if base <> nil then
- result^.size := base^.size;
- result^.alignment := base^.alignment;
- result^.base := base
- end
-return
-
-proc elna_name_enumeration_type_expression*(parser_node: ^ElnaTreeEnumerationTypeExpression;
- error_list: ^ElnaList; result: ^ElnaTypeEnumeration)
-var
- tree_member: ^ElnaTreeEnumeration
- i: Word := 0u
-begin
- result^.size := 8u;
- result^.alignment := 8u;
- result^.length := parser_node^.length;
- result^.members := malloc#[[]const Word8](parser_node^.length * #size([]const Word8));
-
- tree_member := parser_node^.members;
- while i < parser_node^.length & tree_member <> nil do
- (result^.members + i)^ := tree_member^.name;
- tree_member := tree_member^.next;
- i := i + 1u
- end
-return
-
-proc elna_name_pointer_type_expression*(parser_node: ^ElnaTreePointerTypeExpression;
- error_list: ^ElnaList; result: ^ElnaTypePointer)
-begin
- result^.size := 8u;
- result^.alignment := 8u;
- result^.base := elna_name_type_expression(parser_node^.base, error_list)
-return
-
-proc elna_name_array_type_expression*(parser_node: ^ElnaTreeArrayTypeExpression;
- error_list: ^ElnaList; result: ^ElnaTypeArray)
-var
- base: ^ElnaType
- len_lit: ^ElnaTreeIntegerLiteral
-begin
- base := elna_name_type_expression(parser_node^.base, error_list);
- len_lit := cast(parser_node^.length: ^ElnaTreeIntegerLiteral);
- if base <> nil & len_lit <> nil then
- result^.size := base^.size * len_lit^.value;
- result^.alignment := base^.alignment;
- result^.base := base;
- result^.length := len_lit^.value
- end
-return
-
-proc elna_name_record_type_expression*(parser_node: ^ElnaTreeRecordTypeExpression;
- error_list: ^ElnaList; result: ^ElnaTypeRecord)
-var
- tree_field: ^ElnaTreeField
- member_array_current: ^ElnaTypeField
- field_type: ^ElnaType
-begin
- result^.size := 0u;
- result^.alignment := 0u;
- result^.length := 0u;
- result^.members := malloc#[ElnaTypeField](parser_node^.length * #size(ElnaTypeField));
-
- tree_field := parser_node^.members;
- member_array_current := result^.members;
-
- while result^.length < parser_node^.length & tree_field <> nil do
- member_array_current^.name := tree_field^.name;
- field_type := elna_name_type_expression(tree_field^.type_expression, error_list);
- if field_type <> nil then
- result^.size := result^.size + field_type^.size;
- if field_type^.alignment > result^.alignment then
- result^.alignment := field_type^.alignment
- end;
- member_array_current^.field_type := field_type;
- member_array_current := member_array_current + 1u;
- tree_field := tree_field^.next;
- result^.length := result^.length + 1u
- else
- tree_field := nil
- end
- end
-return
-
-proc elna_name_procedure_temporary*(parser_node: ^ElnaTreeVariableDeclaration; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- info: ^ElnaSymbolTemporaryInfo
- variable_type: ^ElnaType
- declaration_error: ^ElnaErrorDuplicateDeclaration
-begin
- info := cast(elna_symbol_table_lookup(symbol_table, parser_node^.name): ^ElnaSymbolTemporaryInfo);
- if info = nil then
- variable_type := elna_name_type_expression(parser_node^.type_expression, error_list);
- info := elna_symbol_temporary_info_create(0u, variable_type);
- elna_symbol_table_enter(symbol_table, parser_node^.name, cast(info: ^ElnaSymbolInfo))
- else
- declaration_error := elna_error_duplicate_declaration_create(parser_node^.position, parser_node^.name);
- elna_list_append(error_list, cast(declaration_error: ^ElnaListNode))
- end
-return
-
-proc elna_name_procedure_temporaries*(parser_node: ^ElnaTreeVariableDeclaration; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- current: ^ElnaTreeVariableDeclaration
-begin
- current := parser_node;
- while current <> nil do
- elna_name_procedure_temporary(current, symbol_table, error_list);
- current := cast(current^.next: ^ElnaTreeVariableDeclaration)
- end
-return
-
-proc elna_name_type_declaration*(parser_node: ^ElnaTreeTypeDeclaration; error_list: ^ElnaList)
-var
- type_info: ^ElnaSymbolTypeInfo
- type_stub: ^ElnaType
- type_expression: ^ElnaTreeTypeExpression
-begin
- type_info := cast(elna_symbol_table_lookup(symbol_table_global, parser_node^.name): ^ElnaSymbolTypeInfo);
- if type_info <> nil then
- type_stub := type_info^._type;
- type_expression := parser_node^.type_expression;
-
- if type_stub^.kind = ElnaTypeKind.alias then
- elna_name_alias_type_expression(cast(type_expression: ^ElnaTreeNamedTypeExpression), error_list, cast(type_stub: ^ElnaTypeAlias))
- elsif type_stub^.kind = ElnaTypeKind.enumeration then
- elna_name_enumeration_type_expression(cast(type_expression: ^ElnaTreeEnumerationTypeExpression), error_list, cast(type_stub: ^ElnaTypeEnumeration))
- elsif type_stub^.kind = ElnaTypeKind._record then
- elna_name_record_type_expression(cast(type_expression: ^ElnaTreeRecordTypeExpression), error_list, cast(type_stub: ^ElnaTypeRecord))
- elsif type_stub^.kind = ElnaTypeKind.pointer then
- elna_name_pointer_type_expression(cast(type_expression: ^ElnaTreePointerTypeExpression), error_list, cast(type_stub: ^ElnaTypePointer))
- elsif type_stub^.kind = ElnaTypeKind.array then
- elna_name_array_type_expression(cast(type_expression: ^ElnaTreeArrayTypeExpression), error_list, cast(type_stub: ^ElnaTypeArray))
- end
- end
-return
-
-proc elna_name_variable_expression*(parser_node: ^ElnaTreeVariableExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- symbol_info: ^ElnaSymbolInfo
- undefined_symbol: ^ElnaErrorUndefinedSymbol
-begin
- symbol_info := elna_symbol_table_lookup(symbol_table, parser_node^.name);
- if symbol_info = nil then
- undefined_symbol := elna_error_undefined_symbol_create(parser_node^.position, parser_node^.name);
- elna_list_append(error_list, cast(undefined_symbol: ^ElnaListNode))
- end
-return
-
-proc elna_name_cast_expression*(parser_node: ^ElnaTreeCastExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_binary_expression(parser_node^.expression, symbol_table, error_list);
- parser_node^.type_decoration := elna_name_type_expression(parser_node^.type_expression, error_list)
-return
-
-proc elna_name_simple_expression*(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- if parser_node^.kind = ElnaTreeKind._cast then
- elna_name_cast_expression(cast(parser_node: ^ElnaTreeCastExpression), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.variable_expression then
- elna_name_variable_expression(cast(parser_node: ^ElnaTreeVariableExpression), symbol_table, error_list)
- end
-return
-
-proc elna_name_call*(parser_node: ^ElnaTreeCall; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-var
- argument_tree: ^ElnaTreeExpressionList
-begin
- elna_name_variable_expression(parser_node^.callee, symbol_table, error_list);
- argument_tree := parser_node^.arguments;
- while argument_tree <> nil do
- elna_name_binary_expression(argument_tree^.expression, symbol_table, error_list);
- argument_tree := argument_tree^.next
- end
-return
-
-proc elna_name_dereference_expression*(parser_node: ^ElnaTreeDereferenceExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_designator(parser_node^.pointer, symbol_table, error_list)
-return
-
-proc elna_name_field_access_expression*(parser_node: ^ElnaTreeFieldAccessExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- variable_expression: ^ElnaTreeVariableExpression
- identifier_symbol: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- undefined_member_error: ^ElnaErrorUndefinedMember
- enumeration_type: ^ElnaTypeEnumeration
- member_count: Word
- current_member: ^[]const Word8
- found: Bool := false
-begin
- if parser_node^.aggregate^.kind = ElnaTreeKind.variable_expression then
- variable_expression := cast(parser_node^.aggregate: ^ElnaTreeVariableExpression);
- identifier_symbol := elna_symbol_table_lookup(symbol_table, variable_expression^.name);
-
- if identifier_symbol <> nil & identifier_symbol^.kind = ElnaSymbolInfoKind.type_info then
- type_info := cast(identifier_symbol: ^ElnaSymbolTypeInfo);
- if type_info^._type^.kind = ElnaTypeKind.enumeration then
- enumeration_type := cast(type_info^._type: ^ElnaTypeEnumeration);
- current_member := enumeration_type^.members;
- member_count := enumeration_type^.length;
-
- while member_count > 0u & ~found do
- if current_member^ = parser_node^.field then
- found := true
- end;
- member_count := member_count - 1u;
- current_member := current_member + 1u
- end
- end;
- if ~found then
- undefined_member_error := elna_error_undefined_member_create(variable_expression^.position,
- variable_expression^.name, parser_node^.field);
- elna_list_append(error_list, cast(undefined_member_error: ^ElnaListNode))
- end
- else
- elna_name_designator(cast(variable_expression: ^ElnaTreeExpression), symbol_table, error_list)
- end
- else
- elna_name_designator(parser_node^.aggregate, symbol_table, error_list)
- end
-return
-
-proc elna_name_array_access_expression*(parser_node: ^ElnaTreeArrayAccessExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_designator(parser_node^.array, symbol_table, error_list);
- elna_name_binary_expression(parser_node^.index, symbol_table, error_list)
-return
-
-proc elna_name_designator*(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-begin
- if parser_node^.kind = ElnaTreeKind.dereference_expression then
- elna_name_dereference_expression(cast(parser_node: ^ElnaTreeDereferenceExpression), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.field_access_expression then
- elna_name_field_access_expression(cast(parser_node: ^ElnaTreeFieldAccessExpression), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.array_access_expression then
- elna_name_array_access_expression(cast(parser_node: ^ElnaTreeArrayAccessExpression), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.call then
- elna_name_call(cast(parser_node: ^ElnaTreeCall), symbol_table, error_list)
- else
- elna_name_simple_expression(parser_node, symbol_table, error_list)
- end
-return
-
-proc elna_name_unary_expression*(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- unary_node: ^ElnaTreeUnaryExpression
-begin
- if parser_node^.kind = ElnaTreeKind.unary_expression then
- unary_node := cast(parser_node: ^ElnaTreeUnaryExpression);
- elna_name_designator(unary_node^.operand, symbol_table, error_list)
- else
- elna_name_designator(parser_node, symbol_table, error_list)
- end
-return
-
-proc elna_name_binary_expression*(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- bin_node: ^ElnaTreeBinaryExpression
-begin
- if parser_node^.kind = ElnaTreeKind.binary_expression then
- bin_node := cast(parser_node: ^ElnaTreeBinaryExpression);
- elna_name_unary_expression(bin_node^.lhs, symbol_table, error_list);
- elna_name_unary_expression(bin_node^.rhs, symbol_table, error_list)
- else
- elna_name_unary_expression(parser_node, symbol_table, error_list)
- end
-return
-
-proc elna_name_conditional_statements*(parser_node: ^ElnaTreeConditionalStatements; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- current: ^ElnaTreeConditionalStatements
-begin
- current := parser_node;
- while current <> nil do
- elna_name_binary_expression(current^.condition, symbol_table, error_list);
- elna_name_statements(current^.statements, symbol_table, error_list);
- current := current^.next
- end
-return
-
-proc elna_name_if_statement*(parser_node: ^ElnaTreeIfStatement; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_conditional_statements(parser_node^.conditionals, symbol_table, error_list);
- if parser_node^._else <> nil then
- elna_name_statements(parser_node^._else, symbol_table, error_list)
- end
-return
-
-proc elna_name_return_statement*(parser_node: ^ElnaTreeReturnStatement; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_binary_expression(parser_node^.returned, symbol_table, error_list)
-return
-
-proc elna_name_assign_statement*(parser_node: ^ElnaTreeAssignStatement; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_name_designator(parser_node^.assignee, symbol_table, error_list);
- elna_name_binary_expression(parser_node^.assignment, symbol_table, error_list)
-return
-
-proc elna_name_statement*(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-var
- call_statement: ^ElnaTreeCallStatement
-begin
- if parser_node^.kind = ElnaTreeKind.if_statement then
- elna_name_if_statement(cast(parser_node: ^ElnaTreeIfStatement), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.return_statement then
- elna_name_return_statement(cast(parser_node: ^ElnaTreeReturnStatement), symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.call_statement then
- call_statement := cast(parser_node: ^ElnaTreeCallStatement);
- elna_name_call(call_statement^.call, symbol_table, error_list)
- elsif parser_node^.kind = ElnaTreeKind.assign_statement then
- elna_name_assign_statement(cast(parser_node: ^ElnaTreeAssignStatement), symbol_table, error_list)
- end
-return
-
-proc elna_name_statements*(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- current: ^ElnaTreeStatement
-begin
- current := parser_node;
- while current <> nil do
- elna_name_statement(current, symbol_table, error_list);
- current := current^.next
- end
-return
-
-proc elna_name_procedure_declaration*(parser_node: ^ElnaTreeProcedureDeclaration; error_list: ^ElnaList)
-var
- new_symbol_table: ^ElnaSymbolTable
- symbol_info: ^ElnaSymbolProcedureInfo
- proc_type: ^ElnaTypeProcedure
-begin
- symbol_info := cast(elna_symbol_table_lookup(symbol_table_global, parser_node^.name): ^ElnaSymbolProcedureInfo);
-
- proc_type := malloc#[ElnaTypeProcedure](#size(ElnaTypeProcedure));
- proc_type^.kind := ElnaTypeKind.procedure;
- proc_type^.size := 8u;
- proc_type^.alignment := 8u;
- if parser_node^.return_type = nil then
- proc_type^.return_type := nil
- else
- proc_type^.return_type := elna_name_type_expression(parser_node^.return_type, error_list)
- end;
- symbol_info^.procedure_type := proc_type;
-
- if ~symbol_info^.is_extern then
- new_symbol_table := elna_symbol_table_create(symbol_table_global);
- symbol_info^.symbol_table := new_symbol_table;
-
- elna_name_procedure_temporaries(parser_node^.parameters, new_symbol_table, error_list);
- elna_name_procedure_temporaries(parser_node^.temporaries, new_symbol_table, error_list);
- elna_name_statements(parser_node^.body, new_symbol_table, error_list)
- end
-return
-
-proc elna_name_program_body*(parser_node: ^ElnaTreeStatement)
-var
- symbol_info: ^ElnaSymbolProcedureInfo
-begin
- symbol_info := elna_symbol_procedure_info_create(false);
- symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
- elna_symbol_table_enter(symbol_table_global, "main", cast(symbol_info: ^ElnaSymbolInfo))
-return
-
-proc elna_declaration_type_declaration*(parser_node: ^ElnaTreeTypeDeclaration; error_list: ^ElnaList)
-var
- type_info: ^ElnaSymbolTypeInfo
- result: ^ElnaType := nil
- type_expression: ^ElnaTreeTypeExpression
- declaration_error: ^ElnaErrorDuplicateDeclaration
-begin
- type_info := cast(elna_symbol_table_lookup(symbol_table_global, parser_node^.name): ^ElnaSymbolTypeInfo);
-
- if type_info = nil then
- type_expression := parser_node^.type_expression;
-
- if type_expression^.kind = ElnaTreeKind.named_type_expression then
- result := malloc#[ElnaType](#size(ElnaTypeAlias));
- result^.kind := ElnaTypeKind.alias
- elsif type_expression^.kind = ElnaTreeKind.enumeration_type_expression then
- result := malloc#[ElnaType](#size(ElnaTypeEnumeration));
- result^.kind := ElnaTypeKind.enumeration
- elsif type_expression^.kind = ElnaTreeKind.record_type_expression then
- result := malloc#[ElnaType](#size(ElnaTypeRecord));
- result^.kind := ElnaTypeKind._record
- elsif type_expression^.kind = ElnaTreeKind.pointer_type_expression then
- result := malloc#[ElnaType](#size(ElnaTypePointer));
- result^.kind := ElnaTypeKind.pointer
- elsif type_expression^.kind = ElnaTreeKind.array_type_expression then
- result := malloc#[ElnaType](#size(ElnaTypeArray));
- result^.kind := ElnaTypeKind.array
- end;
- type_info := elna_symbol_type_info_create(result);
- elna_symbol_table_enter(symbol_table_global, parser_node^.name, cast(type_info: ^ElnaSymbolInfo))
- else
- declaration_error := elna_error_duplicate_declaration_create(parser_node^.position, parser_node^.name);
- elna_list_append(error_list, cast(declaration_error: ^ElnaListNode))
- end
-return
-
-proc elna_declaration_procedure_declaration*(parser_node: ^ElnaTreeProcedureDeclaration; error_list: ^ElnaList)
-var
- symbol_info: ^ElnaSymbolProcedureInfo
- declaration_error: ^ElnaErrorDuplicateDeclaration
-begin
- symbol_info := cast(elna_symbol_table_lookup(symbol_table_global, parser_node^.name): ^ElnaSymbolProcedureInfo);
-
- if symbol_info = nil then
- symbol_info := elna_symbol_procedure_info_create(parser_node^.is_extern);
- symbol_info^.symbol_table := elna_symbol_table_create(symbol_table_global);
- elna_symbol_table_enter(symbol_table_global, parser_node^.name, cast(symbol_info: ^ElnaSymbolInfo))
- else
- declaration_error := elna_error_duplicate_declaration_create(parser_node^.position, parser_node^.name);
- elna_list_append(error_list, cast(declaration_error: ^ElnaListNode))
- end
-return
-
-proc elna_declaration_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration; error_list: ^ElnaList)
-var
- current_type: ^ElnaTreeDeclaration
- current_proc: ^ElnaTreeDeclaration
-begin
- current_type := parser_node^.types;
- while current_type <> nil do
- elna_declaration_type_declaration(cast(current_type: ^ElnaTreeTypeDeclaration), error_list);
- current_type := current_type^.next
- end;
-
- current_proc := cast(parser_node^.procedures: ^ElnaTreeDeclaration);
- while current_proc <> nil do
- elna_declaration_procedure_declaration(cast(current_proc: ^ElnaTreeProcedureDeclaration), error_list);
- current_proc := current_proc^.next
- end
-return
-
-proc elna_name_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration; error_list: ^ElnaList)
-var
- current_type: ^ElnaTreeDeclaration
- current_global: ^ElnaTreeVariableDeclaration
- current_proc: ^ElnaTreeProcedureDeclaration
-begin
- current_type := parser_node^.types;
- while current_type <> nil do
- elna_name_type_declaration(cast(current_type: ^ElnaTreeTypeDeclaration), error_list);
- current_type := current_type^.next
- end;
-
- current_global := parser_node^.globals;
- while current_global <> nil do
- elna_name_procedure_temporary(current_global, symbol_table_global, error_list);
- current_global := cast(current_global^.next: ^ElnaTreeVariableDeclaration)
- end;
-
- current_proc := parser_node^.procedures;
- while current_proc <> nil do
- elna_name_procedure_declaration(current_proc, error_list);
- current_proc := cast(current_proc^.next: ^ElnaTreeProcedureDeclaration)
- end;
-
- if parser_node^.body <> nil then
- elna_name_program_body(parser_node^.body)
- end
-return
-
-end.
diff --git a/source/parser.elna b/source/parser.elna
deleted file mode 100644
index 3912b65..0000000
--- a/source/parser.elna
+++ /dev/null
@@ -1,1162 +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/. *)
-module
-import common, sys.posix.cstdlib, lexer, ast, diagnostic
-
-proc elna_parser_expect*(cursor: ^ElnaLexerCursor; expected: ElnaLexerKind; error_list: ^ElnaList) -> ^ElnaLexerToken
-var
- token: ^ElnaLexerToken
- parser_error: ^ElnaErrorUnexpectedToken
-begin
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
-
- if token^.kind = expected then
- token := elna_lexer_read(cursor)
- else
- token := nil;
- parser_error := elna_error_unexpected_token_create(cursor, 1u);
- parser_error^.expected[1] := expected;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode))
- end
-return token
-
-proc elna_parser_escape*(current_position: ^const Word8; result: ^Word8) -> Word
-var
- parsed_length: Word
- next_character: Word8
- pos: ^const Word8
-begin
- pos := current_position;
- next_character := pos^;
-
- if next_character = '\\' then
- parsed_length := 2u;
- pos := pos + 1u;
- next_character := pos^;
-
- if next_character = '\\' then
- result^ := 92u8
- elsif next_character = 'n' then
- result^ := 10u8
- elsif next_character = 't' then
- result^ := 9u8
- elsif next_character = 'f' then
- result^ := 12u8
- elsif next_character = 'r' then
- result^ := 13u8
- elsif next_character = 'v' then
- result^ := 11u8
- elsif next_character = '"' then
- result^ := 34u8
- elsif next_character = '\'' then
- result^ := 39u8
- elsif next_character = '0' then
- result^ := 0u8
- else
- result^ := next_character
- end
- else
- parsed_length := 1u;
- result^ := next_character
- end
-return parsed_length
-
-proc elna_parser_integer_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeIntegerLiteral
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeIntegerLiteral
- i: Word := 1u
- val: Word := 0u
-begin
- result := malloc#[ElnaTreeIntegerLiteral](#size(ElnaTreeIntegerLiteral));
- token := elna_lexer_read(cursor);
- result^.kind := ElnaTreeKind.integer_literal;
- result^.type_decoration := nil;
- result^.position := token^.position;
-
- while i <= token^.start.length do
- val := val * 10u + cast(token^.start[i] - '0': Word);
- i := i + 1u
- end;
- result^.value := val
-return result
-
-proc elna_parser_boolean_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeBooleanLiteral
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeBooleanLiteral
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeBooleanLiteral](#size(ElnaTreeBooleanLiteral));
- result^.kind := ElnaTreeKind.boolean_literal;
- result^.value := token^.start = "true";
- result^.type_decoration := nil;
- result^.position := token^.position
-return result
-
-proc elna_parser_nil_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNilLiteral
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeNilLiteral
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeNilLiteral](#size(ElnaTreeNilLiteral));
- result^.kind := ElnaTreeKind.null;
- result^.type_decoration := nil;
- result^.position := token^.position
-return result
-
-proc elna_parser_character_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeCharacterLiteral
-var
- result: ^ElnaTreeCharacterLiteral
- token: ^ElnaLexerToken
-begin
- result := malloc#[ElnaTreeCharacterLiteral](#size(ElnaTreeCharacterLiteral));
- token := elna_lexer_read(cursor);
- result^.kind := ElnaTreeKind.character_literal;
- result^.position := token^.position;
- result^.type_decoration := nil;
- elna_parser_escape(token^.start.ptr + 1u, @result^.value)
-return result
-
-proc elna_parser_variable_expression*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeVariableExpression
-var
- result: ^ElnaTreeVariableExpression
- token: ^ElnaLexerToken
-begin
- result := malloc#[ElnaTreeVariableExpression](#size(ElnaTreeVariableExpression));
- token := elna_lexer_read(cursor);
- result^.kind := ElnaTreeKind.variable_expression;
- result^.name := token^.start;
- result^.position := token^.position;
- result^.type_decoration := nil
-return result
-
-proc elna_parser_string_literal*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStringLiteral
-var
- result: ^ElnaTreeStringLiteral
- token: ^ElnaLexerToken
- current_position: ^const Word8
- parsed_length: Word
- parsed_total: Word
- target_start, target_position: ^Word8
-begin
- result := malloc#[ElnaTreeStringLiteral](#size(ElnaTreeStringLiteral));
- token := elna_lexer_read(cursor);
- target_start := malloc#[Word8](token^.start.length);
- target_position := target_start;
- current_position := token^.start.ptr + 1u;
- parsed_total := 2u;
-
- result^.kind := ElnaTreeKind.string_literal;
- result^.position := token^.position;
- result^.type_decoration := nil;
-
- while parsed_total < token^.start.length do
- parsed_length := elna_parser_escape(current_position, target_position);
- current_position := current_position + parsed_length;
- parsed_total := parsed_total + parsed_length;
- target_position := target_position + 1u
- end;
- result^.value := target_start[1 to cast(target_position - target_start: Word)]
-return result
-
-proc elna_parser_trait_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTraitExpression
-var
- result: ^ElnaTreeTraitExpression
- token: ^ElnaLexerToken
-begin
- result := malloc#[ElnaTreeTraitExpression](#size(ElnaTreeTraitExpression));
- result^.kind := ElnaTreeKind.trait_expression;
- token := elna_lexer_read(cursor);
- result^.name := token^.start;
- result^.position := token^.position;
-
- if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) <> nil then
- result^.argument := elna_parser_type_expression(cursor, error_list);
- if result^.argument = nil then
- result := free_and_nil(result)
- elsif elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then
- result := free_and_nil(result)
- end
- else
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_cast_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeCastExpression
-var
- result: ^ElnaTreeCastExpression := nil
- token: ^ElnaLexerToken
- start_location: ElnaLocation
-begin
- token := elna_lexer_read(cursor);
- start_location := token^.position.start_location;
-
- if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) <> nil then
- result := malloc#[ElnaTreeCastExpression](#size(ElnaTreeCastExpression));
- result^.kind := ElnaTreeKind._cast;
- result^.position.start_location := start_location;
- result^.type_decoration := nil;
- result^.expression := elna_parser_binary_expression(cursor, error_list);
- if result^.expression = nil then
- result := free_and_nil(result)
- elsif elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) = nil then
- result := free_and_nil(result)
- else
- result^.type_expression := elna_parser_type_expression(cursor, error_list);
- if result^.type_expression = nil then
- result := free_and_nil(result)
- else
- token := elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list);
- if token = nil then
- result := free_and_nil(result)
- else
- result^.position.end_location := token^.position.end_location
- end
- end
- end
- end
-return result
-
-proc elna_parser_simple_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeExpression := nil
-begin
- token := elna_lexer_peek(cursor);
- case token^.kind of
- ElnaLexerKind.character:
- result := cast(elna_parser_character_literal(cursor): ^ElnaTreeExpression)
- | ElnaLexerKind.integer:
- result := cast(elna_parser_integer_literal(cursor): ^ElnaTreeExpression)
- | ElnaLexerKind.string:
- result := cast(elna_parser_string_literal(cursor): ^ElnaTreeExpression)
- | ElnaLexerKind.boolean:
- result := cast(elna_parser_boolean_literal(cursor): ^ElnaTreeExpression)
- | ElnaLexerKind.null:
- result := cast(elna_parser_nil_literal(cursor): ^ElnaTreeExpression)
- | ElnaLexerKind._cast:
- result := cast(elna_parser_cast_expression(cursor, error_list): ^ElnaTreeExpression)
- | ElnaLexerKind.trait:
- result := cast(elna_parser_trait_expression(cursor, error_list): ^ElnaTreeExpression)
- | ElnaLexerKind.identifier:
- result := cast(elna_parser_variable_expression(cursor): ^ElnaTreeExpression)
- else
- end
-return result
-
-proc elna_parser_dereference_expression*(cursor: ^ElnaLexerCursor;
- simple_expression: ^ElnaTreeExpression) -> ^ElnaTreeDereferenceExpression
-var
- result: ^ElnaTreeDereferenceExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeDereferenceExpression](#size(ElnaTreeDereferenceExpression));
- result^.kind := ElnaTreeKind.dereference_expression;
- result^.pointer := simple_expression;
- result^.type_decoration := nil;
- result^.position := token^.position
-return result
-
-proc elna_parser_field_access_expression*(cursor: ^ElnaLexerCursor;
- aggregate: ^ElnaTreeExpression) -> ^ElnaTreeFieldAccessExpression
-var
- result: ^ElnaTreeFieldAccessExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeFieldAccessExpression](#size(ElnaTreeFieldAccessExpression));
- result^.kind := ElnaTreeKind.field_access_expression;
- result^.type_decoration := nil;
- result^.aggregate := aggregate;
- result^.position.start_location := token^.position.start_location;
-
- token := elna_lexer_read(cursor);
- result^.field := token^.start;
- result^.position.end_location := token^.position.end_location
-return result
-
-proc elna_parser_array_access_expression*(cursor: ^ElnaLexerCursor;
- array: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeArrayAccessExpression
-var
- result: ^ElnaTreeArrayAccessExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeArrayAccessExpression](#size(ElnaTreeArrayAccessExpression));
- result^.kind := ElnaTreeKind.array_access_expression;
- result^.type_decoration := nil;
- result^.array := array;
- result^.position.start_location := token^.position.start_location;
-
- result^.index := elna_parser_binary_expression(cursor, error_list);
- if result^.index = nil then
- result := free_and_nil(result)
- else
- token := elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list);
- if token = nil then
- result := free_and_nil(result)
- else
- result^.position.end_location := token^.position.end_location
- end
- end
-return result
-
-proc elna_parser_call*(cursor: ^ElnaLexerCursor; callee: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeCall
-var
- result: ^ElnaTreeCall
- argument_entry: ^ElnaTreeExpressionList
- token: ^ElnaLexerToken
- parser_error: ^ElnaErrorUnexpectedToken
- reading_args: Bool := true
-begin
- result := malloc#[ElnaTreeCall](#size(ElnaTreeCall));
- result^.kind := ElnaTreeKind.call;
- result^.type_decoration := nil;
- result^.arguments := nil;
- result^.count := 0u;
- result^.callee := cast(callee: ^ElnaTreeVariableExpression);
-
- token := elna_lexer_read(cursor);
- result^.position.start_location := token^.position.start_location;
- token := elna_lexer_peek(cursor);
-
- if token^.kind = ElnaLexerKind.right_paren then
- token := elna_lexer_read(cursor);
- result^.position.end_location := token^.position.end_location
- else
- while reading_args do
- if result^.arguments = nil then
- result^.arguments := malloc#[ElnaTreeExpressionList](#size(ElnaTreeExpressionList));
- argument_entry := result^.arguments
- else
- argument_entry^.next := malloc#[ElnaTreeExpressionList](#size(ElnaTreeExpressionList));
- argument_entry := argument_entry^.next
- end;
- argument_entry^.next := nil;
- argument_entry^.expression := elna_parser_binary_expression(cursor, error_list);
- if argument_entry^.expression = nil then
- result := free_and_nil(result);
- reading_args := false
- else
- result^.count := result^.count + 1u;
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.comma then
- elna_lexer_read(cursor)
- elsif token^.kind = ElnaLexerKind.right_paren then
- token := elna_lexer_read(cursor);
- result^.position.end_location := token^.position.end_location;
- reading_args := false
- else
- parser_error := elna_error_unexpected_token_create(cursor, 2u);
- parser_error^.expected[1] := ElnaLexerKind.comma;
- parser_error^.expected[2] := ElnaLexerKind.right_paren;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode));
- result := free_and_nil(result);
- reading_args := false
- end
- end
- end
- end
-return result
-
-proc elna_parser_designator*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression
-var
- simple_expression: ^ElnaTreeExpression
- token: ^ElnaLexerToken
- continue_loop: Bool := true
-begin
- simple_expression := elna_parser_simple_expression(cursor, error_list);
- if simple_expression <> nil then
- while continue_loop do
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.hat then
- simple_expression := cast(elna_parser_dereference_expression(cursor, simple_expression): ^ElnaTreeExpression)
- elsif token^.kind = ElnaLexerKind.dot then
- simple_expression := cast(elna_parser_field_access_expression(cursor, simple_expression): ^ElnaTreeExpression)
- elsif token^.kind = ElnaLexerKind.left_square then
- simple_expression := cast(elna_parser_array_access_expression(cursor, simple_expression, error_list): ^ElnaTreeExpression);
- if simple_expression = nil then
- continue_loop := false
- end
- elsif token^.kind = ElnaLexerKind.left_paren then
- simple_expression := cast(elna_parser_call(cursor, simple_expression, error_list): ^ElnaTreeExpression);
- if simple_expression = nil then
- continue_loop := false
- end
- else
- continue_loop := false
- end
- end
- end
-return simple_expression
-
-proc elna_parser_unary_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression
-var
- unary_result: ^ElnaTreeUnaryExpression
- result: ^ElnaTreeExpression
- op_kind: ElnaLexerKind
- has_op: Bool := false
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.at or token^.kind = ElnaLexerKind.minus or token^.kind = ElnaLexerKind.not then
- op_kind := token^.kind;
- has_op := true;
- elna_lexer_read(cursor)
- end;
- result := elna_parser_designator(cursor, error_list);
- if result <> nil & has_op then
- unary_result := malloc#[ElnaTreeUnaryExpression](#size(ElnaTreeUnaryExpression));
- unary_result^.kind := ElnaTreeKind.unary_expression;
- unary_result^.operand := result;
- unary_result^.operator := op_kind;
- unary_result^.position := token^.position;
- unary_result^.type_decoration := nil;
- result := cast(unary_result: ^ElnaTreeExpression)
- end
-return result
-
-proc elna_parser_binary_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeExpression
-var
- lhs_node: ^ElnaTreeExpression
- rhs_node: ^ElnaTreeExpression := nil
- bin_result: ^ElnaTreeBinaryExpression
- token: ^ElnaLexerToken
-begin
- lhs_node := elna_parser_unary_expression(cursor, error_list);
- token := elna_lexer_peek(cursor);
-
- case token^.kind of
- ElnaLexerKind.plus,
- ElnaLexerKind.minus,
- ElnaLexerKind.multiplication,
- ElnaLexerKind.and,
- ElnaLexerKind._or,
- ElnaLexerKind._xor,
- ElnaLexerKind.equals,
- ElnaLexerKind.remainder,
- ElnaLexerKind.division,
- ElnaLexerKind.less_than,
- ElnaLexerKind.greater_than,
- ElnaLexerKind.less_equal,
- ElnaLexerKind.not_equal,
- ElnaLexerKind.greater_equal:
- elna_lexer_read(cursor);
- rhs_node := elna_parser_unary_expression(cursor, error_list)
- else
- end;
-
- if rhs_node <> nil then
- bin_result := malloc#[ElnaTreeBinaryExpression](#size(ElnaTreeBinaryExpression));
- bin_result^.kind := ElnaTreeKind.binary_expression;
- bin_result^.lhs := lhs_node;
- bin_result^.rhs := rhs_node;
- bin_result^.operator := token^.kind;
- bin_result^.position := token^.position;
- bin_result^.type_decoration := nil;
- lhs_node := cast(bin_result: ^ElnaTreeExpression)
- end
-return lhs_node
-
-proc elna_parser_label_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeLabelDeclaration
-var
- result: ^ElnaTreeLabelDeclaration
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeLabelDeclaration](#size(ElnaTreeLabelDeclaration));
- result^.kind := ElnaTreeKind.label_declaration;
- result^.next := nil;
- result^.position.start_location := token^.position.start_location;
-
- token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list);
- if token <> nil then
- result^.label := token^.start;
- result^.position.end_location := token^.position.end_location
- else
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_assign_statement*(cursor: ^ElnaLexerCursor; assignee: ^ElnaTreeExpression; error_list: ^ElnaList) -> ^ElnaTreeAssignStatement
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeAssignStatement
-begin
- result := malloc#[ElnaTreeAssignStatement](#size(ElnaTreeAssignStatement));
- result^.kind := ElnaTreeKind.assign_statement;
- result^.next := nil;
- result^.assignee := assignee;
- result^.assignment := nil;
-
- token := elna_parser_expect(cursor, ElnaLexerKind.assignment, error_list);
- if token <> nil then
- result^.position := token^.position;
- result^.assignment := elna_parser_binary_expression(cursor, error_list)
- end;
- if result^.assignment = nil then
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_return_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeReturnStatement
-var
- token: ^ElnaLexerToken
- result: ^ElnaTreeReturnStatement
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeReturnStatement](#size(ElnaTreeReturnStatement));
- result^.kind := ElnaTreeKind.return_statement;
- result^.next := nil;
- result^.position := token^.position;
- result^.returned := elna_parser_binary_expression(cursor, error_list);
- if result^.returned = nil then
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_conditional_statements*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList;
- block_keyword: ElnaLexerKind) -> ^ElnaTreeConditionalStatements
-var
- result: ^ElnaTreeConditionalStatements
-begin
- result := malloc#[ElnaTreeConditionalStatements](#size(ElnaTreeConditionalStatements));
- elna_lexer_read(cursor);
- result^.condition := elna_parser_binary_expression(cursor, error_list);
- if result^.condition = nil then
- result := free_and_nil(result)
- else
- if elna_parser_expect(cursor, block_keyword, error_list) <> nil then
- result^.statements := elna_parser_statements(cursor, error_list)
- end;
- if elna_list_empty(error_list) then
- result^.next := nil
- else
- result := free_and_nil(result)
- end
- end
-return result
-
-proc elna_parser_if_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeIfStatement
-var
- result: ^ElnaTreeIfStatement
- previous_conditional: ^ElnaTreeConditionalStatements
- next_conditional: ^ElnaTreeConditionalStatements
- token: ^ElnaLexerToken
- reading_elsif: Bool := true
-begin
- token := elna_lexer_peek(cursor);
- result := malloc#[ElnaTreeIfStatement](#size(ElnaTreeIfStatement));
- result^.kind := ElnaTreeKind.if_statement;
- result^.position := token^.position;
- result^.next := nil;
-
- previous_conditional := elna_parser_conditional_statements(cursor, error_list, ElnaLexerKind._then);
- result^.conditionals := previous_conditional;
-
- while reading_elsif do
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._elsif then
- next_conditional := elna_parser_conditional_statements(cursor, error_list, ElnaLexerKind._then);
- previous_conditional^.next := next_conditional;
- previous_conditional := next_conditional
- elsif token^.kind = ElnaLexerKind._else then
- elna_lexer_read(cursor);
- result^._else := elna_parser_statements(cursor, error_list);
- reading_elsif := false
- else
- result^._else := nil;
- reading_elsif := false
- end
- end;
- elna_parser_expect(cursor, ElnaLexerKind._end, error_list)
-return result
-
-proc elna_parser_statement*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement
-var
- result: ^ElnaTreeStatement := nil
- call_result: ^ElnaTreeCallStatement
- designator: ^ElnaTreeExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._if then
- result := cast(elna_parser_if_statement(cursor, error_list): ^ElnaTreeStatement)
- elsif token^.kind = ElnaLexerKind._return then
- result := cast(elna_parser_return_statement(cursor, error_list): ^ElnaTreeStatement)
- elsif token^.kind = ElnaLexerKind.dot then
- result := cast(elna_parser_label_declaration(cursor, error_list): ^ElnaTreeStatement)
- elsif token^.kind = ElnaLexerKind.identifier then
- designator := elna_parser_designator(cursor, error_list);
- if designator <> nil then
- if designator^.kind <> ElnaTreeKind.call then
- result := cast(elna_parser_assign_statement(cursor, designator, error_list): ^ElnaTreeStatement)
- else
- call_result := malloc#[ElnaTreeCallStatement](#size(ElnaTreeCallStatement));
- call_result^.kind := ElnaTreeKind.call_statement;
- call_result^.next := nil;
- call_result^.call := cast(designator: ^ElnaTreeCall);
- call_result^.position := designator^.position;
- result := cast(call_result: ^ElnaTreeStatement)
- end
- end
- end
-return result
-
-proc elna_parser_statements*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement
-var
- previous_statement: ^ElnaTreeStatement
- next_statement: ^ElnaTreeStatement
- first_statement: ^ElnaTreeStatement
- token: ^ElnaLexerToken
-begin
- elna_lexer_skip_empty_lines(cursor);
- first_statement := elna_parser_statement(cursor, error_list);
- previous_statement := first_statement;
- if previous_statement <> nil then
- token := elna_lexer_peek(cursor);
- while token^.kind = ElnaLexerKind.semicolon & elna_list_empty(error_list) do
- elna_lexer_read(cursor);
- elna_lexer_skip_empty_lines(cursor);
- next_statement := elna_parser_statement(cursor, error_list);
- previous_statement^.next := next_statement;
- previous_statement := next_statement;
- token := elna_lexer_peek(cursor)
- end
- end;
- elna_lexer_skip_empty_lines(cursor)
-return first_statement
-
-proc elna_parser_named_type_expression*(cursor: ^ElnaLexerCursor) -> ^ElnaTreeNamedTypeExpression
-var
- result: ^ElnaTreeNamedTypeExpression
- token: ^ElnaLexerToken
-begin
- result := malloc#[ElnaTreeNamedTypeExpression](#size(ElnaTreeNamedTypeExpression));
- token := elna_lexer_read(cursor);
- result^.kind := ElnaTreeKind.named_type_expression;
- result^.name := token^.start;
- result^.position := token^.position
-return result
-
-proc elna_parser_pointer_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreePointerTypeExpression
-var
- result: ^ElnaTreePointerTypeExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreePointerTypeExpression](#size(ElnaTreePointerTypeExpression));
- result^.kind := ElnaTreeKind.pointer_type_expression;
- result^.base := elna_parser_type_expression(cursor, error_list);
- result^.position := token^.position;
- if result^.base = nil then
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_array_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeArrayTypeExpression
-var
- result: ^ElnaTreeArrayTypeExpression
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeArrayTypeExpression](#size(ElnaTreeArrayTypeExpression));
- result^.kind := ElnaTreeKind.array_type_expression;
- result^.position.start_location := token^.position.start_location;
-
- result^.length := elna_parser_binary_expression(cursor, error_list);
- if result^.length = nil then
- result := free_and_nil(result)
- else
- token := elna_parser_expect(cursor, ElnaLexerKind.right_square, error_list);
- if token = nil then
- result := free_and_nil(result)
- else
- result^.base := elna_parser_type_expression(cursor, error_list);
- if result^.base = nil then
- result := free_and_nil(result)
- else
- result^.position.end_location := token^.position.end_location
- end
- end
- end
-return result
-
-proc elna_parser_record_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeRecordTypeExpression
-var
- entry: ^ElnaTreeField
- result: ^ElnaTreeRecordTypeExpression
- previous_entry: ^ElnaTreeField
- token: ^ElnaLexerToken
- parser_error: ^ElnaErrorUnexpectedToken
- reading_members: Bool := true
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeRecordTypeExpression](#size(ElnaTreeRecordTypeExpression));
- result^.kind := ElnaTreeKind.record_type_expression;
- result^.members := nil;
- result^.length := 0u;
- result^.position := token^.position;
-
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.left_paren then
- elna_lexer_read(cursor);
- token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list);
- if token = nil then
- result := free_and_nil(result);
- reading_members := false
- else
- result^.parent := token^.start;
- if elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then
- result := free_and_nil(result);
- reading_members := false
- end
- end
- end;
-
- while reading_members & result <> nil do
- token := elna_lexer_read(cursor);
- if token^.kind = ElnaLexerKind._end then
- reading_members := false
- elsif token^.kind <> ElnaLexerKind.identifier then
- parser_error := elna_error_unexpected_token_create(cursor, 2u);
- parser_error^.expected[1] := ElnaLexerKind._end;
- parser_error^.expected[2] := ElnaLexerKind.identifier;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode));
- result := free_and_nil(result);
- reading_members := false
- else
- entry := malloc#[ElnaTreeField](#size(ElnaTreeField));
- result^.length := result^.length + 1u;
- entry^.name := token^.start;
- if elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) = nil then
- result := free_and_nil(result);
- reading_members := false
- else
- entry^.type_expression := elna_parser_type_expression(cursor, error_list);
- if entry^.type_expression = nil then
- result := free_and_nil(result);
- reading_members := false
- else
- entry^.next := nil;
- if result^.members = nil then
- result^.members := entry
- else
- previous_entry^.next := entry
- end;
- previous_entry := entry;
-
- token := elna_lexer_read(cursor);
- if token^.kind = ElnaLexerKind.semicolon then
- (* continue *)
- elsif token^.kind = ElnaLexerKind._end then
- reading_members := false
- else
- parser_error := elna_error_unexpected_token_create(cursor, 2u);
- parser_error^.expected[1] := ElnaLexerKind._end;
- parser_error^.expected[2] := ElnaLexerKind.semicolon;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode));
- reading_members := false
- end
- end
- end
- end
- end
-return result
-
-proc elna_parser_enumeration_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeEnumerationTypeExpression
-var
- result: ^ElnaTreeEnumerationTypeExpression
- entry: ^ElnaTreeEnumeration
- previous_entry: ^ElnaTreeEnumeration
- token: ^ElnaLexerToken
- parser_error: ^ElnaErrorUnexpectedToken
- reading_members: Bool := true
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeEnumerationTypeExpression](#size(ElnaTreeEnumerationTypeExpression));
- result^.kind := ElnaTreeKind.enumeration_type_expression;
- result^.members := nil;
- result^.length := 0u;
- result^.position.start_location := token^.position.start_location;
-
- while reading_members & result <> nil do
- token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list);
- if token = nil then
- result := free_and_nil(result);
- reading_members := false
- else
- entry := malloc#[ElnaTreeEnumeration](#size(ElnaTreeEnumeration));
- result^.length := result^.length + 1u;
- entry^.name := token^.start;
- entry^.next := nil;
- if result^.members = nil then
- result^.members := entry
- else
- previous_entry^.next := entry
- end;
- previous_entry := entry;
-
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.comma then
- elna_lexer_read(cursor)
- elsif token^.kind = ElnaLexerKind.right_paren then
- token := elna_lexer_read(cursor);
- result^.position.end_location := token^.position.end_location;
- reading_members := false
- else
- parser_error := elna_error_unexpected_token_create(cursor, 2u);
- parser_error^.expected[1] := ElnaLexerKind.comma;
- parser_error^.expected[2] := ElnaLexerKind.right_paren;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode));
- result := free_and_nil(result);
- reading_members := false
- end
- end
- end
-return result
-
-proc elna_parser_type_expression*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTypeExpression
-var
- result: ^ElnaTreeTypeExpression := nil
- token: ^ElnaLexerToken
- parser_error: ^ElnaErrorUnexpectedToken
-begin
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.identifier then
- result := cast(elna_parser_named_type_expression(cursor): ^ElnaTreeTypeExpression)
- elsif token^.kind = ElnaLexerKind.left_paren then
- result := cast(elna_parser_enumeration_type_expression(cursor, error_list): ^ElnaTreeTypeExpression)
- elsif token^.kind = ElnaLexerKind._record then
- result := cast(elna_parser_record_type_expression(cursor, error_list): ^ElnaTreeTypeExpression)
- elsif token^.kind = ElnaLexerKind.hat then
- result := cast(elna_parser_pointer_type_expression(cursor, error_list): ^ElnaTreeTypeExpression)
- elsif token^.kind = ElnaLexerKind.left_square then
- result := cast(elna_parser_array_type_expression(cursor, error_list): ^ElnaTreeTypeExpression)
- else
- parser_error := elna_error_unexpected_token_create(cursor, 5u);
- parser_error^.expected[1] := ElnaLexerKind.identifier;
- parser_error^.expected[2] := ElnaLexerKind.left_paren;
- parser_error^.expected[3] := ElnaLexerKind._record;
- parser_error^.expected[4] := ElnaLexerKind.hat;
- parser_error^.expected[5] := ElnaLexerKind.left_square;
- elna_list_append(error_list, cast(parser_error: ^ElnaListNode))
- end
-return result
-
-proc elna_parser_variable_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration
-var
- var_type: ^ElnaTreeTypeExpression
- result: ^ElnaTreeVariableDeclaration := nil
- token: ^ElnaLexerToken
-begin
- token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list);
- if token <> nil then
- if elna_parser_expect(cursor, ElnaLexerKind.colon, error_list) <> nil then
- var_type := elna_parser_type_expression(cursor, error_list);
- if var_type <> nil then
- result := malloc#[ElnaTreeVariableDeclaration](#size(ElnaTreeVariableDeclaration));
- result^.kind := ElnaTreeKind.variable_declaration;
- result^.next := nil;
- result^.name := token^.start;
- result^.type_expression := var_type;
- result^.position := token^.position
- end
- end
- end
-return result
-
-proc elna_parser_parameters*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration
-var
- parameters: ^ElnaTreeVariableDeclaration := nil
- token: ^ElnaLexerToken
- current_declaration: ^ElnaTreeVariableDeclaration
- next_declaration: ^ElnaTreeVariableDeclaration
- reading: Bool := true
-begin
- token := elna_lexer_peek(cursor);
- if token^.kind <> ElnaLexerKind.right_paren then
- while reading do
- next_declaration := elna_parser_variable_declaration(cursor, error_list);
- if next_declaration = nil then
- parameters := free_and_nil(parameters);
- reading := false
- else
- if parameters = nil then
- parameters := next_declaration
- else
- current_declaration^.next := cast(next_declaration: ^ElnaTreeDeclaration)
- end;
- current_declaration := next_declaration;
-
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.comma or token^.kind = ElnaLexerKind.semicolon then
- elna_lexer_read(cursor)
- else
- reading := false
- end
- end
- end
- end
-return parameters
-
-proc elna_parser_procedure_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeProcedureDeclaration
-var
- result: ^ElnaTreeProcedureDeclaration
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeProcedureDeclaration](#size(ElnaTreeProcedureDeclaration));
- result^.kind := ElnaTreeKind.procedure_declaration;
- result^.next := nil;
- result^.position := token^.position;
-
- token := elna_parser_expect(cursor, ElnaLexerKind.identifier, error_list);
- if token = nil then
- result := free_and_nil(result)
- else
- result^.name := token^.start;
-
- if elna_parser_expect(cursor, ElnaLexerKind.left_paren, error_list) = nil then
- result := free_and_nil(result)
- else
- result^.parameters := elna_parser_parameters(cursor, error_list);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- elsif elna_parser_expect(cursor, ElnaLexerKind.right_paren, error_list) = nil then
- result := free_and_nil(result)
- else
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.arrow then
- elna_lexer_read(cursor);
- result^.return_type := elna_parser_type_expression(cursor, error_list);
- if result^.return_type = nil then
- result := free_and_nil(result)
- end
- else
- result^.return_type := nil
- end;
-
- if result <> nil then
- 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);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- else
- 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)
- elsif elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = nil then
- result := free_and_nil(result)
- end
- elsif token^.kind = ElnaLexerKind._return then
- result^.body := cast(elna_parser_return_statement(cursor, error_list): ^ElnaTreeStatement);
- if result^.body = nil then
- result := free_and_nil(result)
- end
- end
- end
- end
- end
- end
- end
- end
-return result
-
-proc elna_parser_procedures*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeProcedureDeclaration
-var
- parser_node: ^ElnaTreeProcedureDeclaration
- result: ^ElnaTreeProcedureDeclaration := nil
- current_declaration: ^ElnaTreeProcedureDeclaration
- token: ^ElnaLexerToken
- reading: Bool := true
-begin
- while reading do
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._proc then
- parser_node := elna_parser_procedure_declaration(cursor, error_list);
- if parser_node <> nil then
- if result = nil then
- result := parser_node
- else
- current_declaration^.next := cast(parser_node: ^ElnaTreeDeclaration)
- end;
- current_declaration := parser_node
- else
- reading := false
- end
- else
- reading := false
- end
- end
-return result
-
-proc elna_parser_type_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeTypeDeclaration
-var
- result: ^ElnaTreeTypeDeclaration
- token: ^ElnaLexerToken
-begin
- token := elna_lexer_read(cursor);
- result := malloc#[ElnaTreeTypeDeclaration](#size(ElnaTreeTypeDeclaration));
- result^.kind := ElnaTreeKind.type_declaration;
- result^.next := nil;
- result^.name := token^.start;
- result^.position := token^.position;
-
- if elna_parser_expect(cursor, ElnaLexerKind.equals, error_list) <> nil then
- result^.type_expression := elna_parser_type_expression(cursor, error_list)
- else
- result := free_and_nil(result)
- end
-return result
-
-proc elna_parser_type_part*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeDeclaration
-var
- parser_node: ^ElnaTreeDeclaration
- result: ^ElnaTreeDeclaration := nil
- current_declaration: ^ElnaTreeDeclaration
- token: ^ElnaLexerToken
- reading: Bool := true
-begin
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._type then
- elna_lexer_read(cursor);
- while reading do
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.identifier then
- parser_node := cast(elna_parser_type_declaration(cursor, error_list): ^ElnaTreeDeclaration);
- if parser_node <> nil then
- if result = nil then
- result := parser_node
- else
- current_declaration^.next := parser_node
- end;
- current_declaration := parser_node;
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.semicolon then
- elna_lexer_read(cursor)
- end
- else
- reading := false
- end
- else
- reading := false
- end
- end
- end
-return result
-
-proc elna_parser_var_part*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeVariableDeclaration
-var
- result: ^ElnaTreeVariableDeclaration := nil
- variable_node: ^ElnaTreeVariableDeclaration
- current_declaration: ^ElnaTreeVariableDeclaration
- token: ^ElnaLexerToken
- reading: Bool := true
-begin
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._var then
- elna_lexer_read(cursor);
- while reading do
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.identifier then
- variable_node := elna_parser_variable_declaration(cursor, error_list);
- if variable_node <> nil then
- if result = nil then
- result := variable_node
- else
- current_declaration^.next := cast(variable_node: ^ElnaTreeDeclaration)
- end;
- current_declaration := variable_node;
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind.semicolon then
- elna_lexer_read(cursor)
- end
- else
- reading := false
- end
- else
- reading := false
- end
- end
- end
-return result
-
-proc elna_parser_program_body*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeStatement
-var
- result: ^ElnaTreeStatement := nil
- token: ^ElnaLexerToken
-begin
- elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_peek(cursor);
- if token^.kind = ElnaLexerKind._begin then
- elna_lexer_read(cursor);
- result := elna_parser_statements(cursor, error_list);
- if elna_parser_expect(cursor, ElnaLexerKind._end, error_list) = nil then
- result := free_and_nil(result)
- elsif elna_parser_expect(cursor, ElnaLexerKind.dot, error_list) = nil then
- result := free_and_nil(result)
- end
- elsif token^.kind = ElnaLexerKind._end then
- elna_lexer_read(cursor);
- if elna_parser_expect(cursor, ElnaLexerKind.dot, error_list) = nil then
- result := free_and_nil(result)
- end
- end
-return result
-
-proc elna_parser_module_declaration*(cursor: ^ElnaLexerCursor; error_list: ^ElnaList) -> ^ElnaTreeModuleDeclaration
-var
- result: ^ElnaTreeModuleDeclaration
-begin
- result := malloc#[ElnaTreeModuleDeclaration](#size(ElnaTreeModuleDeclaration));
- result^.kind := ElnaTreeKind.module_declaration;
- result^.position.start_location := { ElnaLocation; line: 1u, column: 1u };
- result^.position.end_location := result^.position.start_location;
-
- result^.types := elna_parser_type_part(cursor, error_list);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- end;
-
- if result <> nil then
- result^.globals := elna_parser_var_part(cursor, error_list);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- end
- end;
-
- if result <> nil then
- result^.procedures := elna_parser_procedures(cursor, error_list);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- end
- end;
-
- if result <> nil then
- result^.body := elna_parser_program_body(cursor, error_list);
- if elna_list_empty(error_list) = false then
- result := free_and_nil(result)
- end
- end
-return result
-
-end.
diff --git a/source/qbe.elna b/source/qbe.elna
deleted file mode 100644
index 47eac88..0000000
--- a/source/qbe.elna
+++ /dev/null
@@ -1,635 +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/. *)
-module
-import common, sys.posix.cstdlib, sys.posix.cstdio, sys.posix.cstring, lexer, ast, symbol, tac
-
-var
- qbe_unique_id: Word := 0u
-
-proc qbe_write_slice(file: ^FILE; text: []const Word8)
-begin
- fwrite#[Word8](text.ptr, 1u, text.length, file)
-return
-
-proc qbe_write_str(file: ^FILE; str: ^const Word8)
-begin
- fwrite#[Word8](str, 1u, strlen(str), file)
-return
-
-proc qbe_write_word(file: ^FILE; val: Word)
-var
- buf: [32]Word8
- len: Int
-begin
- len := sprintf(@buf[1], "%u\0".ptr, val);
- fwrite#[Word8](@buf[1], 1u, cast(len: Word), file)
-return
-
-proc is_global(globals: ^ElnaTacStaticVariable; name: []const Word8) -> Bool
-var
- current: ^ElnaTacStaticVariable
- found: Bool := false
-begin
- current := globals;
- while current <> nil & ~found do
- if current^.name = name then
- found := true
- else
- current := current^.next
- end
- end
-return found
-
-proc is_string_constant(strings: ^ElnaTacStringConstant; name: []const Word8) -> Bool
-var
- current: ^ElnaTacStringConstant
- found: Bool := false
-begin
- current := strings;
- while current <> nil & ~found do
- if current^.name = name then
- found := true
- else
- current := current^.next
- end
- end
-return found
-
-proc is_pointer_type(_type: ^ElnaType) -> Bool
-var
- result: Bool := false
-begin
- if _type <> nil then
- if _type^.kind = ElnaTypeKind.pointer then
- result := true
- elsif _type = pointer_type then
- result := true
- end
- end
-return result
-
-proc get_procedure_return_type(proc_name: []const Word8) -> ^ElnaType
-var
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
- result: ^ElnaType := nil
-begin
- symbol_info := elna_symbol_table_lookup(symbol_table_global, proc_name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- if procedure_info^.procedure_type <> nil then
- result := procedure_info^.procedure_type^.return_type
- end
- end
-return result
-
-proc get_param_type(sym_table: ^ElnaSymbolTable; param_name: []const Word8) -> ^ElnaType
-var
- symbol_info: ^ElnaSymbolInfo
- temp_info: ^ElnaSymbolTemporaryInfo
- result: ^ElnaType := nil
-begin
- symbol_info := elna_symbol_table_lookup(sym_table, param_name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(symbol_info: ^ElnaSymbolTemporaryInfo);
- result := temp_info^.variable_type
- end
-return result
-
-proc is_pointer_operand(op: ^ElnaTacOperand; sym_table: ^ElnaSymbolTable;
- globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant) -> Bool
-var
- var_type: ^ElnaType
- result: Bool := false
-begin
- if op^.kind = ElnaTacKind.variable then
- if is_global(globals, op^.name) or is_string_constant(strings, op^.name) then
- result := true
- else
- var_type := get_param_type(sym_table, op^.name);
- if is_pointer_type(var_type) then
- result := true
- end
- end
- end
-return result
-
-proc qbe_emit_operand(file: ^FILE; op: ^ElnaTacOperand;
- globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant)
-begin
- case op^.kind of
- ElnaTacKind.constant:
- qbe_write_word(file, op^.constant)
- | ElnaTacKind.variable:
- if is_global(globals, op^.name) or is_string_constant(strings, op^.name) then
- qbe_write_str(file, "$\0".ptr)
- else
- qbe_write_str(file, "%\0".ptr)
- end;
- qbe_write_slice(file, op^.name)
- | ElnaTacKind.label:
- qbe_write_str(file, "@\0".ptr);
- qbe_write_slice(file, op^.name)
- else
- end
-return
-
-proc var_needs_stack_alloc(instructions: ^ElnaList; sym_table: ^ElnaSymbolTable; name: []const Word8) -> Bool
-var
- node: ^ElnaListNode
- inst: ^ElnaTacInstruction
- var_type: ^ElnaType
- result: Bool := false
-begin
- var_type := get_param_type(sym_table, name);
- if var_type <> nil then
- if var_type^.kind = ElnaTypeKind._record or var_type^.kind = ElnaTypeKind.array then
- result := true
- end
- end;
-
- node := instructions^.first;
- while node <> nil & ~result do
- inst := cast(node: ^ElnaTacInstruction);
- if inst^.operator = ElnaTacOperator.get_address & inst^.operands[1].name = name then
- result := true
- elsif inst^.operator = ElnaTacOperator.copy_to_offset & inst^.operands[2].name = name then
- result := true
- elsif inst^.operator = ElnaTacOperator.copy_from_offset & inst^.operands[1].name = name then
- result := true
- end;
- node := node^.next
- end
-return result
-
-proc qbe_emit_procedure(file: ^FILE; proc_node: ^ElnaTacProcedure;
- globals: ^ElnaTacStaticVariable; strings: ^ElnaTacStringConstant)
-var
- node: ^ElnaListNode
- inst: ^ElnaTacInstruction
- ret_type: ^ElnaType
- param_idx: Word := 0u
- param_name: []const Word8
- param_type: ^ElnaType
- entry: ^ElnaSymbolEntry
- temp_info: ^ElnaSymbolTemporaryInfo
- sym_idx: Word := 0u
- alloc_size: Word
- last_operator: ElnaTacOperator := ElnaTacOperator.nop
- tid: Word
- arg_i: Word
- arg_op: ^ElnaTacOperand
- callee_ret: ^ElnaType
- scaled: Word
-begin
- qbe_write_str(file, "export function \0".ptr);
- ret_type := get_procedure_return_type(proc_node^.name);
-
- if proc_node^.name = "main" then
- qbe_write_str(file, "w \0".ptr)
- elsif ret_type <> nil then
- if ret_type = bool_type then
- qbe_write_str(file, "w \0".ptr)
- else
- qbe_write_str(file, "l \0".ptr)
- end
- end;
-
- qbe_write_str(file, "$\0".ptr);
- qbe_write_slice(file, proc_node^.name);
- qbe_write_str(file, "(\0".ptr);
-
- while param_idx < proc_node^.count do
- param_name := (proc_node^.parameters + param_idx)^;
- param_type := get_param_type(proc_node^.symbol_table, param_name);
- if param_type = bool_type then
- qbe_write_str(file, "w %\0".ptr)
- else
- qbe_write_str(file, "l %\0".ptr)
- end;
- qbe_write_slice(file, param_name);
- if param_idx + 1u < proc_node^.count then
- qbe_write_str(file, ", \0".ptr)
- end;
- param_idx := param_idx + 1u
- end;
-
- qbe_write_str(file, ") {\n@start\n\0".ptr);
-
- (* Stack allocate variables needing memory address *)
- if proc_node^.symbol_table <> nil then
- while sym_idx < proc_node^.symbol_table^.count do
- entry := proc_node^.symbol_table^.symbols + sym_idx;
- if entry^.name.length > 0u & entry^.symbol_info <> nil then
- if entry^.symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(entry^.symbol_info: ^ElnaSymbolTemporaryInfo);
- if var_needs_stack_alloc(@proc_node^.body, proc_node^.symbol_table, entry^.name) then
- alloc_size := 8u;
- if temp_info^.variable_type <> nil & temp_info^.variable_type^.size > 8u then
- alloc_size := (temp_info^.variable_type^.size + 7u) / 8u * 8u
- end;
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, entry^.name);
- qbe_write_str(file, " =l alloc8 \0".ptr);
- qbe_write_word(file, alloc_size);
- qbe_write_str(file, "\n\0".ptr)
- end
- end
- end;
- sym_idx := sym_idx + 1u
- end
- end;
-
- (* Emit TAC instructions *)
- node := proc_node^.body.first;
- while node <> nil do
- inst := cast(node: ^ElnaTacInstruction);
- last_operator := inst^.operator;
-
- case inst^.operator of
- ElnaTacOperator.get_address:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, " =l copy \0".ptr);
- if is_global(globals, inst^.operands[1].name) or is_string_constant(strings, inst^.operands[1].name) then
- qbe_write_str(file, "$\0".ptr)
- else
- qbe_write_str(file, "%\0".ptr)
- end;
- qbe_write_slice(file, inst^.operands[1].name);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.copy:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, " =l copy \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.add:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.subtract:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l sub \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.multiply:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l mul \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.divide:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l div \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.remainder:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l rem \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator._or:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l or \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator._xor:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l xor \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.and:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l and \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.equal:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w ceql \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.not_equal:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w cnew \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.less_than:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w csltl \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.greater_than:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w csgtl \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.less_or_equal:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w cslel \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.greater_or_equal:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =w csgel \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.negate:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, " =l neg \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.complement:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, " =l xor \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", -1\n\0".ptr)
- | ElnaTacOperator.load:
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, " =l loadl \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.store:
- qbe_write_str(file, "\tstorel \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.copy_to_offset:
- if inst^.operands[3].constant = 0u then
- qbe_write_str(file, "\tstorel \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- else
- qbe_unique_id := qbe_unique_id + 1u;
- tid := qbe_unique_id;
- qbe_write_str(file, "\t%qbe_off_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_write_word(file, inst^.operands[3].constant);
- qbe_write_str(file, "\n\tstorel \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", %qbe_off_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- end
- | ElnaTacOperator.copy_from_offset:
- if inst^.operands[2].constant = 0u then
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l loadl \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- else
- qbe_unique_id := qbe_unique_id + 1u;
- tid := qbe_unique_id;
- qbe_write_str(file, "\t%qbe_off_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_write_word(file, inst^.operands[2].constant);
- qbe_write_str(file, "\n\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- qbe_write_str(file, " =l loadl %qbe_off_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- end
- | ElnaTacOperator.add_ptr:
- qbe_unique_id := qbe_unique_id + 1u;
- tid := qbe_unique_id;
- if inst^.operands[2].kind = ElnaTacKind.constant then
- if inst^.operands[3].constant = 1u then
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[4].name);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_write_word(file, inst^.operands[2].constant);
- qbe_write_str(file, "\n\0".ptr)
- else
- scaled := inst^.operands[2].constant * inst^.operands[3].constant;
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[4].name);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", \0".ptr);
- qbe_write_word(file, scaled);
- qbe_write_str(file, "\n\0".ptr)
- end
- else
- qbe_write_str(file, "\t%qbe_ext_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, " =l extuw \0".ptr);
- qbe_emit_operand(file, @inst^.operands[2], globals, strings);
- qbe_write_str(file, "\n\0".ptr);
-
- if inst^.operands[3].constant = 1u then
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[4].name);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", %qbe_ext_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- else
- qbe_write_str(file, "\t%qbe_s_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, " =l mul %qbe_ext_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, ", \0".ptr);
- qbe_write_word(file, inst^.operands[3].constant);
- qbe_write_str(file, "\n\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[4].name);
- qbe_write_str(file, " =l add \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", %qbe_s_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- end
- end
- | ElnaTacOperator.proc_call:
- callee_ret := get_procedure_return_type(inst^.operands[1].name);
- if inst^.operands[3].kind = ElnaTacKind.ignore then
- qbe_write_str(file, "\tcall $\0".ptr)
- else
- qbe_write_str(file, "\t%\0".ptr);
- qbe_write_slice(file, inst^.operands[3].name);
- if callee_ret = bool_type then
- qbe_write_str(file, " =w call $\0".ptr)
- else
- qbe_write_str(file, " =l call $\0".ptr)
- end
- end;
- qbe_write_slice(file, inst^.operands[1].name);
- qbe_write_str(file, "(\0".ptr);
-
- arg_i := 0u;
- while arg_i < inst^.operands[2].length do
- arg_op := inst^.operands[2].list_operands + arg_i;
- qbe_write_str(file, "l \0".ptr);
- qbe_emit_operand(file, arg_op, globals, strings);
- if arg_i + 1u < inst^.operands[2].length then
- qbe_write_str(file, ", \0".ptr)
- end;
- arg_i := arg_i + 1u
- end;
- qbe_write_str(file, ")\n\0".ptr)
- | ElnaTacOperator.jump:
- qbe_write_str(file, "\tjmp @\0".ptr);
- qbe_write_slice(file, inst^.operands[1].name);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.jump_if_zero:
- qbe_unique_id := qbe_unique_id + 1u;
- tid := qbe_unique_id;
- qbe_write_str(file, "\tjnz \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", @qbe_ft_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, ", @\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, "\n@qbe_ft_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.jump_if_not_zero:
- qbe_unique_id := qbe_unique_id + 1u;
- tid := qbe_unique_id;
- qbe_write_str(file, "\tjnz \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, ", @\0".ptr);
- qbe_write_slice(file, inst^.operands[2].name);
- qbe_write_str(file, ", @qbe_ft_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n@qbe_ft_\0".ptr);
- qbe_write_word(file, tid);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator.label:
- qbe_write_str(file, "@\0".ptr);
- qbe_write_slice(file, inst^.operands[1].name);
- qbe_write_str(file, "\n\0".ptr)
- | ElnaTacOperator._return:
- if inst^.operands[1].kind = ElnaTacKind.ignore then
- qbe_write_str(file, "\tret\n\0".ptr)
- else
- qbe_write_str(file, "\tret \0".ptr);
- qbe_emit_operand(file, @inst^.operands[1], globals, strings);
- qbe_write_str(file, "\n\0".ptr)
- end
- else
- end;
- node := node^.next
- end;
-
- (* Function terminator if not terminated *)
- if last_operator <> ElnaTacOperator._return & last_operator <> ElnaTacOperator.jump then
- if proc_node^.name = "main" then
- qbe_write_str(file, "\tret 0\n\0".ptr)
- elsif ret_type = nil then
- qbe_write_str(file, "\tret\n\0".ptr)
- else
- qbe_write_str(file, "\tret 0\n\0".ptr)
- end
- end;
-
- qbe_write_str(file, "}\n\n\0".ptr)
-return
-
-proc elna_qbe_emit*(instruction_module: ^ElnaInstructionModule; out_file: ^FILE)
-var
- current_string: ^ElnaTacStringConstant
- current_global: ^ElnaTacStaticVariable
- current_proc: ^ElnaTacProcedure
- i: Word
- byte_val: Word
-begin
- (* Emit strings *)
- current_string := instruction_module^.strings;
- while current_string <> nil do
- qbe_write_str(out_file, "data $\0".ptr);
- qbe_write_slice(out_file, current_string^.name);
- qbe_write_str(out_file, " = { \0".ptr);
-
- i := 0u;
- while i < current_string^.value.length do
- qbe_write_str(out_file, "b \0".ptr);
- byte_val := cast((current_string^.value.ptr + i)^: Word);
- qbe_write_word(out_file, byte_val);
- qbe_write_str(out_file, ", \0".ptr);
- i := i + 1u
- end;
- qbe_write_str(out_file, "b 0 }\n\0".ptr);
-
- current_string := current_string^.next
- end;
-
- (* Emit global data *)
- current_global := instruction_module^.data;
- while current_global <> nil do
- qbe_write_str(out_file, "export data $\0".ptr);
- qbe_write_slice(out_file, current_global^.name);
- qbe_write_str(out_file, " = { z \0".ptr);
- qbe_write_word(out_file, current_global^.size);
- qbe_write_str(out_file, " }\n\0".ptr);
-
- current_global := current_global^.next
- end;
-
- (* Emit procedures *)
- current_proc := instruction_module^.code;
- while current_proc <> nil do
- qbe_emit_procedure(out_file, current_proc, instruction_module^.data, instruction_module^.strings);
- current_proc := current_proc^.next
- end
-return
-
-end.
diff --git a/source/symbol.elna b/source/symbol.elna
deleted file mode 100644
index a07a9f3..0000000
--- a/source/symbol.elna
+++ /dev/null
@@ -1,200 +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/. *)
-module
-import sys.posix.cstdlib, common, ast
-
-type
- ElnaSymbolInfoKind* = (type_info, temporary_info, procedure_info)
- ElnaSymbolInfo* = record
- kind: ElnaSymbolInfoKind
- end
- ElnaSymbolTypeInfo* = record(ElnaSymbolInfo)
- _type: ^ElnaType
- end
- ElnaSymbolTemporaryInfo* = record(ElnaSymbolInfo)
- attr: Word;
- variable_type: ^ElnaType
- end
- ElnaSymbolProcedureInfo* = record(ElnaSymbolInfo)
- symbol_table: ^ElnaSymbolTable;
- procedure_type: ^ElnaTypeProcedure;
- is_extern: Bool
- end
-
- ElnaSymbolEntry* = record
- name: []const Word8;
- symbol_info: ^ElnaSymbolInfo
- end
- ElnaSymbolTable* = record
- count: Word;
- capacity: Word;
- parent: ^ElnaSymbolTable;
- symbols: ^ElnaSymbolEntry
- end
-
-var
- symbol_table_global*: ^ElnaSymbolTable
- word_type*: ^ElnaType
- int_type*: ^ElnaType
- pointer_type*: ^ElnaType
- bool_type*: ^ElnaType
- char_type*: ^ElnaType
- string_type*: ^ElnaTypeRecord
-
-proc elna_symbol_type_info_create*(type_representation: ^ElnaType) -> ^ElnaSymbolTypeInfo
-var
- result: ^ElnaSymbolTypeInfo
-begin
- result := malloc#[ElnaSymbolTypeInfo](#size(ElnaSymbolTypeInfo));
- result^.kind := ElnaSymbolInfoKind.type_info;
- result^._type := type_representation
-return result
-
-proc elna_symbol_temporary_info_create*(attr: Word; temporary_type: ^ElnaType) -> ^ElnaSymbolTemporaryInfo
-var
- result: ^ElnaSymbolTemporaryInfo
-begin
- result := malloc#[ElnaSymbolTemporaryInfo](#size(ElnaSymbolTemporaryInfo));
- result^.kind := ElnaSymbolInfoKind.temporary_info;
- result^.variable_type := temporary_type;
- result^.attr := attr
-return result
-
-proc elna_symbol_procedure_info_create*(is_extern: Bool) -> ^ElnaSymbolProcedureInfo
-var
- result: ^ElnaSymbolProcedureInfo
-begin
- result := malloc#[ElnaSymbolProcedureInfo](#size(ElnaSymbolProcedureInfo));
- result^.kind := ElnaSymbolInfoKind.procedure_info;
- result^.procedure_type := nil;
- result^.symbol_table := nil;
- result^.is_extern := is_extern
-return result
-
-proc elna_symbol_table_create*(parent: ^ElnaSymbolTable) -> ^ElnaSymbolTable
-var
- new_symbol_table: ^ElnaSymbolTable
-begin
- new_symbol_table := malloc#[ElnaSymbolTable](#size(ElnaSymbolTable));
- new_symbol_table^.capacity := 64u;
- new_symbol_table^.symbols := malloc#[ElnaSymbolEntry](new_symbol_table^.capacity * #size(ElnaSymbolEntry));
- new_symbol_table^.count := 0u;
- new_symbol_table^.parent := parent
-return new_symbol_table
-
-proc elna_symbol_table_enter*(symbol_table: ^ElnaSymbolTable; symbol_name: []const Word8; symbol: ^ElnaSymbolInfo)
-var
- entry: ^ElnaSymbolEntry
-begin
- if symbol_table^.count >= symbol_table^.capacity then
- symbol_table^.capacity := symbol_table^.capacity * 2u;
- symbol_table^.symbols := realloc#[ElnaSymbolEntry](symbol_table^.symbols, symbol_table^.capacity * #size(ElnaSymbolEntry))
- end;
- entry := symbol_table^.symbols + symbol_table^.count;
- entry^.name := symbol_name;
- entry^.symbol_info := symbol;
- symbol_table^.count := symbol_table^.count + 1u
-return
-
-proc elna_symbol_table_lookup_local*(symbol_table: ^ElnaSymbolTable; symbol_name: []const Word8) -> ^ElnaSymbolInfo
-var
- i: Word := 0u
- entry: ^ElnaSymbolEntry
- result: ^ElnaSymbolInfo := nil
-begin
- while i < symbol_table^.count & result = nil do
- entry := symbol_table^.symbols + i;
- if entry^.name = symbol_name then
- result := entry^.symbol_info
- end;
- i := i + 1u
- end
-return result
-
-proc elna_symbol_table_lookup*(symbol_table: ^ElnaSymbolTable; symbol_name: []const Word8) -> ^ElnaSymbolInfo
-var
- current: ^ElnaSymbolTable
- found: ^ElnaSymbolInfo := nil
-begin
- current := symbol_table;
- while current <> nil & found = nil do
- found := elna_symbol_table_lookup_local(current, symbol_name);
- current := current^.parent
- end
-return found
-
-proc elna_symbol_string_build()
-var
- current_field: ^ElnaTypeField
- char_pointer: ^ElnaTypePointer
-begin
- string_type := malloc#[ElnaTypeRecord](#size(ElnaTypeRecord));
- string_type^.kind := ElnaTypeKind._record;
- string_type^.size := 16u;
- string_type^.alignment := 8u;
- string_type^.members := malloc#[ElnaTypeField](2u * #size(ElnaTypeField));
- string_type^.length := 2u;
-
- char_pointer := malloc#[ElnaTypePointer](#size(ElnaTypePointer));
- char_pointer^.kind := ElnaTypeKind.pointer;
- char_pointer^.size := 8u;
- char_pointer^.alignment := 8u;
- char_pointer^.base := char_type;
-
- current_field := string_type^.members;
- current_field^.name := "ptr";
- current_field^.field_type := cast(char_pointer: ^ElnaType);
-
- current_field := current_field + 1u;
- current_field^.name := "length";
- current_field^.field_type := word_type
-return
-
-proc elna_symbol_table_build*()
-var
- current_info: ^ElnaSymbolTypeInfo
-begin
- symbol_table_global := elna_symbol_table_create(nil);
-
- word_type := malloc#[ElnaType](#size(ElnaType));
- word_type^.kind := ElnaTypeKind.primitive;
- word_type^.size := 8u;
- word_type^.alignment := 8u;
- current_info := elna_symbol_type_info_create(word_type);
- elna_symbol_table_enter(symbol_table_global, "Word", cast(current_info: ^ElnaSymbolInfo));
-
- int_type := malloc#[ElnaType](#size(ElnaType));
- int_type^.kind := ElnaTypeKind.primitive;
- int_type^.size := 8u;
- int_type^.alignment := 8u;
- current_info := elna_symbol_type_info_create(int_type);
- elna_symbol_table_enter(symbol_table_global, "Int", cast(current_info: ^ElnaSymbolInfo));
-
- pointer_type := malloc#[ElnaType](#size(ElnaType));
- pointer_type^.kind := ElnaTypeKind.primitive;
- pointer_type^.size := 8u;
- pointer_type^.alignment := 8u;
- current_info := elna_symbol_type_info_create(pointer_type);
- elna_symbol_table_enter(symbol_table_global, "Pointer", cast(current_info: ^ElnaSymbolInfo));
-
- bool_type := malloc#[ElnaType](#size(ElnaType));
- bool_type^.kind := ElnaTypeKind.primitive;
- bool_type^.size := 1u;
- bool_type^.alignment := 1u;
- current_info := elna_symbol_type_info_create(bool_type);
- elna_symbol_table_enter(symbol_table_global, "Bool", cast(current_info: ^ElnaSymbolInfo));
-
- char_type := malloc#[ElnaType](#size(ElnaType));
- char_type^.kind := ElnaTypeKind.primitive;
- char_type^.size := 1u;
- char_type^.alignment := 1u;
- current_info := elna_symbol_type_info_create(char_type);
- elna_symbol_table_enter(symbol_table_global, "Char", cast(current_info: ^ElnaSymbolInfo));
-
- elna_symbol_string_build();
- current_info := elna_symbol_type_info_create(cast(string_type: ^ElnaType));
- elna_symbol_table_enter(symbol_table_global, "String", cast(current_info: ^ElnaSymbolInfo))
-return
-
-end.
diff --git a/source/sys/posix/cctype.elna b/source/sys/posix/cctype.elna
deleted file mode 100644
index 19c3491..0000000
--- a/source/sys/posix/cctype.elna
+++ /dev/null
@@ -1,24 +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/. *)
-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
-
-proc tolower*(c: Int) -> Int
-extern
-
-proc toupper*(c: Int) -> Int
-extern
-
-end.
diff --git a/source/sys/posix/cstdio.elna b/source/sys/posix/cstdio.elna
deleted file mode 100644
index 928c7e1..0000000
--- a/source/sys/posix/cstdio.elna
+++ /dev/null
@@ -1,59 +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/. *)
-module
-
-type
- FILE* = extern
-
-var
- stdin*: ^FILE := extern
- stdout*: ^FILE := extern
- stderr*: ^FILE := extern
-
-proc fopen*(pathname, mode: ^const Word8) -> ^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*#[T](ptr: ^T; size: Word; nmemb: Word; stream: ^FILE) -> Word
-extern
-
-proc fwrite*#[T](ptr: ^const T; size: Word; nitems: Word; stream: ^FILE) -> Word
-extern
-
-proc fputc*(c: Int; stream: ^FILE) -> Word
-extern
-
-proc perror*(s: ^const Word8)
-extern
-
-proc puts*(s: ^const Word8) -> Int
-extern
-
-proc putchar*(c: Int) -> Int
-extern
-
-proc sprintf*(str: ^Word8; format: ^const Word8) #{varargs} -> Int
-extern
-
-proc fprintf*(stream: ^FILE; format: ^const Word8) #{varargs} -> Int
-extern
-
-proc fdopen*(fildes: Int; mode: ^const Word8) -> ^FILE
-extern
-
-end.
diff --git a/source/sys/posix/cstdlib.elna b/source/sys/posix/cstdlib.elna
deleted file mode 100644
index 10a4d80..0000000
--- a/source/sys/posix/cstdlib.elna
+++ /dev/null
@@ -1,24 +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/. *)
-module
-
-proc malloc*#[T](size: Word) -> ^T
-extern
-
-proc free*#[T](ptr: ^T)
-extern
-
-proc calloc*#[T](nmemb: Word; size: Word) -> ^T
-extern
-
-proc realloc*#[T](ptr: ^T; size: Word) -> ^T
-extern
-
-proc atoi*(str: ^Word8) -> Int
-extern
-
-proc exit*(code: Int) #{noreturn}
-extern
-
-end.
diff --git a/source/sys/posix/cstring.elna b/source/sys/posix/cstring.elna
deleted file mode 100644
index 3973573..0000000
--- a/source/sys/posix/cstring.elna
+++ /dev/null
@@ -1,30 +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/. *)
-module
-
-proc memset*#[T](ptr: ^T; c: Int; n: Word) -> ^Word8
-extern
-
-proc memcpy*#[T](dst: ^T; src: ^const T; n: Word)
-extern
-
-proc memcmp*#[T](s1, s2: ^const T; n: Word) -> Int
-extern
-
-proc strcmp*(s1: ^const Word8; s2: ^const Word8) -> Int
-extern
-
-proc strncmp*(s1: ^const Word8; s2: ^const Word8; n: Word) -> Int
-extern
-
-proc strncpy*(dst: ^Word8; src: ^const Word8; dsize: Word) -> ^Word8
-extern
-
-proc strcpy*(dst: ^Word8; src: ^const Word8) -> ^Word8
-extern
-
-proc strlen*(ptr: ^const Word8) -> Word
-extern
-
-end.
diff --git a/source/tac.elna b/source/tac.elna
deleted file mode 100644
index 3d65e42..0000000
--- a/source/tac.elna
+++ /dev/null
@@ -1,1074 +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/. *)
-module
-import common, sys.posix.cstdlib, sys.posix.cstdio, sys.posix.cstring, lexer, ast, symbol, diagnostic
-
-type
- ElnaTacOperator* = (
- get_address,
- add,
- load,
- store,
- proc_call,
- copy,
- copy_to_offset,
- copy_from_offset,
- subtract,
- divide,
- remainder,
- multiply,
- _xor,
- _or,
- and,
- less_than,
- greater_than,
- less_or_equal,
- greater_or_equal,
- equal,
- not_equal,
- negate,
- complement,
- jump,
- jump_if_zero,
- jump_if_not_zero,
- label,
- _return,
- add_ptr,
- nop
- )
-
- ElnaTacKind* = (list, label, constant, variable, ignore)
-
- ElnaTacOperand* = record
- kind: ElnaTacKind;
- name: []const Word8;
- constant: Word;
- length: Word;
- list_operands: ^ElnaTacOperand
- end
-
- ElnaTacInstruction* = record(ElnaListNode)
- operator: ElnaTacOperator;
- operands: [4]ElnaTacOperand
- end
-
- ElnaTacProcedure* = record
- next: ^ElnaTacProcedure;
- name: []const Word8;
- body: ElnaList;
- parameters: ^[]const Word8;
- count: Word;
- symbol_table: ^ElnaSymbolTable
- end
-
- ElnaTacStaticVariable* = record
- next: ^ElnaTacStaticVariable;
- name: []const Word8;
- size: Word
- end
-
- ElnaTacStringConstant* = record
- next: ^ElnaTacStringConstant;
- name: []const Word8;
- value: []const Word8
- end
-
- ElnaInstructionModule* = record
- strings: ^ElnaTacStringConstant;
- data: ^ElnaTacStaticVariable;
- code: ^ElnaTacProcedure
- end
-
- ElnaTacOperandType = (plain_object, dereferenced_pointer, sub_object)
-
- ElnaTacOperandResult = record
- kind: ElnaTacOperandType;
- offset: Word
- end
-
-var
- pseudo_counter: Word := 0u
- label_counter: Word := 0u
- string_counter: Word := 0u
- module_strings_first: ^ElnaTacStringConstant := nil
- module_strings_last: ^ElnaTacStringConstant := nil
-
-proc elna_tac_instruction_create*(operator: ElnaTacOperator) -> ^ElnaTacInstruction
-var
- result: ^ElnaTacInstruction
-begin
- result := malloc#[ElnaTacInstruction](#size(ElnaTacInstruction));
- result^.next := nil;
- result^.operator := operator;
- result^.operands[1].kind := ElnaTacKind.ignore;
- result^.operands[2].kind := ElnaTacKind.ignore;
- result^.operands[3].kind := ElnaTacKind.ignore;
- result^.operands[4].kind := ElnaTacKind.ignore
-return result
-
-proc elna_tac_instruction_set_operand*(this: ^ElnaTacInstruction; n: Word;
- kind: ElnaTacKind; name: []const Word8; constant: Word; length: Word)
-begin
- this^.operands[n].kind := kind;
- this^.operands[n].name := name;
- this^.operands[n].constant := constant;
- this^.operands[n].length := length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_instruction_set_op*(this: ^ElnaTacInstruction; n: Word; op: ^ElnaTacOperand)
-begin
- this^.operands[n] := op^
-return
-
-proc elna_tac_instruction_set_const*(this: ^ElnaTacInstruction; n: Word; value: Word; length: Word)
-begin
- this^.operands[n].kind := ElnaTacKind.constant;
- this^.operands[n].name := "";
- this^.operands[n].constant := value;
- this^.operands[n].length := length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_instruction_set_label*(this: ^ElnaTacInstruction; n: Word; label_name: []const Word8)
-begin
- this^.operands[n].kind := ElnaTacKind.label;
- this^.operands[n].name := label_name;
- this^.operands[n].constant := 0u;
- this^.operands[n].length := label_name.length;
- this^.operands[n].list_operands := nil
-return
-
-proc elna_tac_make_variable*(operand: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; variable_type: ^ElnaType)
-var
- buffer: ^Word8
- name_slice: []const Word8
- temporary_info: ^ElnaSymbolTemporaryInfo
- len: Int
-begin
- pseudo_counter := pseudo_counter + 1u;
- buffer := malloc#[Word8](16u);
- len := sprintf(buffer, "t%u\0".ptr, pseudo_counter);
-
- name_slice := buffer[1u to cast(len: Word)];
-
- operand^.kind := ElnaTacKind.variable;
- operand^.name := name_slice;
- operand^.constant := 0u;
- operand^.length := name_slice.length;
- operand^.list_operands := nil;
-
- temporary_info := elna_symbol_temporary_info_create(1u, variable_type);
- elna_symbol_table_enter(symbol_table, name_slice, cast(temporary_info: ^ElnaSymbolInfo))
-return
-
-proc elna_tac_label*() -> []const Word8
-var
- buffer: ^Word8
- result: []const Word8
- len: Int
-begin
- label_counter := label_counter + 1u;
- buffer := malloc#[Word8](16u);
- len := sprintf(buffer, "l%u\0".ptr, label_counter);
- result := buffer[1u to cast(len: Word)]
-return result
-
-proc elna_tac_integer_literal(integer_literal_node: ^ElnaTreeIntegerLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := integer_literal_node^.value;
- operand^.length := word_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- if boolean_literal_node^.value then
- operand^.constant := 1u
- else
- operand^.constant := 0u
- end;
- operand^.length := bool_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_nil_literal(operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := 0u;
- operand^.length := 8u;
- operand^.list_operands := nil
-return
-
-proc elna_tac_character_literal(character_literal_node: ^ElnaTreeCharacterLiteral; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.constant := cast(character_literal_node^.value: Word);
- operand^.length := char_type^.size;
- operand^.list_operands := nil
-return
-
-proc elna_tac_variable_expression(variable_expression: ^ElnaTreeVariableExpression; operand: ^ElnaTacOperand)
-begin
- operand^.kind := ElnaTacKind.variable;
- operand^.name := variable_expression^.name;
- operand^.constant := 0u;
- operand^.length := variable_expression^.name.length;
- operand^.list_operands := nil
-return
-
-proc elna_tac_trait_expression(trait_node: ^ElnaTreeTraitExpression; operand: ^ElnaTacOperand)
-var
- symbol_info: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- parser_node: ^ElnaTreeNamedTypeExpression
-begin
- parser_node := cast(trait_node^.argument: ^ElnaTreeNamedTypeExpression);
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
-
- operand^.kind := ElnaTacKind.constant;
- operand^.name := "";
- operand^.length := 8u;
- operand^.list_operands := nil;
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then
- type_info := cast(symbol_info: ^ElnaSymbolTypeInfo);
- operand^.constant := type_info^._type^.size
- else
- operand^.constant := 0u
- end
-return
-
-proc elna_tac_string_literal(instructions: ^ElnaList; string_literal_node: ^ElnaTreeStringLiteral;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- string_entry: ^ElnaTacStringConstant
- label_buf: ^Word8
- label_slice: []const Word8
- label_len: Int
- instruction: ^ElnaTacInstruction
- address: ElnaTacOperand
-begin
- string_counter := string_counter + 1u;
- label_buf := malloc#[Word8](16u);
- label_len := sprintf(label_buf, "str_%u\0".ptr, string_counter);
- label_slice := label_buf[1u to cast(label_len: Word)];
-
- string_entry := malloc#[ElnaTacStringConstant](#size(ElnaTacStringConstant));
- string_entry^.next := nil;
- string_entry^.name := label_slice;
- string_entry^.value := string_literal_node^.value;
-
- if module_strings_first = nil then
- module_strings_first := string_entry
- else
- module_strings_last^.next := string_entry
- end;
- module_strings_last := string_entry;
-
- elna_tac_make_variable(operand, symbol_table, cast(string_type: ^ElnaType));
- elna_tac_make_variable(@address, symbol_table, pointer_type);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_operand(instruction, 1u, ElnaTacKind.variable, label_slice, 0u, label_slice.length);
- elna_tac_instruction_set_op(instruction, 2u, @address);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_op(instruction, 1u, @address);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_tac_instruction_set_const(instruction, 3u, 0u, 8u);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_const(instruction, 1u, string_literal_node^.value.length, 8u);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_tac_instruction_set_const(instruction, 3u, 8u, 8u);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_copy_address(instructions: ^ElnaList; operand_result: ^ElnaTacOperandResult; from, dest: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
-begin
- if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
- dest^ := from^
- elsif operand_result^.kind = ElnaTacOperandType.sub_object then
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_op(instruction, 1u, from);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add);
- elna_tac_instruction_set_const(instruction, 1u, operand_result^.offset, 4u);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_tac_instruction_set_op(instruction, 3u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
- elna_tac_instruction_set_op(instruction, 1u, from);
- elna_tac_instruction_set_op(instruction, 2u, dest);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- end
-return
-
-proc elna_tac_simple_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-begin
- case parser_node^.kind of
- ElnaTreeKind.integer_literal:
- elna_tac_integer_literal(cast(parser_node: ^ElnaTreeIntegerLiteral), operand)
- | ElnaTreeKind.character_literal:
- elna_tac_character_literal(cast(parser_node: ^ElnaTreeCharacterLiteral), operand)
- | ElnaTreeKind.string_literal:
- elna_tac_string_literal(instructions, cast(parser_node: ^ElnaTreeStringLiteral), symbol_table, operand)
- | ElnaTreeKind.boolean_literal:
- elna_tac_boolean_literal(cast(parser_node: ^ElnaTreeBooleanLiteral), operand)
- | ElnaTreeKind.null:
- elna_tac_nil_literal(operand)
- | ElnaTreeKind.variable_expression:
- elna_tac_variable_expression(cast(parser_node: ^ElnaTreeVariableExpression), operand)
- | ElnaTreeKind.trait_expression:
- elna_tac_trait_expression(cast(parser_node: ^ElnaTreeTraitExpression), operand)
- | ElnaTreeKind._cast:
- elna_tac_binary_expression(instructions, (cast(parser_node: ^ElnaTreeCastExpression))^.expression, symbol_table, operand)
- else
- end
-return
-
-proc elna_tac_unary_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- operator: ElnaLexerKind
- unary_operand: ^ElnaTreeExpression
- unary_node: ^ElnaTreeUnaryExpression
- operand_result: ElnaTacOperandResult
- instruction: ^ElnaTacInstruction
- base: ElnaTacOperand
- has_unary: Bool := false
-begin
- if parser_node^.kind = ElnaTreeKind.unary_expression then
- unary_node := cast(parser_node: ^ElnaTreeUnaryExpression);
- operator := unary_node^.operator;
- unary_operand := unary_node^.operand;
- has_unary := true
- else
- unary_operand := parser_node
- end;
- elna_tac_designator(instructions, unary_operand, symbol_table, @operand_result, @base);
-
- if has_unary & operator = ElnaLexerKind.at then
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_copy_address(instructions, @operand_result, @base, operand)
- elsif has_unary & operator = ElnaLexerKind.minus then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif has_unary & operator = ElnaLexerKind.not then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.complement);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.load);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- elna_tac_make_variable(operand, symbol_table, parser_node^.type_decoration);
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_const(instruction, 2u, operand_result.offset, 4u);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- operand^ := base
- end
-return
-
-proc elna_tac_add_pointer(parser_node: ^ElnaTreeExpression; lhs, rhs: ^ElnaTacOperand;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand) -> ^ElnaTacInstruction
-var
- instruction: ^ElnaTacInstruction
- pointer_type_node: ^ElnaTypePointer
- elem_size: Word := 1u
-begin
- if parser_node^.type_decoration <> nil & parser_node^.type_decoration^.kind = ElnaTypeKind.pointer then
- pointer_type_node := cast(parser_node^.type_decoration: ^ElnaTypePointer);
- if pointer_type_node^.base <> nil then
- elem_size := pointer_type_node^.base^.size
- end
- end;
- instruction := elna_tac_instruction_create(ElnaTacOperator.add_ptr);
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_instruction_set_op(instruction, 1u, lhs);
- elna_tac_instruction_set_op(instruction, 2u, rhs);
- elna_tac_instruction_set_const(instruction, 3u, elem_size, 4u);
- elna_tac_instruction_set_op(instruction, 4u, operand)
-return instruction
-
-proc elna_tac_binary_create(instructions: ^ElnaList; operator: ElnaTacOperator;
- lhs, rhs: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- lhs_symbol: ^ElnaSymbolInfo
- temp_info: ^ElnaSymbolTemporaryInfo
- variable_type: ^ElnaType := word_type
-begin
- if lhs^.kind = ElnaTacKind.variable then
- lhs_symbol := elna_symbol_table_lookup(symbol_table, lhs^.name);
- if lhs_symbol <> nil & lhs_symbol^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(lhs_symbol: ^ElnaSymbolTemporaryInfo);
- variable_type := temp_info^.variable_type
- end
- end;
- elna_tac_make_variable(operand, symbol_table, variable_type);
-
- instruction := elna_tac_instruction_create(operator);
- elna_tac_instruction_set_op(instruction, 1u, lhs);
- elna_tac_instruction_set_op(instruction, 2u, rhs);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_subtract_create(instructions: ^ElnaList; parser_node: ^ElnaTreeBinaryExpression;
- lhs, rhs: ^ElnaTacOperand; symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- lhs_is_pointer: Bool := false
- rhs_is_not_pointer: Bool := true
-begin
- if parser_node^.lhs^.type_decoration <> nil & parser_node^.lhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- lhs_is_pointer := true
- end;
- if parser_node^.rhs^.type_decoration <> nil & parser_node^.rhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- rhs_is_not_pointer := false
- end;
-
- if lhs_is_pointer & rhs_is_not_pointer then
- instruction := elna_tac_instruction_create(ElnaTacOperator.negate);
- elna_tac_instruction_set_op(instruction, 1u, rhs);
- elna_tac_instruction_set_op(instruction, 2u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_add_pointer(parser_node^.lhs, lhs, operand, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- elna_tac_binary_create(instructions, ElnaTacOperator.subtract, lhs, rhs, symbol_table, operand)
- end
-return
-
-proc elna_tac_binary_expression(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- binary_node: ^ElnaTreeBinaryExpression
- instruction: ^ElnaTacInstruction
- lhs: ElnaTacOperand
- rhs: ElnaTacOperand
-begin
- if parser_node^.kind <> ElnaTreeKind.binary_expression then
- elna_tac_unary_expression(instructions, parser_node, symbol_table, operand)
- else
- binary_node := cast(parser_node: ^ElnaTreeBinaryExpression);
- elna_tac_unary_expression(instructions, binary_node^.lhs, symbol_table, @lhs);
- elna_tac_unary_expression(instructions, binary_node^.rhs, symbol_table, @rhs);
-
- case binary_node^.operator of
- ElnaLexerKind.plus:
- if binary_node^.lhs^.type_decoration <> nil & binary_node^.lhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- instruction := elna_tac_add_pointer(binary_node^.lhs, @lhs, @rhs, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif binary_node^.rhs^.type_decoration <> nil & binary_node^.rhs^.type_decoration^.kind = ElnaTypeKind.pointer then
- instruction := elna_tac_add_pointer(binary_node^.rhs, @rhs, @lhs, symbol_table, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- else
- elna_tac_binary_create(instructions, ElnaTacOperator.add, @lhs, @rhs, symbol_table, operand)
- end
- | ElnaLexerKind.minus:
- elna_tac_subtract_create(instructions, binary_node, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.multiplication:
- elna_tac_binary_create(instructions, ElnaTacOperator.multiply, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.division:
- elna_tac_binary_create(instructions, ElnaTacOperator.divide, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.remainder:
- elna_tac_binary_create(instructions, ElnaTacOperator.remainder, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.and:
- elna_tac_binary_create(instructions, ElnaTacOperator.and, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind._or:
- elna_tac_binary_create(instructions, ElnaTacOperator._or, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind._xor:
- elna_tac_binary_create(instructions, ElnaTacOperator._xor, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.equals:
- elna_tac_binary_create(instructions, ElnaTacOperator.equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.not_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.not_equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.less_than:
- elna_tac_binary_create(instructions, ElnaTacOperator.less_than, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.greater_than:
- elna_tac_binary_create(instructions, ElnaTacOperator.greater_than, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.less_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.less_or_equal, @lhs, @rhs, symbol_table, operand)
- | ElnaLexerKind.greater_equal:
- elna_tac_binary_create(instructions, ElnaTacOperator.greater_or_equal, @lhs, @rhs, symbol_table, operand)
- else
- end
- end
-return
-
-proc elna_tac_call(instructions: ^ElnaList; parsed_call: ^ElnaTreeCall; symbol_table: ^ElnaSymbolTable;
- operand: ^ElnaTacOperand)
-var
- parsed_expression: ^ElnaTreeVariableExpression
- arguments_operand: ^ElnaTacOperand
- call_instruction: ^ElnaTacInstruction
- argument_entry: ^ElnaTreeExpressionList
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
- i: Word := 0u
-begin
- parsed_expression := parsed_call^.callee;
- arguments_operand := malloc#[ElnaTacOperand](parsed_call^.count * #size(ElnaTacOperand));
- symbol_info := elna_symbol_table_lookup(symbol_table, parsed_expression^.name);
-
- call_instruction := elna_tac_instruction_create(ElnaTacOperator.proc_call);
- elna_tac_instruction_set_label(call_instruction, 1u, parsed_expression^.name);
-
- call_instruction^.operands[2].kind := ElnaTacKind.list;
- call_instruction^.operands[2].list_operands := arguments_operand;
- call_instruction^.operands[2].length := parsed_call^.count;
-
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- if procedure_info^.procedure_type^.return_type = nil then
- call_instruction^.operands[3].kind := ElnaTacKind.ignore
- else
- elna_tac_make_variable(operand, symbol_table, procedure_info^.procedure_type^.return_type);
- elna_tac_instruction_set_op(call_instruction, 3u, operand)
- end
- else
- call_instruction^.operands[3].kind := ElnaTacKind.ignore
- end;
-
- argument_entry := parsed_call^.arguments;
- while argument_entry <> nil & i < parsed_call^.count do
- elna_tac_binary_expression(instructions, argument_entry^.expression, symbol_table, arguments_operand + i);
- argument_entry := argument_entry^.next;
- i := i + 1u
- end;
- elna_list_append(instructions, cast(call_instruction: ^ElnaListNode))
-return
-
-proc elna_tac_goto_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeGotoStatement)
-var
- instruction: ^ElnaTacInstruction
-begin
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
- elna_tac_instruction_set_label(instruction, 1u, parser_node^.label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_label_declaration(instructions: ^ElnaList; parser_node: ^ElnaTreeLabelDeclaration)
-var
- result: ^ElnaTacInstruction
-begin
- result := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(result, 1u, parser_node^.label);
- elna_list_append(instructions, cast(result: ^ElnaListNode))
-return
-
-proc elna_tac_enumeration_value(field_access_expression: ^ElnaTreeFieldAccessExpression; operand: ^ElnaTacOperand)
-var
- enumeration_type: ^ElnaTypeEnumeration
- members: ^[]const Word8
- members_length: Word
- symbol_info: ^ElnaSymbolInfo
- type_info: ^ElnaSymbolTypeInfo
- counter: Word := 1u
- found: Bool := false
- aggregate_tree: ^ElnaTreeVariableExpression
-begin
- aggregate_tree := cast(field_access_expression^.aggregate: ^ElnaTreeVariableExpression);
- symbol_info := elna_symbol_table_lookup(symbol_table_global, aggregate_tree^.name);
-
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then
- type_info := cast(symbol_info: ^ElnaSymbolTypeInfo);
- if type_info^._type^.kind = ElnaTypeKind.enumeration then
- enumeration_type := cast(type_info^._type: ^ElnaTypeEnumeration);
- members := enumeration_type^.members;
- members_length := enumeration_type^.length;
-
- while members_length > 0u & ~found do
- if members^ = field_access_expression^.field then
- found := true;
- operand^.kind := ElnaTacKind.constant;
- operand^.constant := counter;
- operand^.length := 4u;
- operand^.name := "";
- operand^.list_operands := nil
- else
- members_length := members_length - 1u;
- members := members + 1u;
- counter := counter + 1u
- end
- end
- end
- end
-return
-
-proc elna_tac_dereference_expression(instructions: ^ElnaList; dereference_expression: ^ElnaTreeDereferenceExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- load_instruction: ^ElnaTacInstruction
- operand_result: ElnaTacOperandResult
- intermediate: ElnaTacOperand
-begin
- elna_tac_designator(instructions, dereference_expression^.pointer, symbol_table, @operand_result, operand);
-
- if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- intermediate := operand^;
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- load_instruction := elna_tac_instruction_create(ElnaTacOperator.load);
- elna_tac_instruction_set_op(load_instruction, 1u, @intermediate);
- elna_tac_instruction_set_op(load_instruction, 2u, operand);
- elna_list_append(instructions, cast(load_instruction: ^ElnaListNode))
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- intermediate := operand^;
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- load_instruction := elna_tac_instruction_create(ElnaTacOperator.copy_from_offset);
- elna_tac_instruction_set_op(load_instruction, 1u, @intermediate);
- elna_tac_instruction_set_const(load_instruction, 2u, operand_result.offset, 4u);
- elna_tac_instruction_set_op(load_instruction, 3u, operand);
- elna_list_append(instructions, cast(load_instruction: ^ElnaListNode))
- end
-return
-
-proc elna_tac_field_access_expression(instructions: ^ElnaList; field_access_expression: ^ElnaTreeFieldAccessExpression;
- symbol_table: ^ElnaSymbolTable; operand_result: ^ElnaTacOperandResult; operand: ^ElnaTacOperand)
-var
- field_type: ^ElnaType
- instruction: ^ElnaTacInstruction
- designator_base: ^ElnaTreeExpression
- aggregate_type: ^ElnaTypeRecord
- field_count: Word
- current_field: ^ElnaTypeField
- field_offset: Word := 0u
- base: ElnaTacOperand
- found: Bool := false
-begin
- designator_base := field_access_expression^.aggregate;
- aggregate_type := cast(designator_base^.type_decoration: ^ElnaTypeRecord);
-
- elna_tac_designator(instructions, designator_base, symbol_table, operand_result, @base);
-
- if aggregate_type <> nil & aggregate_type^.kind = ElnaTypeKind._record then
- field_count := aggregate_type^.length;
- current_field := aggregate_type^.members;
-
- while field_count > 0u & ~found do
- if current_field^.name = field_access_expression^.field then
- found := true
- else
- field_type := current_field^.field_type;
- field_count := field_count - 1u;
- field_offset := field_offset + field_type^.size;
- current_field := current_field + 1u
- end
- end
- end;
-
- if operand_result^.kind = ElnaTacOperandType.dereferenced_pointer then
- elna_tac_make_variable(operand, symbol_table, word_type);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add);
- elna_tac_instruction_set_op(instruction, 1u, @base);
- elna_tac_instruction_set_const(instruction, 2u, field_offset, 4u);
- elna_tac_instruction_set_op(instruction, 3u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
- elsif operand_result^.kind = ElnaTacOperandType.sub_object then
- operand^ := base;
- operand_result^.offset := operand_result^.offset + field_offset
- else
- operand^ := base;
- operand_result^.kind := ElnaTacOperandType.sub_object;
- operand_result^.offset := field_offset
- end
-return
-
-proc elna_tac_array_access_expression(instructions: ^ElnaList; array_access_expression: ^ElnaTreeArrayAccessExpression;
- symbol_table: ^ElnaSymbolTable; operand: ^ElnaTacOperand)
-var
- instruction: ^ElnaTacInstruction
- operand_result: ElnaTacOperandResult
- inter_operand: ElnaTacOperand
- index_operand: ElnaTacOperand
- aggregate_type: ^ElnaTypeArray
- designator_base: ^ElnaTreeExpression
- element_type: ^ElnaType
- elem_size: Word := 1u
-begin
- designator_base := array_access_expression^.array;
- if designator_base^.type_decoration <> nil & designator_base^.type_decoration^.kind = ElnaTypeKind.array then
- aggregate_type := cast(designator_base^.type_decoration: ^ElnaTypeArray);
- element_type := aggregate_type^.base;
- if element_type <> nil then
- elem_size := element_type^.size
- end
- end;
-
- elna_tac_binary_expression(instructions, array_access_expression^.index, symbol_table, @inter_operand);
- elna_tac_make_variable(@index_operand, symbol_table, word_type);
-
- (* In Elna arrays are 1-based, subtract 1 for 0-based index *)
- instruction := elna_tac_instruction_create(ElnaTacOperator.subtract);
- elna_tac_instruction_set_op(instruction, 1u, @inter_operand);
- elna_tac_instruction_set_const(instruction, 2u, 1u, 4u);
- elna_tac_instruction_set_op(instruction, 3u, @index_operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- elna_tac_designator(instructions, array_access_expression^.array,
- symbol_table, @operand_result, @inter_operand);
- elna_tac_make_variable(operand, symbol_table, word_type);
- elna_tac_copy_address(instructions, @operand_result, @inter_operand, operand);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.add_ptr);
- elna_tac_instruction_set_op(instruction, 1u, operand);
- elna_tac_instruction_set_op(instruction, 2u, @index_operand);
- elna_tac_instruction_set_const(instruction, 3u, elem_size, 4u);
- elna_tac_instruction_set_op(instruction, 4u, operand);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_designator(instructions: ^ElnaList; parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- operand_result: ^ElnaTacOperandResult; operand: ^ElnaTacOperand)
-var
- field_access_expression: ^ElnaTreeFieldAccessExpression
- designator_base: ^ElnaTreeExpression
-begin
- operand_result^.kind := ElnaTacOperandType.plain_object;
- operand_result^.offset := 0u;
-
- case parser_node^.kind of
- ElnaTreeKind.dereference_expression:
- elna_tac_dereference_expression(instructions, cast(parser_node: ^ElnaTreeDereferenceExpression), symbol_table, operand);
- operand_result^.kind := ElnaTacOperandType.dereferenced_pointer
- | ElnaTreeKind.field_access_expression:
- field_access_expression := cast(parser_node: ^ElnaTreeFieldAccessExpression);
- designator_base := field_access_expression^.aggregate;
-
- if designator_base^.type_decoration = nil then
- elna_tac_enumeration_value(field_access_expression, operand)
- else
- elna_tac_field_access_expression(instructions, field_access_expression, symbol_table, operand_result, operand)
- end
- | ElnaTreeKind.array_access_expression:
- elna_tac_array_access_expression(instructions, cast(parser_node: ^ElnaTreeArrayAccessExpression), symbol_table, operand);
- operand_result^.kind := ElnaTacOperandType.dereferenced_pointer
- | ElnaTreeKind.call:
- elna_tac_call(instructions, cast(parser_node: ^ElnaTreeCall), symbol_table, operand)
- else
- elna_tac_simple_expression(instructions, parser_node, symbol_table, operand)
- end
-return
-
-proc elna_tac_assign_statement(instructions: ^ElnaList; parser_tree: ^ElnaTreeAssignStatement; symbol_table: ^ElnaSymbolTable)
-var
- operand_result: ElnaTacOperandResult
- instruction: ^ElnaTacInstruction
- assignment_operand: ElnaTacOperand
- assignee: ElnaTacOperand
-begin
- elna_tac_designator(instructions, parser_tree^.assignee, symbol_table, @operand_result, @assignee);
- elna_tac_binary_expression(instructions, parser_tree^.assignment, symbol_table, @assignment_operand);
-
- if operand_result.kind = ElnaTacOperandType.dereferenced_pointer then
- instruction := elna_tac_instruction_create(ElnaTacOperator.store);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee)
- elsif operand_result.kind = ElnaTacOperandType.sub_object then
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy_to_offset);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee);
- elna_tac_instruction_set_const(instruction, 3u, operand_result.offset, 4u)
- else
- instruction := elna_tac_instruction_create(ElnaTacOperator.copy);
- elna_tac_instruction_set_op(instruction, 1u, @assignment_operand);
- elna_tac_instruction_set_op(instruction, 2u, @assignee)
- end;
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_return_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeReturnStatement; symbol_table: ^ElnaSymbolTable)
-var
- instruction: ^ElnaTacInstruction
- operand: ElnaTacOperand
-begin
- instruction := elna_tac_instruction_create(ElnaTacOperator._return);
- if parser_node^.returned <> nil then
- elna_tac_binary_expression(instructions, parser_node^.returned, symbol_table, @operand);
- elna_tac_instruction_set_op(instruction, 1u, @operand)
- else
- instruction^.operands[1].kind := ElnaTacKind.ignore
- end;
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_conditional_statements(instructions: ^ElnaList; parser_node: ^ElnaTreeConditionalStatements;
- after_end_label: []const Word8; symbol_table: ^ElnaSymbolTable)
-var
- condition_label: []const Word8
- instruction: ^ElnaTacInstruction
- operand: ElnaTacOperand
-begin
- elna_tac_binary_expression(instructions, parser_node^.condition, symbol_table, @operand);
- condition_label := elna_tac_label();
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump_if_zero);
- elna_tac_instruction_set_op(instruction, 1u, @operand);
- elna_tac_instruction_set_label(instruction, 2u, condition_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- elna_tac_statements(instructions, parser_node^.statements, symbol_table);
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.jump);
- elna_tac_instruction_set_label(instruction, 1u, after_end_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode));
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(instruction, 1u, condition_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_if_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeIfStatement; symbol_table: ^ElnaSymbolTable)
-var
- current_node: ^ElnaTreeConditionalStatements
- after_end_label: []const Word8
- instruction: ^ElnaTacInstruction
-begin
- after_end_label := elna_tac_label();
- current_node := parser_node^.conditionals;
-
- while current_node <> nil do
- elna_tac_conditional_statements(instructions, current_node, after_end_label, symbol_table);
- current_node := current_node^.next
- end;
-
- if parser_node^._else <> nil then
- elna_tac_statements(instructions, parser_node^._else, symbol_table)
- end;
-
- instruction := elna_tac_instruction_create(ElnaTacOperator.label);
- elna_tac_instruction_set_label(instruction, 1u, after_end_label);
- elna_list_append(instructions, cast(instruction: ^ElnaListNode))
-return
-
-proc elna_tac_statement(instructions: ^ElnaList; parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable)
-var
- operand: ElnaTacOperand
- call_statement: ^ElnaTreeCallStatement
-begin
- case parser_node^.kind of
- ElnaTreeKind.goto_statement:
- elna_tac_goto_statement(instructions, cast(parser_node: ^ElnaTreeGotoStatement))
- | ElnaTreeKind.if_statement:
- elna_tac_if_statement(instructions, cast(parser_node: ^ElnaTreeIfStatement), symbol_table)
- | ElnaTreeKind.return_statement:
- elna_tac_return_statement(instructions, cast(parser_node: ^ElnaTreeReturnStatement), symbol_table)
- | ElnaTreeKind.label_declaration:
- elna_tac_label_declaration(instructions, cast(parser_node: ^ElnaTreeLabelDeclaration))
- | ElnaTreeKind.call_statement:
- call_statement := cast(parser_node: ^ElnaTreeCallStatement);
- elna_tac_call(instructions, call_statement^.call, symbol_table, @operand)
- | ElnaTreeKind.assign_statement:
- elna_tac_assign_statement(instructions, cast(parser_node: ^ElnaTreeAssignStatement), symbol_table)
- else
- end
-return
-
-proc elna_tac_statements(instructions: ^ElnaList; current_statement: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable)
-var
- current: ^ElnaTreeStatement
-begin
- current := current_statement;
- while current <> nil do
- elna_tac_statement(instructions, current, symbol_table);
- current := current^.next
- end
-return
-
-proc elna_tac_parameters(ast_list: ^ElnaTreeDeclaration; parameter_count: ^Word) -> ^[]const Word8
-var
- ast_parameter: ^ElnaTreeDeclaration
- parameter_list: ^[]const Word8
- count: Word := 0u
- i: Word := 0u
-begin
- ast_parameter := ast_list;
- while ast_parameter <> nil do
- count := count + 1u;
- ast_parameter := ast_parameter^.next
- end;
- parameter_count^ := count;
-
- parameter_list := malloc#[[]const Word8](count * #size([]const Word8));
- ast_parameter := ast_list;
- while i < count do
- (parameter_list + i)^ := ast_parameter^.name;
- i := i + 1u;
- ast_parameter := ast_parameter^.next
- end
-return parameter_list
-
-proc elna_tac_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration) -> ^ElnaTacProcedure
-var
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
- result: ^ElnaTacProcedure
- parameter_count: Word := 0u
-begin
- result := malloc#[ElnaTacProcedure](#size(ElnaTacProcedure));
- result^.next := nil;
- elna_list_initialize(@result^.body);
- result^.name := parser_node^.name;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- result^.symbol_table := procedure_info^.symbol_table
- else
- result^.symbol_table := symbol_table_global
- end;
-
- result^.parameters := elna_tac_parameters(parser_node^.parameters, @parameter_count);
- result^.count := parameter_count;
- pseudo_counter := 0u;
-
- elna_tac_statements(@result^.body, parser_node^.body, result^.symbol_table)
-return result
-
-proc elna_tac_procedures(parser_node: ^ElnaTreeProcedureDeclaration) -> ^ElnaTacProcedure
-var
- result: ^ElnaTacProcedure
- current_procedure: ^ElnaTacProcedure := nil
- first_procedure: ^ElnaTacProcedure := nil
- current_node: ^ElnaTreeProcedureDeclaration
-begin
- current_node := parser_node;
- while current_node <> nil do
- if ~current_node^.is_extern then
- result := elna_tac_procedure_declaration(current_node);
- if first_procedure = nil then
- first_procedure := result
- else
- current_procedure^.next := result
- end;
- current_procedure := result
- end;
- current_node := cast(current_node^.next: ^ElnaTreeProcedureDeclaration)
- end
-return first_procedure
-
-proc elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration) -> ^ElnaTacStaticVariable
-var
- result: ^ElnaTacStaticVariable
- symbol_info: ^ElnaSymbolInfo
- temp_info: ^ElnaSymbolTemporaryInfo
-begin
- result := malloc#[ElnaTacStaticVariable](#size(ElnaTacStaticVariable));
- result^.next := nil;
- result^.name := parser_tree^.name;
- result^.size := 4u;
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_tree^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.temporary_info then
- temp_info := cast(symbol_info: ^ElnaSymbolTemporaryInfo);
- if temp_info^.variable_type <> nil then
- result^.size := temp_info^.variable_type^.size
- end
- end
-return result
-
-proc elna_tac_var_part(parser_node: ^ElnaTreeDeclaration) -> ^ElnaTacStaticVariable
-var
- node: ^ElnaTacStaticVariable
- current_variable: ^ElnaTacStaticVariable := nil
- first_variable: ^ElnaTacStaticVariable := nil
- current_node: ^ElnaTreeDeclaration
-begin
- current_node := parser_node;
- while current_node <> nil do
- node := elna_tac_variable_declaration(cast(current_node: ^ElnaTreeVariableDeclaration));
- if first_variable = nil then
- first_variable := node
- else
- current_variable^.next := node
- end;
- current_variable := node;
- current_node := current_node^.next
- end
-return first_variable
-
-proc elna_tac_program_body(parser_node: ^ElnaTreeStatement) -> ^ElnaTacProcedure
-var
- result: ^ElnaTacProcedure
- symbol_info: ^ElnaSymbolInfo
- procedure_info: ^ElnaSymbolProcedureInfo
-begin
- result := malloc#[ElnaTacProcedure](#size(ElnaTacProcedure));
- result^.next := nil;
- elna_list_initialize(@result^.body);
- result^.name := "main";
-
- symbol_info := elna_symbol_table_lookup(symbol_table_global, result^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- result^.symbol_table := procedure_info^.symbol_table
- else
- result^.symbol_table := symbol_table_global
- end;
-
- result^.parameters := nil;
- result^.count := 0u;
- pseudo_counter := 0u;
-
- elna_tac_statements(@result^.body, parser_node, result^.symbol_table)
-return result
-
-proc elna_tac_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration) -> ^ElnaInstructionModule
-var
- result: ^ElnaInstructionModule
- last_proc: ^ElnaTacProcedure
- body_proc: ^ElnaTacProcedure
-begin
- result := malloc#[ElnaInstructionModule](#size(ElnaInstructionModule));
- result^.strings := module_strings_first;
- result^.data := elna_tac_var_part(parser_node^.globals);
- result^.code := elna_tac_procedures(parser_node^.procedures);
-
- if parser_node^.body <> nil then
- body_proc := elna_tac_program_body(parser_node^.body);
- if result^.code = nil then
- result^.code := body_proc
- else
- last_proc := result^.code;
- while last_proc^.next <> nil do
- last_proc := last_proc^.next
- end;
- last_proc^.next := body_proc
- end
- end;
- result^.strings := module_strings_first
-return result
-
-end.
diff --git a/source/type_check.elna b/source/type_check.elna
deleted file mode 100644
index 8edc30d..0000000
--- a/source/type_check.elna
+++ /dev/null
@@ -1,315 +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/. *)
-module
-import common, lexer, ast, symbol, diagnostic
-
-proc elna_type_is_aggregate*(_type: ^ElnaType) -> Bool
-var
- result: Bool := false
-begin
- if _type <> nil then
- result := _type^.kind = ElnaTypeKind._record or _type^.kind = ElnaTypeKind.array
- end
-return result
-
-proc elna_type_character_literal(parser_node: ^ElnaTreeCharacterLiteral)
-begin
- parser_node^.type_decoration := char_type
-return
-
-proc elna_type_integer_literal(parser_node: ^ElnaTreeIntegerLiteral)
-begin
- parser_node^.type_decoration := word_type
-return
-
-proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral)
-begin
- parser_node^.type_decoration := cast(string_type: ^ElnaType)
-return
-
-proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral)
-begin
- parser_node^.type_decoration := bool_type
-return
-
-proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral)
-begin
- parser_node^.type_decoration := pointer_type
-return
-
-proc elna_type_variable_expression(parser_node: ^ElnaTreeVariableExpression; symbol_table: ^ElnaSymbolTable)
-var
- variable_info: ^ElnaSymbolInfo
- temporary_info: ^ElnaSymbolTemporaryInfo
- procedure_info: ^ElnaSymbolProcedureInfo
-begin
- variable_info := elna_symbol_table_lookup(symbol_table, parser_node^.name);
- if variable_info <> nil then
- if variable_info^.kind = ElnaSymbolInfoKind.temporary_info then
- temporary_info := cast(variable_info: ^ElnaSymbolTemporaryInfo);
- parser_node^.type_decoration := temporary_info^.variable_type
- elsif variable_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(variable_info: ^ElnaSymbolProcedureInfo);
- parser_node^.type_decoration := cast(procedure_info^.procedure_type: ^ElnaType)
- end
- end
-return
-
-proc elna_type_cast_expression(parser_node: ^ElnaTreeCastExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_type_binary_expression(parser_node^.expression, symbol_table, error_list)
-return
-
-proc elna_type_call(parser_node: ^ElnaTreeCall; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-var
- argument_tree: ^ElnaTreeExpressionList
- procedure_type: ^ElnaTypeProcedure
-begin
- argument_tree := parser_node^.arguments;
-
- elna_type_variable_expression(parser_node^.callee, symbol_table);
- if parser_node^.callee^.type_decoration <> nil & parser_node^.callee^.type_decoration^.kind = ElnaTypeKind.procedure then
- procedure_type := cast(parser_node^.callee^.type_decoration: ^ElnaTypeProcedure);
- parser_node^.type_decoration := procedure_type^.return_type
- end;
-
- while argument_tree <> nil do
- elna_type_binary_expression(argument_tree^.expression, symbol_table, error_list);
- argument_tree := argument_tree^.next
- end
-return
-
-proc elna_type_dereference_expression(parser_node: ^ElnaTreeDereferenceExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- base_type: ^ElnaType := nil
- pointer_type_node: ^ElnaTypePointer
-begin
- elna_type_designator(parser_node^.pointer, symbol_table, error_list);
-
- if parser_node^.pointer^.type_decoration <> nil then
- base_type := parser_node^.pointer^.type_decoration;
- if base_type^.kind = ElnaTypeKind.pointer then
- pointer_type_node := cast(base_type: ^ElnaTypePointer);
- base_type := pointer_type_node^.base
- end
- end;
- parser_node^.type_decoration := base_type
-return
-
-proc elna_type_field_access_expression(parser_node: ^ElnaTreeFieldAccessExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- variable_expression: ^ElnaTreeVariableExpression
- base_type: ^ElnaType := nil
- type_kind: ^ElnaSymbolTypeInfo
- symbol_info: ^ElnaSymbolInfo
- aggregate_type: ^ElnaTypeRecord
- field_count: Word
- current_field: ^ElnaTypeField
-begin
- if parser_node^.aggregate^.kind = ElnaTreeKind.variable_expression then
- variable_expression := cast(parser_node^.aggregate: ^ElnaTreeVariableExpression);
- symbol_info := elna_symbol_table_lookup(symbol_table_global, variable_expression^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.type_info then
- type_kind := cast(symbol_info: ^ElnaSymbolTypeInfo);
- base_type := type_kind^._type
- end
- end;
-
- if base_type = nil then
- elna_type_designator(parser_node^.aggregate, symbol_table, error_list);
- if parser_node^.aggregate^.type_decoration <> nil & parser_node^.aggregate^.type_decoration^.kind = ElnaTypeKind._record then
- aggregate_type := cast(parser_node^.aggregate^.type_decoration: ^ElnaTypeRecord);
- field_count := aggregate_type^.length;
- current_field := aggregate_type^.members;
-
- while field_count > 0u & base_type = nil do
- if current_field^.name = parser_node^.field then
- base_type := current_field^.field_type
- else
- field_count := field_count - 1u;
- current_field := current_field + 1u
- end
- end
- end
- end;
-
- parser_node^.type_decoration := base_type
-return
-
-proc elna_type_array_access_expression(parser_node: ^ElnaTreeArrayAccessExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- aggregate_type: ^ElnaTypeArray
-begin
- elna_type_designator(parser_node^.array, symbol_table, error_list);
- elna_type_binary_expression(parser_node^.index, symbol_table, error_list);
-
- if parser_node^.array^.type_decoration <> nil & parser_node^.array^.type_decoration^.kind = ElnaTypeKind.array then
- aggregate_type := cast(parser_node^.array^.type_decoration: ^ElnaTypeArray);
- parser_node^.type_decoration := aggregate_type^.base
- end
-return
-
-proc elna_type_simple_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-begin
- case parser_node^.kind of
- ElnaTreeKind.integer_literal:
- elna_type_integer_literal(cast(parser_node: ^ElnaTreeIntegerLiteral))
- | ElnaTreeKind.character_literal:
- elna_type_character_literal(cast(parser_node: ^ElnaTreeCharacterLiteral))
- | ElnaTreeKind.string_literal:
- elna_type_string_literal(cast(parser_node: ^ElnaTreeStringLiteral))
- | ElnaTreeKind.boolean_literal:
- elna_type_boolean_literal(cast(parser_node: ^ElnaTreeBooleanLiteral))
- | ElnaTreeKind.null:
- elna_type_nil_literal(cast(parser_node: ^ElnaTreeNilLiteral))
- | ElnaTreeKind._cast:
- elna_type_cast_expression(cast(parser_node: ^ElnaTreeCastExpression), symbol_table, error_list)
- | ElnaTreeKind.variable_expression:
- elna_type_variable_expression(cast(parser_node: ^ElnaTreeVariableExpression), symbol_table)
- else
- end
-return
-
-proc elna_type_designator(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-begin
- case parser_node^.kind of
- ElnaTreeKind.dereference_expression:
- elna_type_dereference_expression(cast(parser_node: ^ElnaTreeDereferenceExpression), symbol_table, error_list)
- | ElnaTreeKind.field_access_expression:
- elna_type_field_access_expression(cast(parser_node: ^ElnaTreeFieldAccessExpression), symbol_table, error_list)
- | ElnaTreeKind.array_access_expression:
- elna_type_array_access_expression(cast(parser_node: ^ElnaTreeArrayAccessExpression), symbol_table, error_list)
- | ElnaTreeKind.call:
- elna_type_call(cast(parser_node: ^ElnaTreeCall), symbol_table, error_list)
- else
- elna_type_simple_expression(parser_node, symbol_table, error_list)
- end
-return
-
-proc elna_type_unary_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- unary_node: ^ElnaTreeUnaryExpression
-begin
- if parser_node^.kind = ElnaTreeKind.unary_expression then
- unary_node := cast(parser_node: ^ElnaTreeUnaryExpression);
- elna_type_designator(unary_node^.operand, symbol_table, error_list);
- parser_node^.type_decoration := unary_node^.operand^.type_decoration
- else
- elna_type_designator(parser_node, symbol_table, error_list)
- end
-return
-
-proc elna_type_binary_expression(parser_node: ^ElnaTreeExpression; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- binary_node: ^ElnaTreeBinaryExpression
-begin
- if parser_node <> nil then
- if parser_node^.kind = ElnaTreeKind.binary_expression then
- binary_node := cast(parser_node: ^ElnaTreeBinaryExpression);
- elna_type_unary_expression(binary_node^.rhs, symbol_table, error_list);
- elna_type_unary_expression(binary_node^.lhs, symbol_table, error_list);
- parser_node^.type_decoration := binary_node^.lhs^.type_decoration
- else
- elna_type_unary_expression(parser_node, symbol_table, error_list)
- end
- end
-return
-
-proc elna_type_assign_statement(parser_node: ^ElnaTreeAssignStatement; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-begin
- elna_type_designator(parser_node^.assignee, symbol_table, error_list);
- elna_type_binary_expression(parser_node^.assignment, symbol_table, error_list)
-return
-
-proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements; symbol_table: ^ElnaSymbolTable;
- error_list: ^ElnaList)
-var
- current: ^ElnaTreeConditionalStatements
-begin
- current := parser_node;
- while current <> nil do
- elna_type_binary_expression(current^.condition, symbol_table, error_list);
- elna_type_statements(current^.statements, symbol_table, error_list);
- current := current^.next
- end
-return
-
-proc elna_type_if_statement(parser_node: ^ElnaTreeIfStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-begin
- elna_type_conditional_statements(parser_node^.conditionals, symbol_table, error_list);
- if parser_node^._else <> nil then
- elna_type_statements(parser_node^._else, symbol_table, error_list)
- end
-return
-
-proc elna_type_return_statement(parser_node: ^ElnaTreeReturnStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-begin
- if parser_node^.returned <> nil then
- elna_type_binary_expression(parser_node^.returned, symbol_table, error_list)
- end
-return
-
-proc elna_type_statement(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-var
- call_statement: ^ElnaTreeCallStatement
-begin
- case parser_node^.kind of
- ElnaTreeKind.if_statement:
- elna_type_if_statement(cast(parser_node: ^ElnaTreeIfStatement), symbol_table, error_list)
- | ElnaTreeKind.return_statement:
- elna_type_return_statement(cast(parser_node: ^ElnaTreeReturnStatement), symbol_table, error_list)
- | ElnaTreeKind.call_statement:
- call_statement := cast(parser_node: ^ElnaTreeCallStatement);
- elna_type_call(call_statement^.call, symbol_table, error_list)
- | ElnaTreeKind.assign_statement:
- elna_type_assign_statement(cast(parser_node: ^ElnaTreeAssignStatement), symbol_table, error_list)
- else
- end
-return
-
-proc elna_type_statements(parser_node: ^ElnaTreeStatement; symbol_table: ^ElnaSymbolTable; error_list: ^ElnaList)
-var
- current: ^ElnaTreeStatement
-begin
- current := parser_node;
- while current <> nil do
- elna_type_statement(current, symbol_table, error_list);
- current := current^.next
- end
-return
-
-proc elna_type_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration; error_list: ^ElnaList)
-var
- procedure_info: ^ElnaSymbolProcedureInfo
- symbol_info: ^ElnaSymbolInfo
-begin
- symbol_info := elna_symbol_table_lookup(symbol_table_global, parser_node^.name);
- if symbol_info <> nil & symbol_info^.kind = ElnaSymbolInfoKind.procedure_info then
- procedure_info := cast(symbol_info: ^ElnaSymbolProcedureInfo);
- elna_type_statements(parser_node^.body, procedure_info^.symbol_table, error_list)
- end
-return
-
-proc elna_type_module_declaration*(parser_node: ^ElnaTreeModuleDeclaration; error_list: ^ElnaList)
-var
- current_proc: ^ElnaTreeProcedureDeclaration
-begin
- current_proc := parser_node^.procedures;
- while current_proc <> nil do
- elna_type_procedure_declaration(current_proc, error_list);
- current_proc := cast(current_proc^.next: ^ElnaTreeProcedureDeclaration)
- end;
- if parser_node^.body <> nil then
- elna_type_statements(parser_node^.body, symbol_table_global, error_list)
- end
-return
-
-end.