forked from cosmonaut/wraith-lang
				
			Compare commits
	
		
			25 Commits 
		
	
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 9adfaed54c | |
|  | a571edcf6d | |
|  | ea203e6c3c | |
|  | 61344f5b60 | |
|  | 506ee9ecad | |
|  | d9b01515eb | |
|  | 473b706ad9 | |
|  | 876e8deb6e | |
|  | 459a1dd3b7 | |
|  | abc82f381e | |
|  | 41bf2bece8 | |
|  | f441e5bede | |
|  | 32541d4794 | |
|  | aa2449f7df | |
|  | 252dc9b87f | |
|  | 743828450c | |
|  | 5ab3cc533d | |
|  | e2bca66dc4 | |
|  | fddacae487 | |
|  | 71ba1f9454 | |
|  | 565d815deb | |
|  | 8f86392cf3 | |
|  | 27587d1fb0 | |
|  | aeb36f9540 | |
|  | 6ec5479db1 | 
|  | @ -0,0 +1,166 @@ | |||
| --- | ||||
| Language:        Cpp | ||||
| # BasedOnStyle:  LLVM | ||||
| AccessModifierOffset: -2 | ||||
| AlignAfterOpenBracket: AlwaysBreak | ||||
| AlignConsecutiveMacros: None | ||||
| AlignConsecutiveAssignments: None | ||||
| AlignConsecutiveBitFields: None | ||||
| AlignConsecutiveDeclarations: None | ||||
| AlignEscapedNewlines: Right | ||||
| AlignOperands:   Align | ||||
| AlignTrailingComments: true | ||||
| AllowAllArgumentsOnNextLine: false | ||||
| AllowAllConstructorInitializersOnNextLine: true | ||||
| AllowAllParametersOfDeclarationOnNextLine: false | ||||
| AllowShortEnumsOnASingleLine: true | ||||
| AllowShortBlocksOnASingleLine: Never | ||||
| AllowShortCaseLabelsOnASingleLine: false | ||||
| AllowShortFunctionsOnASingleLine: All | ||||
| AllowShortLambdasOnASingleLine: All | ||||
| AllowShortIfStatementsOnASingleLine: Never | ||||
| AllowShortLoopsOnASingleLine: false | ||||
| AlwaysBreakAfterDefinitionReturnType: None | ||||
| AlwaysBreakAfterReturnType: None | ||||
| AlwaysBreakBeforeMultilineStrings: false | ||||
| AlwaysBreakTemplateDeclarations: MultiLine | ||||
| AttributeMacros: | ||||
|   - __capability | ||||
| BinPackArguments: false | ||||
| BinPackParameters: false | ||||
| BraceWrapping: | ||||
|   AfterCaseLabel:  false | ||||
|   AfterClass:      false | ||||
|   AfterControlStatement: Never | ||||
|   AfterEnum:       false | ||||
|   AfterFunction:   false | ||||
|   AfterNamespace:  false | ||||
|   AfterObjCDeclaration: false | ||||
|   AfterStruct:     false | ||||
|   AfterUnion:      false | ||||
|   AfterExternBlock: false | ||||
|   BeforeCatch:     false | ||||
|   BeforeElse:      false | ||||
|   BeforeLambdaBody: false | ||||
|   BeforeWhile:     false | ||||
|   IndentBraces:    false | ||||
|   SplitEmptyFunction: true | ||||
|   SplitEmptyRecord: true | ||||
|   SplitEmptyNamespace: true | ||||
| BreakBeforeBinaryOperators: None | ||||
| BreakBeforeConceptDeclarations: true | ||||
| BreakBeforeBraces: Allman | ||||
| BreakBeforeInheritanceComma: false | ||||
| BreakInheritanceList: BeforeColon | ||||
| BreakBeforeTernaryOperators: true | ||||
| BreakConstructorInitializersBeforeComma: false | ||||
| BreakConstructorInitializers: BeforeColon | ||||
| BreakAfterJavaFieldAnnotations: false | ||||
| BreakStringLiterals: true | ||||
| ColumnLimit:     80 | ||||
| CommentPragmas:  '^ IWYU pragma:' | ||||
| CompactNamespaces: false | ||||
| ConstructorInitializerAllOnOneLineOrOnePerLine: false | ||||
| ConstructorInitializerIndentWidth: 4 | ||||
| ContinuationIndentWidth: 4 | ||||
| Cpp11BracedListStyle: true | ||||
| DeriveLineEnding: true | ||||
| DerivePointerAlignment: false | ||||
| DisableFormat:   false | ||||
| EmptyLineBeforeAccessModifier: LogicalBlock | ||||
| ExperimentalAutoDetectBinPacking: false | ||||
| FixNamespaceComments: true | ||||
| ForEachMacros: | ||||
|   - foreach | ||||
|   - Q_FOREACH | ||||
|   - BOOST_FOREACH | ||||
| StatementAttributeLikeMacros: | ||||
|   - Q_EMIT | ||||
| IncludeBlocks:   Preserve | ||||
| IncludeCategories: | ||||
|   - Regex:           '^"(llvm|llvm-c|clang|clang-c)/' | ||||
|     Priority:        2 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '^(<|"(gtest|gmock|isl|json)/)' | ||||
|     Priority:        3 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
|   - Regex:           '.*' | ||||
|     Priority:        1 | ||||
|     SortPriority:    0 | ||||
|     CaseSensitive:   false | ||||
| IncludeIsMainRegex: '(Test)?$' | ||||
| IncludeIsMainSourceRegex: '' | ||||
| IndentCaseLabels: false | ||||
| IndentCaseBlocks: false | ||||
| IndentGotoLabels: true | ||||
| IndentPPDirectives: None | ||||
| IndentExternBlock: AfterExternBlock | ||||
| IndentRequires:  false | ||||
| IndentWidth:     4 | ||||
| IndentWrappedFunctionNames: false | ||||
| InsertTrailingCommas: None | ||||
| JavaScriptQuotes: Leave | ||||
| JavaScriptWrapImports: true | ||||
| KeepEmptyLinesAtTheStartOfBlocks: true | ||||
| MacroBlockBegin: '' | ||||
| MacroBlockEnd:   '' | ||||
| MaxEmptyLinesToKeep: 1 | ||||
| NamespaceIndentation: None | ||||
| ObjCBinPackProtocolList: Auto | ||||
| ObjCBlockIndentWidth: 4 | ||||
| ObjCBreakBeforeNestedBlockParam: true | ||||
| ObjCSpaceAfterProperty: false | ||||
| ObjCSpaceBeforeProtocolList: true | ||||
| PenaltyBreakAssignment: 2 | ||||
| PenaltyBreakBeforeFirstCallParameter: 19 | ||||
| PenaltyBreakComment: 300 | ||||
| PenaltyBreakFirstLessLess: 120 | ||||
| PenaltyBreakString: 1000 | ||||
| PenaltyBreakTemplateDeclaration: 10 | ||||
| PenaltyExcessCharacter: 1000000 | ||||
| PenaltyReturnTypeOnItsOwnLine: 1000000 | ||||
| PenaltyIndentedWhitespace: 0 | ||||
| PointerAlignment: Right | ||||
| ReflowComments:  true | ||||
| SortIncludes:    true | ||||
| SortJavaStaticImport: Before | ||||
| SortUsingDeclarations: true | ||||
| SpaceAfterCStyleCast: false | ||||
| SpaceAfterLogicalNot: false | ||||
| SpaceAfterTemplateKeyword: true | ||||
| SpaceBeforeAssignmentOperators: true | ||||
| SpaceBeforeCaseColon: false | ||||
| SpaceBeforeCpp11BracedList: false | ||||
| SpaceBeforeCtorInitializerColon: true | ||||
| SpaceBeforeInheritanceColon: true | ||||
| SpaceBeforeParens: ControlStatements | ||||
| SpaceAroundPointerQualifiers: Default | ||||
| SpaceBeforeRangeBasedForLoopColon: true | ||||
| SpaceInEmptyBlock: false | ||||
| SpaceInEmptyParentheses: false | ||||
| SpacesBeforeTrailingComments: 1 | ||||
| SpacesInAngles:  false | ||||
| SpacesInConditionalStatement: false | ||||
| SpacesInContainerLiterals: true | ||||
| SpacesInCStyleCastParentheses: false | ||||
| SpacesInParentheses: false | ||||
| SpacesInSquareBrackets: false | ||||
| SpaceBeforeSquareBrackets: false | ||||
| BitFieldColonSpacing: Both | ||||
| Standard:        Latest | ||||
| StatementMacros: | ||||
|   - Q_UNUSED | ||||
|   - QT_REQUIRE_VERSION | ||||
| TabWidth:        8 | ||||
| UseCRLF:         false | ||||
| UseTab:          Never | ||||
| WhitespaceSensitiveMacros: | ||||
|   - STRINGIZE | ||||
|   - PP_STRINGIZE | ||||
|   - BOOST_PP_STRINGIZE | ||||
|   - NS_SWIFT_NAME | ||||
|   - CF_SWIFT_NAME | ||||
| ... | ||||
| 
 | ||||
