(* 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.