|  | @ -23,7 +23,7 @@ find_package(LLVM) | |||
| 
 | ||||
| include_directories(${CMAKE_SOURCE_DIR}) | ||||
| 
 | ||||
| BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t -Wcounterexamples") | ||||
| BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t") | ||||
| FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) | ||||
| 
 | ||||
| ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) | ||||
|  | @ -42,9 +42,13 @@ add_executable( | |||
| 	src/ast.h | ||||
| 	src/codegen.h | ||||
| 	src/parser.h | ||||
| 	src/validation.h | ||||
| 	src/util.h | ||||
|     src/ast.c | ||||
| 	src/codegen.c | ||||
| 	src/parser.c | ||||
| 	src/validation.c | ||||
| 	src/util.c | ||||
| 	src/main.c | ||||
| 	# Generated code | ||||
|     ${BISON_Parser_OUTPUTS} | ||||
|  |  | |||
|  | @ -0,0 +1,13 @@ | |||
| struct G { | ||||
|     Foo(t: bool): bool { | ||||
|         return t; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static main(): int { | ||||
|         g: G = alloc G; | ||||
|         g.Foo(true); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,6 @@ | |||
| struct Program {  | ||||
|     // This triggers a parse error | ||||
|     static Main(): int { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										14
									
								
								example.w
								
								
								
								
							
							
						
						
									
										14
									
								
								example.w
								
								
								
								
							|  | @ -1,16 +1,6 @@ | |||
| interface Increments | ||||
| { | ||||
|     Increment(): void; | ||||
| } | ||||
| 
 | ||||
| struct YourStruct | ||||
| { | ||||
|     yourInt: int; | ||||
| 
 | ||||
|     IncrementOther<T: Increments>(other: T): void | ||||
|     { | ||||
|         other.Increment(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct MyStruct | ||||
|  | @ -64,6 +54,8 @@ struct Program | |||
|             myStruct.myInt = 4; | ||||
|         } | ||||
| 
 | ||||
|         return myStruct.myInt; | ||||
|         Console.PrintLine("%i", myStruct.myInt); | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -12,8 +12,8 @@ | |||
| "double"                    return DOUBLE; | ||||
| "string"                    return STRING; | ||||
| "bool"                      return BOOL; | ||||
| "MemoryAddress"             return MEMORYADDRESS; | ||||
| "struct"                    return STRUCT; | ||||
| "interface"                 return INTERFACE; | ||||
| "return"                    return RETURN; | ||||
| "static"                    return STATIC; | ||||
| "Reference"                 return REFERENCE; | ||||
|  | @ -41,6 +41,7 @@ | |||
| ";"                         return SEMICOLON; | ||||
| ":"                         return COLON; | ||||
| "?"                         return QUESTION; | ||||
| "@"                         return AT; | ||||
| "("                         return LEFT_PAREN; | ||||
| ")"                         return RIGHT_PAREN; | ||||
| "["                         return LEFT_BRACKET; | ||||
|  |  | |||
|  | @ -25,8 +25,8 @@ extern FILE *yyin; | |||
| %token DOUBLE | ||||
| %token STRING | ||||
| %token BOOL | ||||
| %token MEMORYADDRESS | ||||
| %token STRUCT | ||||
| %token INTERFACE | ||||
| %token RETURN | ||||
| %token STATIC | ||||
| %token REFERENCE | ||||
|  | @ -55,6 +55,7 @@ extern FILE *yyin; | |||
| %token SEMICOLON | ||||
| %token COLON | ||||
| %token QUESTION | ||||
| %token AT | ||||
| %token LEFT_PAREN | ||||
| %token RIGHT_PAREN | ||||
| %token LEFT_BRACE | ||||
|  | @ -108,9 +109,17 @@ BaseType                : VOID | |||
|                         { | ||||
|                             $$ = MakePrimitiveTypeNode(Bool); | ||||
|                         } | ||||
|                         | MEMORYADDRESS | ||||
|                         { | ||||
|                             $$ = MakePrimitiveTypeNode(MemoryAddress); | ||||
|                         } | ||||
|                         | Identifier GenericArgumentClauseNonEmpty | ||||
|                         { | ||||
|                             $$ = MakeConcreteGenericTypeNode($1, $2); | ||||
|                         } | ||||
|                         | Identifier | ||||
|                         { | ||||
|                             $$ = MakeCustomTypeNode(yytext); | ||||
|                             $$ = MakeCustomTypeNode($1); | ||||
|                         } | ||||
|                         | REFERENCE LESS_THAN Type GREATER_THAN | ||||
|                         { | ||||
|  | @ -142,11 +151,40 @@ AccessExpression        : Identifier POINT AccessExpression | |||
|                             $$ = $1; | ||||
|                         } | ||||
| 
 | ||||
| SystemCallExpression    : AT Identifier | ||||
|                         { | ||||
|                             $$ = $2; | ||||
|                         } | ||||
| 
 | ||||
| Number                  : NUMBER | ||||
|                         { | ||||
|                             $$ = MakeNumberNode(yytext); | ||||
|                         } | ||||
| 
 | ||||
| FieldInit               : Identifier COLON Expression | ||||
|                         { | ||||
|                             $$ = MakeFieldInitNode($1, $3); | ||||
|                         } | ||||
| 
 | ||||
| StructInitFields        : FieldInit | ||||
|                         { | ||||
|                             $$ = StartStructInitFieldsNode($1); | ||||
|                         } | ||||
|                         | StructInitFields COMMA FieldInit | ||||
|                         { | ||||
|                             $$ = AddFieldInitNode($1, $3); | ||||
|                         } | ||||
|                         | | ||||
|                         { | ||||
|                             $$ = MakeEmptyFieldInitNode(); | ||||
|                         } | ||||
|                         ; | ||||
| 
 | ||||
| StructInitExpression    : Type LEFT_BRACE StructInitFields RIGHT_BRACE | ||||
|                         { | ||||
|                             $$ = MakeStructInitExpressionNode($1, $3); | ||||
|                         } | ||||
| 
 | ||||
| PrimaryExpression       : Number | ||||
|                         | STRING_LITERAL | ||||
|                         { | ||||
|  | @ -158,6 +196,7 @@ PrimaryExpression       : Number | |||
|                         } | ||||
|                         | FunctionCallExpression | ||||
|                         | AccessExpression | ||||
|                         | StructInitExpression | ||||
|                         ; | ||||
| 
 | ||||
| UnaryExpression         : BANG Expression | ||||
|  | @ -231,9 +270,13 @@ ReturnStatement         : RETURN Expression | |||
|                             $$ = MakeReturnVoidStatementNode(); | ||||
|                         } | ||||
| 
 | ||||
| FunctionCallExpression  : AccessExpression LEFT_PAREN Arguments RIGHT_PAREN | ||||
| FunctionCallExpression  : AccessExpression GenericArgumentClause LEFT_PAREN Arguments RIGHT_PAREN | ||||
|                         { | ||||
|                             $$ = MakeFunctionCallExpressionNode($1, $3); | ||||
|                             $$ = MakeFunctionCallExpressionNode($1, $4, $2); | ||||
|                         } | ||||
|                         | SystemCallExpression GenericArgumentClause LEFT_PAREN Arguments RIGHT_PAREN | ||||
|                         { | ||||
|                             $$ = MakeSystemCallExpressionNode($1, $4, $2); | ||||
|                         } | ||||
| 
 | ||||
| PartialStatement        : FunctionCallExpression | ||||
|  | @ -276,11 +319,11 @@ Statements              : Statement | |||
|                             $$ = AddStatement($1, $2); | ||||
|                         } | ||||
| 
 | ||||
| Arguments               : PrimaryExpression | ||||
| Arguments               : Expression | ||||
|                         { | ||||
|                             $$ = StartFunctionArgumentSequenceNode($1); | ||||
|                         } | ||||
|                         | Arguments COMMA PrimaryExpression | ||||
|                         | Arguments COMMA Expression | ||||
|                         { | ||||
|                             $$ = AddFunctionArgumentNode($1, $3); | ||||
|                         } | ||||
|  | @ -308,40 +351,63 @@ Body                    : LEFT_BRACE Statements RIGHT_BRACE | |||
|                             $$ = $2; | ||||
|                         } | ||||
| 
 | ||||
| GenericConstraint       : Identifier COLON Identifier | ||||
| GenericDeclaration      : Identifier | ||||
|                         { | ||||
|                             $$ = MakeGenericConstraintNode($1, $3); | ||||
|                             $$ = MakeGenericDeclarationNode($1, NULL); | ||||
|                         } | ||||
| 
 | ||||
| GenericConstraints      : GenericConstraint | ||||
| GenericDeclarations     : GenericDeclaration | ||||
|                         { | ||||
|                             $$ = StartGenericConstraintsNode($1); | ||||
|                             $$ = StartGenericDeclarationsNode($1); | ||||
|                         } | ||||
|                         | GenericConstraints COMMA GenericConstraint | ||||
|                         | GenericDeclarations COMMA GenericDeclaration | ||||
|                         { | ||||
|                             $$ = AddGenericConstraint($1, $3); | ||||
|                             $$ = AddGenericDeclaration($1, $3); | ||||
|                         } | ||||
|                         ; | ||||
| 
 | ||||
| GenericConstraintClause : LESS_THAN GenericConstraints GREATER_THAN | ||||
| GenericDeclarationClause    : LESS_THAN GenericDeclarations GREATER_THAN | ||||
|                             { | ||||
|                                 $$ = $2; | ||||
|                             } | ||||
|                             | | ||||
|                             { | ||||
|                             $$ = MakeEmptyGenericConstraintsNode(); | ||||
|                                 $$ = MakeEmptyGenericDeclarationsNode(); | ||||
|                             } | ||||
| 
 | ||||
| GenericArgument         : Type | ||||
|                         { | ||||
|                             $$ = MakeGenericArgumentNode($1); | ||||
|                         } | ||||
| 
 | ||||
| GenericArguments        : GenericArgument | ||||
|                         { | ||||
|                             $$ = StartGenericArgumentsNode($1); | ||||
|                         } | ||||
|                         | GenericArguments COMMA GenericArgument | ||||
|                         { | ||||
|                             $$ = AddGenericArgument($1, $3); | ||||
|                         } | ||||
| 
 | ||||
| GenericArgumentClauseNonEmpty   : LESS_THAN GenericArguments GREATER_THAN | ||||
|                                 { | ||||
|                                     $$ = $2; | ||||
|                                 } | ||||
|                                 ; | ||||
| 
 | ||||
| /* FIXME: modifiers should be recursive */ | ||||
| FunctionSignature       : Identifier GenericConstraintClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||
| GenericArgumentClause   : GenericArgumentClauseNonEmpty | ||||
|                         | | ||||
|                         { | ||||
|                             $$ = MakeEmptyGenericArgumentsNode(); | ||||
|                         } | ||||
| 
 | ||||
| FunctionSignature       : Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||
|                         { | ||||
|                             $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); | ||||
|                         } | ||||
|                         | STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||
|                         | STATIC Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||
|                         { | ||||
|                             Node *modifier = MakeStaticNode(); | ||||
|                             $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1), MakeEmptyGenericConstraintsNode()); | ||||
|                             $$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3); | ||||
|                         } | ||||
| 
 | ||||
| FunctionDeclaration     : FunctionSignature Body | ||||
|  | @ -349,29 +415,11 @@ FunctionDeclaration     : FunctionSignature Body | |||
|                             $$ = MakeFunctionDeclarationNode($1, $2); | ||||
|                         } | ||||
| 
 | ||||
| StructDeclaration       : STRUCT Identifier LEFT_BRACE Declarations RIGHT_BRACE | ||||
| StructDeclaration       : STRUCT Identifier GenericDeclarationClause LEFT_BRACE Declarations RIGHT_BRACE | ||||
|                         { | ||||
|                             $$ = MakeStructDeclarationNode($2, $4); | ||||
|                             $$ = MakeStructDeclarationNode($2, $5, $3); | ||||
|                         } | ||||
| 
 | ||||
| InterfaceDeclaration    : INTERFACE Identifier LEFT_BRACE InterfaceChildren RIGHT_BRACE | ||||
|                         { | ||||
|                             $$ = MakeInterfaceDeclarationNode($2, $4); | ||||
|                         } | ||||
| 
 | ||||
| InterfaceChild          : FunctionSignature SEMICOLON | ||||
|                         ; | ||||
| 
 | ||||
| InterfaceChildren       : InterfaceChild | ||||
|                         { | ||||
|                             $$ = StartDeclarationSequenceNode($1); | ||||
|                         } | ||||
|                         | InterfaceChildren InterfaceChild | ||||
|                         { | ||||
|                             $$ = AddDeclarationNode($1, $2); | ||||
|                         } | ||||
|                         ; | ||||
| 
 | ||||
| Declaration             : FunctionDeclaration | ||||
|                         | VariableDeclaration SEMICOLON | ||||
|                         ; | ||||
|  | @ -385,9 +433,7 @@ Declarations            : Declaration | |||
|                             $$ = AddDeclarationNode($1, $2); | ||||
|                         } | ||||
| 
 | ||||
| TopLevelDeclaration     : StructDeclaration | ||||
|                         | InterfaceDeclaration | ||||
|                         ; | ||||
| TopLevelDeclaration     : StructDeclaration; | ||||
| 
 | ||||
| TopLevelDeclarations    : TopLevelDeclaration | ||||
|                         { | ||||
|  |  | |||
|  | @ -0,0 +1,59 @@ | |||
| struct Foo { | ||||
|     static Func2<U>(u: U) : U { | ||||
|         return u; | ||||
|     } | ||||
| 
 | ||||
|     static Func<T>(t: T): T { | ||||
|         foo: T = t; | ||||
|         return Foo.Func2(foo); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct MemoryBlock<T> | ||||
| { | ||||
| 	start: MemoryAddress; | ||||
| 	capacity: uint; | ||||
| 
 | ||||
| 	AddressOf(index: uint): MemoryAddress | ||||
|     { | ||||
|         return start + (index * @sizeof<T>()); | ||||
|     } | ||||
| 
 | ||||
|     Get(index: uint): T | ||||
|     { | ||||
|         return @dereference<T>(AddressOf(index)); | ||||
|     } | ||||
| 
 | ||||
|     Set(index: uint, value: T): void | ||||
|     { | ||||
|         @memcpy(AddressOf(index), @addr(value), @sizeof<T>()); | ||||
|     } | ||||
| 
 | ||||
|     Free(): void | ||||
|     { | ||||
|         @free(start); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static Main(): int { | ||||
|         x: int = 4; | ||||
|         y: int = Foo.Func(x); | ||||
|         block: MemoryBlock<int> = MemoryBlock<int> | ||||
|         { | ||||
|             capacity: y, | ||||
|             start: @malloc(y * @sizeof<int>()) | ||||
|         }; | ||||
|         block.Set(0, 5); | ||||
|         block.Set(1, 3); | ||||
|         block.Set(2, 9); | ||||
|         block.Set(3, 100); | ||||
|         Console.PrintLine("%p", block.start); | ||||
|         Console.PrintLine("%i", block.Get(0)); | ||||
|         Console.PrintLine("%i", block.Get(1)); | ||||
|         Console.PrintLine("%i", block.Get(2)); | ||||
|         Console.PrintLine("%i", block.Get(3)); | ||||
|         block.Free(); | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,44 @@ | |||
| struct MyStruct { | ||||
|     static MyFunc(): int { | ||||
|         myStructInt: int = 595959959; | ||||
|         return myStructInt; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static Foo(): int { | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     static Main(): int { | ||||
|         myInt: int = 54; | ||||
|         if (myInt < 0) { | ||||
|             signTag: int = 0 - 1; | ||||
|         } else if (myInt == 0) { | ||||
|             signTag: int = 0; | ||||
|         } else { | ||||
|             signTag: int = 1; | ||||
|         } | ||||
| 
 | ||||
|         myBool: bool; | ||||
|         if (myBool) { | ||||
|             if (myBool) { | ||||
|                 if (myBool) { | ||||
|                     if (myBool) { | ||||
|                         if (myBool) { | ||||
|                             lol: int = 69; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         someInt: int = 9585858; | ||||
| 
 | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     static Bar(): int { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,15 @@ | |||
| struct Foo { | ||||
|     static Func(): void { | ||||
|         Func2(); | ||||
|     } | ||||
| 
 | ||||
|     static Func2(): void { | ||||
|         Func(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static main(): int { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| struct MyStruct { | ||||
|     foo: int; | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static Main(): int { | ||||
|         myStruct: Reference<MyStruct>; | ||||
|         myStruct = alloc MyStruct; | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										492
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										492
									
								
								src/ast.h
								
								
								
								
							|  | @ -3,6 +3,15 @@ | |||
| 
 | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| /* -Wpedantic nameless union/struct silencing */ | ||||
| #ifndef WRAITHNAMELESS | ||||
| #ifdef __GNUC__ | ||||
| #define WRAITHNAMELESS __extension__ | ||||
| #else | ||||
| #define WRAITHNAMELESS | ||||
| #endif /* __GNUC__ */ | ||||
| #endif /* WRAITHNAMELESS */ | ||||
| 
 | ||||
| typedef enum | ||||
| { | ||||
|     AccessExpression, | ||||
|  | @ -10,10 +19,11 @@ typedef enum | |||
|     Assignment, | ||||
|     BinaryExpression, | ||||
|     Comment, | ||||
|     ConcreteGenericTypeNode, | ||||
|     CustomTypeNode, | ||||
|     Declaration, | ||||
|     DeclarationSequence, | ||||
|     Expression, | ||||
|     FieldInit, | ||||
|     ForLoop, | ||||
|     FunctionArgumentSequence, | ||||
|     FunctionCallExpression, | ||||
|  | @ -21,12 +31,14 @@ typedef enum | |||
|     FunctionModifiers, | ||||
|     FunctionSignature, | ||||
|     FunctionSignatureArguments, | ||||
|     GenericConstraint, | ||||
|     GenericConstraints, | ||||
|     GenericArgument, | ||||
|     GenericArguments, | ||||
|     GenericDeclaration, | ||||
|     GenericDeclarations, | ||||
|     GenericTypeNode, | ||||
|     Identifier, | ||||
|     IfStatement, | ||||
|     IfElseStatement, | ||||
|     InterfaceDeclaration, | ||||
|     Number, | ||||
|     PrimitiveTypeNode, | ||||
|     ReferenceTypeNode, | ||||
|  | @ -36,6 +48,9 @@ typedef enum | |||
|     StaticModifier, | ||||
|     StringLiteral, | ||||
|     StructDeclaration, | ||||
|     StructInit, | ||||
|     StructInitFields, | ||||
|     SystemCall, | ||||
|     Type, | ||||
|     UnaryExpression | ||||
| } SyntaxKind; | ||||
|  | @ -65,7 +80,8 @@ typedef enum | |||
|     UInt, | ||||
|     Float, | ||||
|     Double, | ||||
|     String | ||||
|     String, | ||||
|     MemoryAddress | ||||
| } PrimitiveType; | ||||
| 
 | ||||
| typedef union | ||||
|  | @ -74,160 +90,378 @@ typedef union | |||
|     BinaryOperator binaryOperator; | ||||
| } Operator; | ||||
| 
 | ||||
| typedef struct Node | ||||
| typedef struct TypeTag TypeTag; | ||||
| 
 | ||||
| typedef struct ConcreteGenericTypeTag | ||||
| { | ||||
|     char *name; | ||||
|     TypeTag **genericArguments; | ||||
|     uint32_t genericArgumentCount; | ||||
| } ConcreteGenericTypeTag; | ||||
| 
 | ||||
| struct TypeTag | ||||
| { | ||||
|     enum Type | ||||
|     { | ||||
|         Unknown, | ||||
|         Primitive, | ||||
|         Reference, | ||||
|         Custom, | ||||
|         Generic, | ||||
|         ConcreteGeneric | ||||
|     } type; | ||||
|     union | ||||
|     { | ||||
|         /* Valid when type = Primitive. */ | ||||
|         PrimitiveType primitiveType; | ||||
|         /* Valid when type = Reference. */ | ||||
|         struct TypeTag *referenceType; | ||||
|         /* Valid when type = Custom. */ | ||||
|         char *customType; | ||||
|         /* Valid when type = Generic. */ | ||||
|         char *genericType; | ||||
|         /* Valid when type = ConcreteGeneric */ | ||||
|         ConcreteGenericTypeTag concreteGenericType; | ||||
|     } value; | ||||
| }; | ||||
| 
 | ||||
| typedef struct Node Node; | ||||
| 
 | ||||
| struct Node | ||||
| { | ||||
|     Node *parent; | ||||
|     SyntaxKind syntaxKind; | ||||
|     struct Node **children; | ||||
|     uint32_t childCount; | ||||
|     union | ||||
|     WRAITHNAMELESS union | ||||
|     { | ||||
|         UnaryOperator unaryOperator; | ||||
|         BinaryOperator binaryOperator; | ||||
|     } operator; | ||||
|     union | ||||
|         struct | ||||
|         { | ||||
|             Node *accessee; | ||||
|             Node *accessor; | ||||
|         } accessExpression; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *type; | ||||
|         } allocExpression; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *left; | ||||
|             Node *right; | ||||
|         } assignmentStatement; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *left; | ||||
|             Node *right; | ||||
|             BinaryOperator operator; | ||||
|         } binaryExpression; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
| 
 | ||||
|         } comment; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|             Node *genericArguments; | ||||
|         } concreteGenericType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|         } customType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *type; | ||||
|             Node *identifier; | ||||
|         } declaration; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **sequence; | ||||
|             uint32_t count; | ||||
|         } declarationSequence; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; | ||||
|             Node *expression; | ||||
|         } fieldInit; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *declaration; | ||||
|             Node *startNumber; | ||||
|             Node *endNumber; | ||||
|             Node *statementSequence; | ||||
|         } forLoop; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **sequence; | ||||
|             uint32_t count; | ||||
|         } functionArgumentSequence; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; /* FIXME: need better name */ | ||||
|             Node *argumentSequence; | ||||
|             Node *genericArguments; | ||||
|         } functionCallExpression; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *functionSignature; | ||||
|             Node *functionBody; | ||||
|         } functionDeclaration; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **sequence; | ||||
|             uint32_t count; | ||||
|         } functionModifiers; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; | ||||
|             Node *type; | ||||
|             Node *arguments; | ||||
|             Node *modifiers; | ||||
|             Node *genericDeclarations; | ||||
|         } functionSignature; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **sequence; | ||||
|             uint32_t count; | ||||
|         } functionSignatureArguments; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *type; | ||||
|         } genericArgument; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **arguments; | ||||
|             uint32_t count; | ||||
|         } genericArguments; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; | ||||
|             Node *constraint; | ||||
|         } genericDeclaration; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **declarations; | ||||
|             uint32_t count; | ||||
|         } genericDeclarations; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|         } genericType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|         } identifier; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *expression; | ||||
|             Node *statementSequence; | ||||
|         } ifStatement; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *ifStatement; | ||||
|             Node *elseStatement; | ||||
|         } ifElseStatement; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             uint64_t value; | ||||
|         } number; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             PrimitiveType type; | ||||
|         } primitiveType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *type; | ||||
|         } referenceType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *expression; | ||||
|         } returnStatement; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
| 
 | ||||
|         } returnVoidStatement; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **sequence; | ||||
|             uint32_t count; | ||||
|         } statementSequence; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
| 
 | ||||
|         } staticModifier; /* FIXME: modifiers should just be an enum */ | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *string; | ||||
|         uint64_t number; | ||||
|     } value; | ||||
|     PrimitiveType primitiveType; | ||||
| } Node; | ||||
|         } stringLiteral; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; | ||||
|             Node *declarationSequence; | ||||
|             Node *genericDeclarations; | ||||
|         } structDeclaration; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *type; | ||||
|             Node *initFields; | ||||
|         } structInit; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node **fieldInits; | ||||
|             uint32_t count; | ||||
|         } structInitFields; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *identifier; | ||||
|             Node *argumentSequence; | ||||
|             Node *genericArguments; | ||||
|         } systemCall; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *typeNode; | ||||
|         } type; /* FIXME: this needs a refactor */ | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             Node *child; | ||||
|             UnaryOperator operator; | ||||
|         } unaryExpression; | ||||
|     }; | ||||
|     TypeTag *typeTag; | ||||
| }; | ||||
| 
 | ||||
| char* strdup (const char* s); | ||||
| const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||
| 
 | ||||
| uint8_t IsPrimitiveType(Node *typeNode); | ||||
| Node* MakePrimitiveTypeNode( | ||||
|     PrimitiveType type | ||||
| ); | ||||
| Node* MakeCustomTypeNode( | ||||
|     char *string | ||||
| ); | ||||
| Node* MakeReferenceTypeNode( | ||||
|     Node *typeNode | ||||
| ); | ||||
| Node* MakeTypeNode( | ||||
|     Node *typeNode /* can be primitive, custom, or reference */ | ||||
| ); | ||||
| Node* MakeIdentifierNode( | ||||
|     const char *id | ||||
| ); | ||||
| Node* MakeNumberNode( | ||||
|     const char *numberString | ||||
| ); | ||||
| Node* MakeStringNode( | ||||
|     const char *string | ||||
| ); | ||||
| Node* MakeStaticNode(); | ||||
| Node* MakeFunctionModifiersNode( | ||||
|     Node **pModifierNodes, | ||||
|     uint32_t modifierCount | ||||
| ); | ||||
| Node* MakeUnaryNode( | ||||
|     UnaryOperator operator, | ||||
|     Node *child | ||||
| ); | ||||
| Node* MakeBinaryNode( | ||||
|     BinaryOperator operator, | ||||
|     Node *left, | ||||
|     Node *right | ||||
| ); | ||||
| Node* MakeDeclarationNode( | ||||
|     Node* typeNode, | ||||
|     Node* identifierNode | ||||
| ); | ||||
| Node* MakeAssignmentNode( | ||||
|     Node *left, | ||||
|     Node *right | ||||
| ); | ||||
| Node* StartStatementSequenceNode( | ||||
|     Node* statementNode | ||||
| ); | ||||
| Node* AddStatement( | ||||
|     Node* statementSequenceNode, | ||||
|     Node *statementNode | ||||
| ); | ||||
| Node* MakeReturnStatementNode( | ||||
|     Node *expressionNode | ||||
| ); | ||||
| Node* MakeReturnVoidStatementNode(); | ||||
| Node* StartFunctionSignatureArgumentsNode( | ||||
|     Node *argumentNode | ||||
| ); | ||||
| Node* AddFunctionSignatureArgumentNode( | ||||
|     Node *argumentsNode, | ||||
|     Node *argumentNode | ||||
| ); | ||||
| Node* MakeEmptyFunctionSignatureArgumentsNode(); | ||||
| Node* MakeGenericConstraintNode( | ||||
| Node *MakePrimitiveTypeNode(PrimitiveType type); | ||||
| Node *MakeCustomTypeNode(Node *identifierNode); | ||||
| Node *MakeReferenceTypeNode(Node *typeNode); | ||||
| Node *MakeConcreteGenericTypeNode( | ||||
|     Node *identifierNode, | ||||
|     Node *interfaceNode | ||||
| ); | ||||
| Node* StartGenericConstraintsNode(Node *genericNode); | ||||
| Node* AddGenericConstraint( | ||||
|     Node *genericsNode, | ||||
|     Node *genericNode | ||||
| ); | ||||
| Node* MakeEmptyGenericConstraintsNode(); | ||||
|     Node *genericArgumentsNode); | ||||
| Node *MakeTypeNode(Node *typeNode); | ||||
| Node *MakeIdentifierNode(const char *id); | ||||
| Node *MakeNumberNode(const char *numberString); | ||||
| Node *MakeStringNode(const char *string); | ||||
| Node *MakeStaticNode(); | ||||
| Node *MakeFunctionModifiersNode(Node **pModifierNodes, uint32_t modifierCount); | ||||
| Node *MakeUnaryNode(UnaryOperator operator, Node * child); | ||||
| Node *MakeBinaryNode(BinaryOperator operator, Node * left, Node *right); | ||||
| Node *MakeDeclarationNode(Node *typeNode, Node *identifierNode); | ||||
| Node *MakeAssignmentNode(Node *left, Node *right); | ||||
| Node *StartStatementSequenceNode(Node *statementNode); | ||||
| Node *AddStatement(Node *statementSequenceNode, Node *statementNode); | ||||
| Node *MakeReturnStatementNode(Node *expressionNode); | ||||
| Node *MakeReturnVoidStatementNode(); | ||||
| Node *StartFunctionSignatureArgumentsNode(Node *argumentNode); | ||||
| Node *AddFunctionSignatureArgumentNode(Node *argumentsNode, Node *argumentNode); | ||||
| Node *MakeEmptyFunctionSignatureArgumentsNode(); | ||||
| Node *MakeFunctionSignatureNode( | ||||
|     Node *identifierNode, | ||||
|     Node *typeNode, | ||||
|     Node *argumentsNode, | ||||
|     Node *modifiersNode, | ||||
|     Node *genericConstraintsNode | ||||
| ); | ||||
|     Node *genericArgumentsNode); | ||||
| Node *MakeFunctionDeclarationNode( | ||||
|     Node *functionSignatureNode, | ||||
|     Node *functionBodyNode | ||||
| ); | ||||
|     Node *functionBodyNode); | ||||
| Node *MakeGenericDeclarationNode(Node *identifierNode, Node *constraintNode); | ||||
| Node *MakeEmptyGenericDeclarationsNode(); | ||||
| Node *StartGenericDeclarationsNode(Node *genericDeclarationNode); | ||||
| Node *AddGenericDeclaration( | ||||
|     Node *genericDeclarationsNode, | ||||
|     Node *genericDeclarationNode); | ||||
| Node *MakeGenericArgumentNode(Node *typeNode); | ||||
| Node *MakeEmptyGenericArgumentsNode(); | ||||
| Node *StartGenericArgumentsNode(Node *genericArgumentNode); | ||||
| Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | ||||
| Node *MakeGenericTypeNode(char *name); | ||||
| Node *MakeStructDeclarationNode( | ||||
|     Node *identifierNode, | ||||
|     Node *declarationSequenceNode | ||||
| ); | ||||
| Node* MakeInterfaceDeclarationNode( | ||||
|     Node *identifierNode, | ||||
|     Node *declarationSequenceNode | ||||
| ); | ||||
| Node* StartDeclarationSequenceNode( | ||||
|     Node *declarationNode | ||||
| ); | ||||
| Node* AddDeclarationNode( | ||||
|     Node *declarationSequenceNode, | ||||
|     Node *declarationNode | ||||
| ); | ||||
| Node *StartFunctionArgumentSequenceNode( | ||||
|     Node *argumentNode | ||||
| ); | ||||
| Node *AddFunctionArgumentNode( | ||||
|     Node *argumentSequenceNode, | ||||
|     Node *argumentNode | ||||
| ); | ||||
|     Node *genericArgumentsNode); | ||||
| Node *StartDeclarationSequenceNode(Node *declarationNode); | ||||
| Node *AddDeclarationNode(Node *declarationSequenceNode, Node *declarationNode); | ||||
| Node *StartFunctionArgumentSequenceNode(Node *argumentNode); | ||||
| Node *AddFunctionArgumentNode(Node *argumentSequenceNode, Node *argumentNode); | ||||
| Node *MakeEmptyFunctionArgumentSequenceNode(); | ||||
| Node *MakeFunctionCallExpressionNode( | ||||
|     Node *identifierNode, | ||||
|     Node *argumentSequenceNode | ||||
| ); | ||||
| Node* MakeAccessExpressionNode( | ||||
|     Node *accessee, | ||||
|     Node *accessor | ||||
| ); | ||||
| Node* MakeAllocNode( | ||||
|     Node *typeNode | ||||
| ); | ||||
| Node* MakeIfNode( | ||||
|     Node *expressionNode, | ||||
|     Node *statementSequenceNode | ||||
| ); | ||||
|     Node *argumentSequenceNode, | ||||
|     Node *genericArgumentsNode); | ||||
| Node *MakeSystemCallExpressionNode( | ||||
|     Node *identifierNode, | ||||
|     Node *argumentSequenceNode, | ||||
|     Node *genericArgumentsNode); | ||||
| Node *MakeAccessExpressionNode(Node *accessee, Node *accessor); | ||||
| Node *MakeAllocNode(Node *typeNode); | ||||
| Node *MakeIfNode(Node *expressionNode, Node *statementSequenceNode); | ||||
| Node *MakeIfElseNode( | ||||
|     Node *ifNode, | ||||
|     Node *statementSequenceNode | ||||
|     Node *elseNode /* can be a conditional or a statement sequence */ | ||||
| ); | ||||
| Node *MakeForLoopNode( | ||||
|     Node *identifierNode, | ||||
|     Node *startNumberNode, | ||||
|     Node *endNumberNode, | ||||
|     Node *statementSequenceNode | ||||
| ); | ||||
|     Node *statementSequenceNode); | ||||
| Node *MakeFieldInitNode(Node *identifierNode, Node *expressionNode); | ||||
| Node *StartStructInitFieldsNode(Node *fieldInitNode); | ||||
| Node *AddFieldInitNode(Node *structInitFieldsNode, Node *fieldInitNode); | ||||
| Node *MakeEmptyFieldInitNode(); | ||||
| Node *MakeStructInitExpressionNode(Node *typeNode, Node *structInitFieldsNode); | ||||
| 
 | ||||
| void PrintTree(Node *node, uint32_t tabCount); | ||||
| void PrintNode(Node *node, uint32_t tabCount); | ||||
| const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||
| 
 | ||||
| /* Helper function for applying a void function generically over the children of
 | ||||
|  * an AST node. Used for functions that need to traverse the entire tree but | ||||
|  * only perform operations on a subset of node types. Such functions can match | ||||
|  * the syntaxKinds relevant to their purpose and invoke this function in all | ||||
|  * other cases. */ | ||||
| void Recurse(Node *node, void (*func)(Node *)); | ||||
| 
 | ||||
| void LinkParentPointers(Node *node, Node *prev); | ||||
| 
 | ||||
| TypeTag *MakeTypeTag(Node *node); | ||||
| char *TypeTagToString(TypeTag *tag); | ||||
| uint8_t TypeTagEqual(TypeTag *typeTagA, TypeTag *typeTagB); | ||||
| 
 | ||||
| Node *LookupIdNode(Node *current, Node *prev, char *target); | ||||
| 
 | ||||
| #endif /* WRAITH_AST_H */ | ||||
|  |  | |||
							
								
								
									
										2068
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										2068
									
								
								src/codegen.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										42
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										42
									
								
								src/main.c
								
								
								
								
							|  | @ -1,8 +1,9 @@ | |||
| #include <stdlib.h> | ||||
| #include "../lib/dropt/dropt.h" | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "parser.h" | ||||
| #include "codegen.h" | ||||
| #include "parser.h" | ||||
| #include "validation.h" | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|  | @ -13,9 +14,26 @@ int main(int argc, char *argv[]) | |||
|     int exitCode = EXIT_SUCCESS; | ||||
| 
 | ||||
|     dropt_option options[] = { | ||||
|         { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, | ||||
|         { 'v', "parse-verbose", "Shows verbose parser output.", NULL, dropt_handle_bool, &parseVerbose }, | ||||
|         { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, | ||||
|         {'h', | ||||
|          "help", | ||||
|          "Shows help.", | ||||
|          NULL, | ||||
|          dropt_handle_bool, | ||||
|          &showHelp, | ||||
|          dropt_attr_halt}, | ||||
|         {'v', | ||||
|          "parse-verbose", | ||||
|          "Shows verbose parser output.", | ||||
|          NULL, | ||||
|          dropt_handle_bool, | ||||
|          &parseVerbose}, | ||||
|         {'O', | ||||
|          "optimize", | ||||
|          "Sets optimization level of the output IR. Must be a value between 0 " | ||||
|          "and 3.", | ||||
|          "number", | ||||
|          dropt_handle_uint, | ||||
|          &optimizationLevel}, | ||||
|         {0} /* Required sentinel value. */ | ||||
|     }; | ||||
| 
 | ||||
|  | @ -35,7 +53,10 @@ int main(int argc, char *argv[]) | |||
|         char **rest = dropt_parse(droptContext, -1, &argv[1]); | ||||
|         if (dropt_get_error(droptContext) != dropt_error_none) | ||||
|         { | ||||
|             fprintf(stderr, "wraith: %s\n", dropt_get_error_message(droptContext)); | ||||
|             fprintf( | ||||
|                 stderr, | ||||
|                 "wraith: %s\n", | ||||
|                 dropt_get_error_message(droptContext)); | ||||
|             exitCode = EXIT_FAILURE; | ||||
|         } | ||||
|         else if (showHelp) | ||||
|  | @ -64,6 +85,15 @@ int main(int argc, char *argv[]) | |||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     LinkParentPointers(rootNode, NULL); | ||||
|                     /* FIXME: ValidateIdentifiers should return some sort of
 | ||||
|                               error status object. */ | ||||
|                     ValidateIdentifiers(rootNode); | ||||
|                     TagIdentifierTypes(rootNode); | ||||
|                     ConvertCustomsToGenerics(rootNode); | ||||
|                     PrintNode(rootNode, 0); | ||||
| 
 | ||||
|                     printf("Beginning codegen.\n"); | ||||
|                     exitCode = Codegen(rootNode, optimizationLevel); | ||||
|                 } | ||||
|             } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| #include <stdio.h> | ||||
| 
 | ||||
| #include "y.tab.h" | ||||
| #include "ast.h" | ||||
| #include "y.tab.h" | ||||
| 
 | ||||
| extern FILE *yyin; | ||||
| extern int yydebug; | ||||
|  | @ -31,7 +31,7 @@ int Parse(char *inputFilename, Node **pRootNode, uint8_t parseVerbose) | |||
|     { | ||||
|         if (parseVerbose) | ||||
|         { | ||||
|             PrintTree(*pRootNode, 0); | ||||
|             PrintNode(*pRootNode, 0); | ||||
|         } | ||||
|     } | ||||
|     else if (result == 1) | ||||
|  |  | |||
|  | @ -0,0 +1,38 @@ | |||
| #include "util.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| char *strdup(const char *s) | ||||
| { | ||||
|     size_t slen = strlen(s); | ||||
|     char *result = (char *)malloc(sizeof(char) * (slen + 1)); | ||||
|     if (result == NULL) | ||||
|     { | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     memcpy(result, s, slen + 1); | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| char *w_strcat(char *s, char *s2) | ||||
| { | ||||
|     size_t slen = strlen(s); | ||||
|     size_t slen2 = strlen(s2); | ||||
|     s = realloc(s, sizeof(char) * (slen + slen2 + 1)); | ||||
|     strcat(s, s2); | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| uint64_t str_hash(char *str) | ||||
| { | ||||
|     uint64_t hash = 5381; | ||||
|     size_t c; | ||||
| 
 | ||||
|     while ((c = *str++)) | ||||
|     { | ||||
|         hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ | ||||
|     } | ||||
| 
 | ||||
|     return hash; | ||||
| } | ||||
|  | @ -0,0 +1,11 @@ | |||
| #ifndef WRAITH_UTIL_H | ||||
| #define WRAITH_UTIL_H | ||||
| 
 | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| char *strdup(const char *s); | ||||
| char *w_strcat(char *s, char *s2); | ||||
| uint64_t str_hash(char *str); | ||||
| 
 | ||||
| #endif /* WRAITH_UTIL_H */ | ||||
|  | @ -0,0 +1,493 @@ | |||
| #include "validation.h" | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| Node *GetIdFromStruct(Node *structDecl) | ||||
| { | ||||
|     if (structDecl->syntaxKind != StructDeclaration) | ||||
|     { | ||||
|         fprintf( | ||||
|             stderr, | ||||
|             "wraith: Attempted to call GetIdFromStruct on node with kind: " | ||||
|             "%s.\n", | ||||
|             SyntaxKindString(structDecl->syntaxKind)); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     return structDecl->structDeclaration.identifier; | ||||
| } | ||||
| 
 | ||||
| Node *GetIdFromFunction(Node *funcDecl) | ||||
| { | ||||
|     if (funcDecl->syntaxKind != FunctionDeclaration) | ||||
|     { | ||||
|         fprintf( | ||||
|             stderr, | ||||
|             "wraith: Attempted to call GetIdFromFunction on node with kind: " | ||||
|             "%s.\n", | ||||
|             SyntaxKindString(funcDecl->syntaxKind)); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     Node *sig = funcDecl->functionDeclaration.functionSignature; | ||||
|     return sig->functionSignature.identifier; | ||||
| } | ||||
| 
 | ||||
| Node *GetIdFromDeclaration(Node *decl) | ||||
| { | ||||
|     if (decl->syntaxKind != Declaration) | ||||
|     { | ||||
|         fprintf( | ||||
|             stderr, | ||||
|             "wraith: Attempted to call GetIdFromDeclaration on node with kind: " | ||||
|             "%s.\n", | ||||
|             SyntaxKindString(decl->syntaxKind)); | ||||
|     } | ||||
| 
 | ||||
|     return decl->declaration.identifier; | ||||
| } | ||||
| 
 | ||||
| bool AssignmentHasDeclaration(Node *assign) | ||||
| { | ||||
|     return ( | ||||
|         assign->syntaxKind == Assignment && | ||||
|         assign->assignmentStatement.left->syntaxKind == Declaration); | ||||
| } | ||||
| 
 | ||||
| Node *GetIdFromAssignment(Node *assign) | ||||
| { | ||||
|     if (assign->syntaxKind != Assignment) | ||||
|     { | ||||
|         fprintf( | ||||
|             stderr, | ||||
|             "wraith: Attempted to call GetIdFromAssignment on node with kind: " | ||||
|             "%s.\n", | ||||
|             SyntaxKindString(assign->syntaxKind)); | ||||
|     } | ||||
| 
 | ||||
|     if (AssignmentHasDeclaration(assign)) | ||||
|     { | ||||
|         return GetIdFromDeclaration(assign->assignmentStatement.left); | ||||
|     } | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| bool NodeMayHaveId(Node *node) | ||||
| { | ||||
|     switch (node->syntaxKind) | ||||
|     { | ||||
|     case StructDeclaration: | ||||
|     case FunctionDeclaration: | ||||
|     case Declaration: | ||||
|     case Assignment: | ||||
|         return true; | ||||
|     default: | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Node *TryGetId(Node *node) | ||||
| { | ||||
|     switch (node->syntaxKind) | ||||
|     { | ||||
|     case Assignment: | ||||
|         return GetIdFromAssignment(node); | ||||
|     case Declaration: | ||||
|         return GetIdFromDeclaration(node); | ||||
|     case FunctionDeclaration: | ||||
|         return GetIdFromFunction(node); | ||||
|     case StructDeclaration: | ||||
|         return GetIdFromStruct(node); | ||||
|     default: | ||||
|         return NULL; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Node *LookupFunctionArgId(Node *funcDecl, char *target) | ||||
| { | ||||
|     Node *args = funcDecl->functionDeclaration.functionSignature | ||||
|                      ->functionSignature.arguments; | ||||
| 
 | ||||
|     uint32_t i; | ||||
|     for (i = 0; i < args->functionArgumentSequence.count; i += 1) | ||||
|     { | ||||
|         Node *arg = args->functionArgumentSequence.sequence[i]; | ||||
|         if (arg->syntaxKind != Declaration) | ||||
|         { | ||||
|             fprintf( | ||||
|                 stderr, | ||||
|                 "wraith: Encountered %s node in function signature args " | ||||
|                 "list.\n", | ||||
|                 SyntaxKindString(arg->syntaxKind)); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         Node *argId = GetIdFromDeclaration(arg); | ||||
|         if (argId != NULL && strcmp(target, argId->identifier.name) == 0) | ||||
|             return argId; | ||||
|     } | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| Node *LookupStructInternalId(Node *structDecl, char *target) | ||||
| { | ||||
|     Node *decls = structDecl->structDeclaration.declarationSequence; | ||||
| 
 | ||||
|     uint32_t i; | ||||
|     for (i = 0; i < decls->declarationSequence.count; i += 1) | ||||
|     { | ||||
|         Node *match = TryGetId(decls->declarationSequence.sequence[i]); | ||||
|         if (match != NULL && strcmp(target, match->identifier.name) == 0) | ||||
|             return match; | ||||
|     } | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| Node *InspectNode(Node *node, char *target) | ||||
| { | ||||
|     /* If this node may have an identifier declaration inside it, attempt to
 | ||||
|      * look up the identifier | ||||
|      * node itself, returning it if it matches the given target name. */ | ||||
|     if (NodeMayHaveId(node)) | ||||
|     { | ||||
|         Node *candidateId = TryGetId(node); | ||||
|         if (candidateId != NULL && | ||||
|             strcmp(target, candidateId->identifier.name) == 0) | ||||
|             return candidateId; | ||||
|     } | ||||
| 
 | ||||
|     /* If the candidate node was not the one we wanted, but the node node is a
 | ||||
|      * function declaration, it's possible that the identifier we want is one of | ||||
|      * the function's parameters rather than the function's name itself. */ | ||||
|     if (node->syntaxKind == FunctionDeclaration) | ||||
|     { | ||||
|         Node *match = LookupFunctionArgId(node, target); | ||||
|         if (match != NULL) | ||||
|             return match; | ||||
|     } | ||||
| 
 | ||||
|     /* Likewise if the node node is a struct declaration, inspect the struct's
 | ||||
|      * internals | ||||
|      * to see if a top-level definition is the one we're looking for. */ | ||||
|     if (node->syntaxKind == StructDeclaration) | ||||
|     { | ||||
|         Node *match = LookupStructInternalId(node, target); | ||||
|         if (match != NULL) | ||||
|             return match; | ||||
|     } | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| /* FIXME: Handle staged lookups for AccessExpressions. */ | ||||
| /* FIXME: Similar to above, disallow inspection of struct internals outside of
 | ||||
|  *        AccessExpressions. */ | ||||
| Node *LookupId(Node *current, Node *prev, char *target) | ||||
| { | ||||
|     if (current == NULL) | ||||
|         return NULL; | ||||
| 
 | ||||
|     Node *match; | ||||
| 
 | ||||
|     /* First inspect the current node to see if it contains the target
 | ||||
|      * identifier. */ | ||||
|     match = InspectNode(current, target); | ||||
|     if (match != NULL) | ||||
|         return match; | ||||
| 
 | ||||
|     /* If this is the start of our search, we should not attempt to look at
 | ||||
|      * child nodes. Only looking up the AST is valid at this point. | ||||
|      * | ||||
|      * This has the notable side-effect that this function will return NULL if | ||||
|      * you attempt to look up a struct's internals starting from the node | ||||
|      * representing the struct itself. The same is true for functions. */ | ||||
|     if (prev == NULL) | ||||
|         return LookupId(current->parent, current, target); | ||||
| 
 | ||||
|     uint32_t i; | ||||
|     uint32_t idxLimit; | ||||
|     switch (current->syntaxKind) | ||||
|     { | ||||
|     case DeclarationSequence: | ||||
|         for (i = 0; i < current->declarationSequence.count; i += 1) | ||||
|         { | ||||
|             Node *decl = current->declarationSequence.sequence[i]; | ||||
|             match = InspectNode(decl, target); | ||||
|             if (match != NULL) | ||||
|                 return match; | ||||
|         } | ||||
|         break; | ||||
|     case StatementSequence: | ||||
|         idxLimit = current->statementSequence.count; | ||||
|         for (i = 0; i < current->statementSequence.count; i += 1) | ||||
|         { | ||||
|             if (current->statementSequence.sequence[i] == prev) | ||||
|             { | ||||
|                 idxLimit = i; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for (i = 0; i < idxLimit; i += 1) | ||||
|         { | ||||
|             Node *stmt = current->statementSequence.sequence[i]; | ||||
|             if (stmt == prev) | ||||
|                 break; | ||||
| 
 | ||||
|             match = InspectNode(stmt, target); | ||||
|             if (match != NULL) | ||||
|                 return match; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     return LookupId(current->parent, current, target); | ||||
| } | ||||
| 
 | ||||
| /* FIXME: This function should be extended to handle multi-stage ID lookups for
 | ||||
|  *        AccessExpression nodes. */ | ||||
| /* FIXME: Make this function return an error status object of some kind.
 | ||||
|  *        A non-OK status should halt compilation. */ | ||||
| void ValidateIdentifiers(Node *node) | ||||
| { | ||||
|     if (node == NULL) | ||||
|         return; | ||||
| 
 | ||||
|     /* Skip over generic arguments. They contain Identifiers but are not
 | ||||
|      * actually identifiers, they declare types. */ | ||||
|     if (node->syntaxKind == GenericDeclarations) | ||||
|         return; | ||||
| 
 | ||||
|     if (node->syntaxKind != Identifier) | ||||
|     { | ||||
|         Recurse(node, *ValidateIdentifiers); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     char *name = node->identifier.name; | ||||
|     Node *decl = LookupId(node, NULL, name); | ||||
|     if (decl == NULL) | ||||
|     { | ||||
|         /* FIXME: Express this case as an error with AST information, see the
 | ||||
|          *        FIXME comment above. */ | ||||
|         fprintf( | ||||
|             stderr, | ||||
|             "wraith: Could not find definition of identifier %s.\n", | ||||
|             name); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* FIXME: This function should be extended to handle multi-stage ID lookups for
 | ||||
|  *        AccessExpression nodes. */ | ||||
| void TagIdentifierTypes(Node *node) | ||||
| { | ||||
|     if (node == NULL) | ||||
|         return; | ||||
| 
 | ||||
|     switch (node->syntaxKind) | ||||
|     { | ||||
|     case AllocExpression: | ||||
|         node->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case Declaration: | ||||
|         node->declaration.identifier->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case FunctionDeclaration: | ||||
|         node->functionDeclaration.functionSignature->functionSignature | ||||
|             .identifier->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case StructDeclaration: | ||||
|         node->structDeclaration.identifier->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case GenericDeclaration: | ||||
|         node->genericDeclaration.identifier->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case Type: | ||||
|         node->typeTag = MakeTypeTag(node); | ||||
|         break; | ||||
| 
 | ||||
|     case Identifier: | ||||
|     { | ||||
|         if (node->typeTag != NULL) | ||||
|             return; | ||||
| 
 | ||||
|         char *name = node->identifier.name; | ||||
|         Node *declaration = LookupId(node, NULL, name); | ||||
|         /* FIXME: Remove this case once ValidateIdentifiers returns error status
 | ||||
|          * info and halts compilation. See ValidateIdentifiers FIXME. */ | ||||
|         if (declaration == NULL) | ||||
|         { | ||||
|             TypeTag *tag = (TypeTag *)malloc(sizeof(TypeTag)); | ||||
|             tag->type = Unknown; | ||||
|             node->typeTag = tag; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             node->typeTag = declaration->typeTag; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     Recurse(node, *TagIdentifierTypes); | ||||
| } | ||||
| 
 | ||||
| Node *LookupType(Node *current, char *target) | ||||
| { | ||||
|     if (current == NULL) | ||||
|         return NULL; | ||||
| 
 | ||||
|     switch (current->syntaxKind) | ||||
|     { | ||||
|     /* If we've encountered a function declaration, check to see if it's generic
 | ||||
|      * and, if so, if one of its type parameters is the target. */ | ||||
|     case FunctionDeclaration: | ||||
|     { | ||||
|         Node *typeArgs = current->functionDeclaration.functionSignature | ||||
|                              ->functionSignature.genericDeclarations; | ||||
|         uint32_t i; | ||||
|         for (i = 0; i < typeArgs->genericDeclarations.count; i += 1) | ||||
|         { | ||||
|             Node *arg = typeArgs->genericDeclarations.declarations[i]; | ||||
|             Node *argId = arg->genericDeclaration.identifier; | ||||
|             char *argName = argId->identifier.name; | ||||
|             /* note: return the GenericDeclaration, not the Identifier, so that
 | ||||
|              * the caller can differentiate between generics and customs. */ | ||||
|             if (strcmp(target, argName) == 0) | ||||
|             { | ||||
|                 return arg; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return LookupType(current->parent, target); | ||||
|     } | ||||
| 
 | ||||
|     case StructDeclaration: | ||||
|     { | ||||
|         uint32_t i; | ||||
|         Node *typeArgs = current->structDeclaration.genericDeclarations; | ||||
|         for (i = 0; i < typeArgs->genericDeclarations.count; i += 1) | ||||
|         { | ||||
|             Node *arg = typeArgs->genericDeclarations.declarations[i]; | ||||
|             Node *argId = arg->genericDeclaration.identifier; | ||||
|             char *argName = argId->identifier.name; | ||||
|             /* note: return the GenericDeclaration, not the Identifier, so that
 | ||||
|              * the caller can differentiate between generics and customs. */ | ||||
|             if (strcmp(target, argName) == 0) | ||||
|             { | ||||
|                 return arg; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Node *structId = GetIdFromStruct(current); | ||||
|         if (strcmp(target, structId->identifier.name) == 0) | ||||
|         { | ||||
|             return structId; | ||||
|         } | ||||
| 
 | ||||
|         return LookupType(current->parent, target); | ||||
|     } | ||||
| 
 | ||||
|     /* If we encounter a declaration sequence, search each of its children for
 | ||||
|      * struct definitions in case one of them is the target. */ | ||||
|     case DeclarationSequence: | ||||
|     { | ||||
|         uint32_t i; | ||||
|         for (i = 0; i < current->declarationSequence.count; i += 1) | ||||
|         { | ||||
|             Node *decl = current->declarationSequence.sequence[i]; | ||||
|             if (decl->syntaxKind == StructDeclaration) | ||||
|             { | ||||
|                 Node *structId = GetIdFromStruct(decl); | ||||
|                 if (strcmp(target, structId->identifier.name) == 0) | ||||
|                     return structId; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return LookupType(current->parent, target); | ||||
|     } | ||||
| 
 | ||||
|     default: | ||||
|         return LookupType(current->parent, target); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* FIXME: This function should be modified to handle type parameters over
 | ||||
|  * structs. */ | ||||
| void ConvertCustomsToGenerics(Node *node) | ||||
| { | ||||
|     if (node == NULL) | ||||
|         return; | ||||
| 
 | ||||
|     switch (node->syntaxKind) | ||||
|     { | ||||
|     case Declaration: | ||||
|     { | ||||
|         Node *id = node->declaration.identifier; | ||||
|         Node *type = node->declaration.type->type.typeNode; | ||||
|         if (type->syntaxKind == CustomTypeNode) | ||||
|         { | ||||
|             char *target = id->typeTag->value.customType; | ||||
|             Node *typeLookup = LookupType(node, target); | ||||
|             if (typeLookup != NULL && | ||||
|                 typeLookup->syntaxKind == GenericDeclaration) | ||||
|             { | ||||
|                 id->typeTag->type = Generic; | ||||
|                 free(node->declaration.type); | ||||
|                 node->declaration.type = | ||||
|                     MakeGenericTypeNode(id->typeTag->value.genericType); | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case FunctionSignature: | ||||
|     { | ||||
|         Node *id = node->functionSignature.identifier; | ||||
|         Node *type = node->functionSignature.type->type.typeNode; | ||||
|         if (type->syntaxKind == CustomTypeNode) | ||||
|         { | ||||
|             char *target = id->typeTag->value.customType; | ||||
|             Node *typeLookup = LookupType(node, target); | ||||
|             if (typeLookup != NULL && | ||||
|                 typeLookup->syntaxKind == GenericDeclaration) | ||||
|             { | ||||
|                 id->typeTag->type = Generic; | ||||
|                 free(node->functionSignature.type); | ||||
|                 node->functionSignature.type = | ||||
|                     MakeGenericTypeNode(id->typeTag->value.genericType); | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case GenericArgument: | ||||
|     { | ||||
|         Node *typeNode = node->genericArgument.type; | ||||
|         if (typeNode->typeTag->type == Custom) | ||||
|         { | ||||
|             char *target = typeNode->typeTag->value.customType; | ||||
|             Node *typeLookup = LookupType(node, target); | ||||
|             if (typeLookup != NULL && | ||||
|                 typeLookup->syntaxKind == GenericDeclaration) | ||||
|             { | ||||
|                 typeNode->typeTag->type = Generic; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|     } | ||||
| 
 | ||||
|     Recurse(node, *ConvertCustomsToGenerics); | ||||
| } | ||||
|  | @ -0,0 +1,10 @@ | |||
| #ifndef WRAITH_VALIDATION_H | ||||
| #define WRAITH_VALIDATION_H | ||||
| 
 | ||||
| #include "ast.h" | ||||
| 
 | ||||
| void ValidateIdentifiers(Node *node); | ||||
| void TagIdentifierTypes(Node *node); | ||||
| void ConvertCustomsToGenerics(Node *node); | ||||
| 
 | ||||
| #endif /* WRAITH_VALIDATION_H */ | ||||
		Loading…
	
		Reference in New Issue