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}) | 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) | FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) | ||||||
| 
 | 
 | ||||||
| ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) | ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) | ||||||
|  | @ -42,9 +42,13 @@ add_executable( | ||||||
| 	src/ast.h | 	src/ast.h | ||||||
| 	src/codegen.h | 	src/codegen.h | ||||||
| 	src/parser.h | 	src/parser.h | ||||||
|  | 	src/validation.h | ||||||
|  | 	src/util.h | ||||||
|     src/ast.c |     src/ast.c | ||||||
| 	src/codegen.c | 	src/codegen.c | ||||||
| 	src/parser.c | 	src/parser.c | ||||||
|  | 	src/validation.c | ||||||
|  | 	src/util.c | ||||||
| 	src/main.c | 	src/main.c | ||||||
| 	# Generated code | 	# Generated code | ||||||
|     ${BISON_Parser_OUTPUTS} |     ${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; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -54,6 +54,8 @@ struct Program | ||||||
|             myStruct.myInt = 4; |             myStruct.myInt = 4; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return myStruct.myInt; |         Console.PrintLine("%i", myStruct.myInt); | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| "double"                    return DOUBLE; | "double"                    return DOUBLE; | ||||||
| "string"                    return STRING; | "string"                    return STRING; | ||||||
| "bool"                      return BOOL; | "bool"                      return BOOL; | ||||||
|  | "MemoryAddress"             return MEMORYADDRESS; | ||||||
| "struct"                    return STRUCT; | "struct"                    return STRUCT; | ||||||
| "return"                    return RETURN; | "return"                    return RETURN; | ||||||
| "static"                    return STATIC; | "static"                    return STATIC; | ||||||
|  | @ -40,6 +41,7 @@ | ||||||
| ";"                         return SEMICOLON; | ";"                         return SEMICOLON; | ||||||
| ":"                         return COLON; | ":"                         return COLON; | ||||||
| "?"                         return QUESTION; | "?"                         return QUESTION; | ||||||
|  | "@"                         return AT; | ||||||
| "("                         return LEFT_PAREN; | "("                         return LEFT_PAREN; | ||||||
| ")"                         return RIGHT_PAREN; | ")"                         return RIGHT_PAREN; | ||||||
| "["                         return LEFT_BRACKET; | "["                         return LEFT_BRACKET; | ||||||
|  |  | ||||||
|  | @ -25,6 +25,7 @@ extern FILE *yyin; | ||||||
| %token DOUBLE | %token DOUBLE | ||||||
| %token STRING | %token STRING | ||||||
| %token BOOL | %token BOOL | ||||||
|  | %token MEMORYADDRESS | ||||||
| %token STRUCT | %token STRUCT | ||||||
| %token RETURN | %token RETURN | ||||||
| %token STATIC | %token STATIC | ||||||
|  | @ -54,6 +55,7 @@ extern FILE *yyin; | ||||||
| %token SEMICOLON | %token SEMICOLON | ||||||
| %token COLON | %token COLON | ||||||
| %token QUESTION | %token QUESTION | ||||||
|  | %token AT | ||||||
| %token LEFT_PAREN | %token LEFT_PAREN | ||||||
| %token RIGHT_PAREN | %token RIGHT_PAREN | ||||||
| %token LEFT_BRACE | %token LEFT_BRACE | ||||||
|  | @ -107,9 +109,17 @@ BaseType                : VOID | ||||||
|                         { |                         { | ||||||
|                             $$ = MakePrimitiveTypeNode(Bool); |                             $$ = MakePrimitiveTypeNode(Bool); | ||||||
|                         } |                         } | ||||||
|  |                         | MEMORYADDRESS | ||||||
|  |                         { | ||||||
|  |                             $$ = MakePrimitiveTypeNode(MemoryAddress); | ||||||
|  |                         } | ||||||
|  |                         | Identifier GenericArgumentClauseNonEmpty | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeConcreteGenericTypeNode($1, $2); | ||||||
|  |                         } | ||||||
|                         | Identifier |                         | Identifier | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeCustomTypeNode(yytext); |                             $$ = MakeCustomTypeNode($1); | ||||||
|                         } |                         } | ||||||
|                         | REFERENCE LESS_THAN Type GREATER_THAN |                         | REFERENCE LESS_THAN Type GREATER_THAN | ||||||
|                         { |                         { | ||||||
|  | @ -141,11 +151,40 @@ AccessExpression        : Identifier POINT AccessExpression | ||||||
|                             $$ = $1; |                             $$ = $1; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|  | SystemCallExpression    : AT Identifier | ||||||
|  |                         { | ||||||
|  |                             $$ = $2; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
| Number                  : NUMBER | Number                  : NUMBER | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeNumberNode(yytext); |                             $$ = 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 | PrimaryExpression       : Number | ||||||
|                         | STRING_LITERAL |                         | STRING_LITERAL | ||||||
|                         { |                         { | ||||||
|  | @ -157,6 +196,7 @@ PrimaryExpression       : Number | ||||||
|                         } |                         } | ||||||
|                         | FunctionCallExpression |                         | FunctionCallExpression | ||||||
|                         | AccessExpression |                         | AccessExpression | ||||||
|  |                         | StructInitExpression | ||||||
|                         ; |                         ; | ||||||
| 
 | 
 | ||||||
| UnaryExpression         : BANG Expression | UnaryExpression         : BANG Expression | ||||||
|  | @ -230,9 +270,13 @@ ReturnStatement         : RETURN Expression | ||||||
|                             $$ = MakeReturnVoidStatementNode(); |                             $$ = 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 | PartialStatement        : FunctionCallExpression | ||||||
|  | @ -275,11 +319,11 @@ Statements              : Statement | ||||||
|                             $$ = AddStatement($1, $2); |                             $$ = AddStatement($1, $2); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| Arguments               : PrimaryExpression | Arguments               : Expression | ||||||
|                         { |                         { | ||||||
|                             $$ = StartFunctionArgumentSequenceNode($1); |                             $$ = StartFunctionArgumentSequenceNode($1); | ||||||
|                         } |                         } | ||||||
|                         | Arguments COMMA PrimaryExpression |                         | Arguments COMMA Expression | ||||||
|                         { |                         { | ||||||
|                             $$ = AddFunctionArgumentNode($1, $3); |                             $$ = AddFunctionArgumentNode($1, $3); | ||||||
|                         } |                         } | ||||||
|  | @ -307,14 +351,63 @@ Body                    : LEFT_BRACE Statements RIGHT_BRACE | ||||||
|                             $$ = $2; |                             $$ = $2; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| FunctionSignature       : Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | GenericDeclaration      : Identifier | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeFunctionSignatureNode($1, $6, $3, MakeFunctionModifiersNode(NULL, 0)); |                             $$ = MakeGenericDeclarationNode($1, NULL); | ||||||
|                         } |                         } | ||||||
|                         | STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | 
 | ||||||
|  | GenericDeclarations     : GenericDeclaration | ||||||
|  |                         { | ||||||
|  |                             $$ = StartGenericDeclarationsNode($1); | ||||||
|  |                         } | ||||||
|  |                         | GenericDeclarations COMMA GenericDeclaration | ||||||
|  |                         { | ||||||
|  |                             $$ = AddGenericDeclaration($1, $3); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | GenericDeclarationClause    : LESS_THAN GenericDeclarations GREATER_THAN | ||||||
|  |                             { | ||||||
|  |                                 $$ = $2; | ||||||
|  |                             } | ||||||
|  |                             | | ||||||
|  |                             { | ||||||
|  |                                 $$ = MakeEmptyGenericDeclarationsNode(); | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  | GenericArgument         : Type | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeGenericArgumentNode($1); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | GenericArguments        : GenericArgument | ||||||
|  |                         { | ||||||
|  |                             $$ = StartGenericArgumentsNode($1); | ||||||
|  |                         } | ||||||
|  |                         | GenericArguments COMMA GenericArgument | ||||||
|  |                         { | ||||||
|  |                             $$ = AddGenericArgument($1, $3); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | GenericArgumentClauseNonEmpty   : LESS_THAN GenericArguments GREATER_THAN | ||||||
|  |                                 { | ||||||
|  |                                     $$ = $2; | ||||||
|  |                                 } | ||||||
|  |                                 ; | ||||||
|  | 
 | ||||||
|  | GenericArgumentClause   : GenericArgumentClauseNonEmpty | ||||||
|  |                         | | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeEmptyGenericArgumentsNode(); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | FunctionSignature       : Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); | ||||||
|  |                         } | ||||||
|  |                         | STATIC Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||||
|                         { |                         { | ||||||
|                             Node *modifier = MakeStaticNode(); |                             Node *modifier = MakeStaticNode(); | ||||||
|                             $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1)); |                             $$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| FunctionDeclaration     : FunctionSignature Body | FunctionDeclaration     : FunctionSignature Body | ||||||
|  | @ -322,9 +415,9 @@ FunctionDeclaration     : FunctionSignature Body | ||||||
|                             $$ = MakeFunctionDeclarationNode($1, $2); |                             $$ = 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); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| Declaration             : FunctionDeclaration | Declaration             : FunctionDeclaration | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										496
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										496
									
								
								src/ast.h
								
								
								
								
							|  | @ -3,6 +3,15 @@ | ||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| 
 | 
 | ||||||
|  | /* -Wpedantic nameless union/struct silencing */ | ||||||
|  | #ifndef WRAITHNAMELESS | ||||||
|  | #ifdef __GNUC__ | ||||||
|  | #define WRAITHNAMELESS __extension__ | ||||||
|  | #else | ||||||
|  | #define WRAITHNAMELESS | ||||||
|  | #endif /* __GNUC__ */ | ||||||
|  | #endif /* WRAITHNAMELESS */ | ||||||
|  | 
 | ||||||
| typedef enum | typedef enum | ||||||
| { | { | ||||||
|     AccessExpression, |     AccessExpression, | ||||||
|  | @ -10,10 +19,11 @@ typedef enum | ||||||
|     Assignment, |     Assignment, | ||||||
|     BinaryExpression, |     BinaryExpression, | ||||||
|     Comment, |     Comment, | ||||||
|  |     ConcreteGenericTypeNode, | ||||||
|     CustomTypeNode, |     CustomTypeNode, | ||||||
|     Declaration, |     Declaration, | ||||||
|     DeclarationSequence, |     DeclarationSequence, | ||||||
|     Expression, |     FieldInit, | ||||||
|     ForLoop, |     ForLoop, | ||||||
|     FunctionArgumentSequence, |     FunctionArgumentSequence, | ||||||
|     FunctionCallExpression, |     FunctionCallExpression, | ||||||
|  | @ -21,6 +31,11 @@ typedef enum | ||||||
|     FunctionModifiers, |     FunctionModifiers, | ||||||
|     FunctionSignature, |     FunctionSignature, | ||||||
|     FunctionSignatureArguments, |     FunctionSignatureArguments, | ||||||
|  |     GenericArgument, | ||||||
|  |     GenericArguments, | ||||||
|  |     GenericDeclaration, | ||||||
|  |     GenericDeclarations, | ||||||
|  |     GenericTypeNode, | ||||||
|     Identifier, |     Identifier, | ||||||
|     IfStatement, |     IfStatement, | ||||||
|     IfElseStatement, |     IfElseStatement, | ||||||
|  | @ -33,6 +48,9 @@ typedef enum | ||||||
|     StaticModifier, |     StaticModifier, | ||||||
|     StringLiteral, |     StringLiteral, | ||||||
|     StructDeclaration, |     StructDeclaration, | ||||||
|  |     StructInit, | ||||||
|  |     StructInitFields, | ||||||
|  |     SystemCall, | ||||||
|     Type, |     Type, | ||||||
|     UnaryExpression |     UnaryExpression | ||||||
| } SyntaxKind; | } SyntaxKind; | ||||||
|  | @ -62,7 +80,8 @@ typedef enum | ||||||
|     UInt, |     UInt, | ||||||
|     Float, |     Float, | ||||||
|     Double, |     Double, | ||||||
|     String |     String, | ||||||
|  |     MemoryAddress | ||||||
| } PrimitiveType; | } PrimitiveType; | ||||||
| 
 | 
 | ||||||
| typedef union | typedef union | ||||||
|  | @ -71,145 +90,378 @@ typedef union | ||||||
|     BinaryOperator binaryOperator; |     BinaryOperator binaryOperator; | ||||||
| } Operator; | } Operator; | ||||||
| 
 | 
 | ||||||
| typedef struct Node | typedef struct TypeTag TypeTag; | ||||||
|  | 
 | ||||||
|  | typedef struct ConcreteGenericTypeTag | ||||||
| { | { | ||||||
|     SyntaxKind syntaxKind; |     char *name; | ||||||
|     struct Node **children; |     TypeTag **genericArguments; | ||||||
|     uint32_t childCount; |     uint32_t genericArgumentCount; | ||||||
|  | } ConcreteGenericTypeTag; | ||||||
|  | 
 | ||||||
|  | struct TypeTag | ||||||
|  | { | ||||||
|  |     enum Type | ||||||
|  |     { | ||||||
|  |         Unknown, | ||||||
|  |         Primitive, | ||||||
|  |         Reference, | ||||||
|  |         Custom, | ||||||
|  |         Generic, | ||||||
|  |         ConcreteGeneric | ||||||
|  |     } type; | ||||||
|     union |     union | ||||||
|     { |     { | ||||||
|         UnaryOperator unaryOperator; |         /* Valid when type = Primitive. */ | ||||||
|         BinaryOperator binaryOperator; |         PrimitiveType primitiveType; | ||||||
|     } operator; |         /* Valid when type = Reference. */ | ||||||
|     union |         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; | ||||||
|  |     WRAITHNAMELESS 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; |             char *string; | ||||||
|         uint64_t number; |         } stringLiteral; | ||||||
|     } value; |  | ||||||
|     PrimitiveType primitiveType; |  | ||||||
| } Node; |  | ||||||
| 
 | 
 | ||||||
| char* strdup (const char* s); |         struct | ||||||
| const char* SyntaxKindString(SyntaxKind syntaxKind); |         { | ||||||
|  |             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; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||||
| 
 | 
 | ||||||
| uint8_t IsPrimitiveType(Node *typeNode); | uint8_t IsPrimitiveType(Node *typeNode); | ||||||
| Node* MakePrimitiveTypeNode( | Node *MakePrimitiveTypeNode(PrimitiveType type); | ||||||
|     PrimitiveType type | Node *MakeCustomTypeNode(Node *identifierNode); | ||||||
| ); | Node *MakeReferenceTypeNode(Node *typeNode); | ||||||
| Node* MakeCustomTypeNode( | Node *MakeConcreteGenericTypeNode( | ||||||
|     char *string |     Node *identifierNode, | ||||||
| ); |     Node *genericArgumentsNode); | ||||||
| Node* MakeReferenceTypeNode( | Node *MakeTypeNode(Node *typeNode); | ||||||
|     Node *typeNode | Node *MakeIdentifierNode(const char *id); | ||||||
| ); | Node *MakeNumberNode(const char *numberString); | ||||||
| Node* MakeTypeNode( | Node *MakeStringNode(const char *string); | ||||||
|     Node *typeNode /* can be primitive, custom, or reference */ | Node *MakeStaticNode(); | ||||||
| ); | Node *MakeFunctionModifiersNode(Node **pModifierNodes, uint32_t modifierCount); | ||||||
| Node* MakeIdentifierNode( | Node *MakeUnaryNode(UnaryOperator operator, Node * child); | ||||||
|     const char *id | Node *MakeBinaryNode(BinaryOperator operator, Node * left, Node *right); | ||||||
| ); | Node *MakeDeclarationNode(Node *typeNode, Node *identifierNode); | ||||||
| Node* MakeNumberNode( | Node *MakeAssignmentNode(Node *left, Node *right); | ||||||
|     const char *numberString | Node *StartStatementSequenceNode(Node *statementNode); | ||||||
| ); | Node *AddStatement(Node *statementSequenceNode, Node *statementNode); | ||||||
| Node* MakeStringNode( | Node *MakeReturnStatementNode(Node *expressionNode); | ||||||
|     const char *string | Node *MakeReturnVoidStatementNode(); | ||||||
| ); | Node *StartFunctionSignatureArgumentsNode(Node *argumentNode); | ||||||
| Node* MakeStaticNode(); | Node *AddFunctionSignatureArgumentNode(Node *argumentsNode, Node *argumentNode); | ||||||
| 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 *MakeEmptyFunctionSignatureArgumentsNode(); | ||||||
| Node* MakeFunctionSignatureNode( | Node *MakeFunctionSignatureNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node* typeNode, |     Node *typeNode, | ||||||
|     Node* argumentsNode, |     Node *argumentsNode, | ||||||
|     Node* modifiersNode |     Node *modifiersNode, | ||||||
| ); |     Node *genericArgumentsNode); | ||||||
| Node* MakeFunctionDeclarationNode( | Node *MakeFunctionDeclarationNode( | ||||||
|     Node* functionSignatureNode, |     Node *functionSignatureNode, | ||||||
|     Node* functionBodyNode |     Node *functionBodyNode); | ||||||
| ); | Node *MakeGenericDeclarationNode(Node *identifierNode, Node *constraintNode); | ||||||
| Node* MakeStructDeclarationNode( | 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 *identifierNode, | ||||||
|     Node *declarationSequenceNode |  | ||||||
| ); |  | ||||||
| Node* StartDeclarationSequenceNode( |  | ||||||
|     Node *declarationNode |  | ||||||
| ); |  | ||||||
| Node* AddDeclarationNode( |  | ||||||
|     Node *declarationSequenceNode, |     Node *declarationSequenceNode, | ||||||
|     Node *declarationNode |     Node *genericArgumentsNode); | ||||||
| ); | Node *StartDeclarationSequenceNode(Node *declarationNode); | ||||||
| Node *StartFunctionArgumentSequenceNode( | Node *AddDeclarationNode(Node *declarationSequenceNode, Node *declarationNode); | ||||||
|     Node *argumentNode | Node *StartFunctionArgumentSequenceNode(Node *argumentNode); | ||||||
| ); | Node *AddFunctionArgumentNode(Node *argumentSequenceNode, Node *argumentNode); | ||||||
| Node *AddFunctionArgumentNode( |  | ||||||
|     Node *argumentSequenceNode, |  | ||||||
|     Node *argumentNode |  | ||||||
| ); |  | ||||||
| Node *MakeEmptyFunctionArgumentSequenceNode(); | Node *MakeEmptyFunctionArgumentSequenceNode(); | ||||||
| Node* MakeFunctionCallExpressionNode( | Node *MakeFunctionCallExpressionNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *argumentSequenceNode |     Node *argumentSequenceNode, | ||||||
| ); |     Node *genericArgumentsNode); | ||||||
| Node* MakeAccessExpressionNode( | Node *MakeSystemCallExpressionNode( | ||||||
|     Node *accessee, |     Node *identifierNode, | ||||||
|     Node *accessor |     Node *argumentSequenceNode, | ||||||
| ); |     Node *genericArgumentsNode); | ||||||
| Node* MakeAllocNode( | Node *MakeAccessExpressionNode(Node *accessee, Node *accessor); | ||||||
|     Node *typeNode | Node *MakeAllocNode(Node *typeNode); | ||||||
| ); | Node *MakeIfNode(Node *expressionNode, Node *statementSequenceNode); | ||||||
| Node* MakeIfNode( | Node *MakeIfElseNode( | ||||||
|     Node *expressionNode, |  | ||||||
|     Node *statementSequenceNode |  | ||||||
| ); |  | ||||||
| Node* MakeIfElseNode( |  | ||||||
|     Node *ifNode, |     Node *ifNode, | ||||||
|     Node *statementSequenceNode |     Node *elseNode /* can be a conditional or a statement sequence */ | ||||||
| ); | ); | ||||||
| Node* MakeForLoopNode( | Node *MakeForLoopNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *startNumberNode, |     Node *startNumberNode, | ||||||
|     Node *endNumberNode, |     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 */ | #endif /* WRAITH_AST_H */ | ||||||
|  |  | ||||||
							
								
								
									
										2061
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										2061
									
								
								src/codegen.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										46
									
								
								src/main.c
								
								
								
								
							|  | @ -1,8 +1,9 @@ | ||||||
| #include <stdlib.h> |  | ||||||
| #include "../lib/dropt/dropt.h" | #include "../lib/dropt/dropt.h" | ||||||
|  | #include <stdlib.h> | ||||||
| 
 | 
 | ||||||
| #include "parser.h" |  | ||||||
| #include "codegen.h" | #include "codegen.h" | ||||||
|  | #include "parser.h" | ||||||
|  | #include "validation.h" | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|  | @ -13,10 +14,27 @@ int main(int argc, char *argv[]) | ||||||
|     int exitCode = EXIT_SUCCESS; |     int exitCode = EXIT_SUCCESS; | ||||||
| 
 | 
 | ||||||
|     dropt_option options[] = { |     dropt_option options[] = { | ||||||
|         { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, |         {'h', | ||||||
|         { 'v', "parse-verbose", "Shows verbose parser output.", NULL, dropt_handle_bool, &parseVerbose }, |          "help", | ||||||
|         { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, |          "Shows help.", | ||||||
|         { 0 } /* Required sentinel value. */ |          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. */ | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     dropt_context *droptContext = dropt_new_context(options); |     dropt_context *droptContext = dropt_new_context(options); | ||||||
|  | @ -32,10 +50,13 @@ int main(int argc, char *argv[]) | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         char** rest = dropt_parse(droptContext, -1, &argv[1]); |         char **rest = dropt_parse(droptContext, -1, &argv[1]); | ||||||
|         if (dropt_get_error(droptContext) != dropt_error_none) |         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; |             exitCode = EXIT_FAILURE; | ||||||
|         } |         } | ||||||
|         else if (showHelp) |         else if (showHelp) | ||||||
|  | @ -64,6 +85,15 @@ int main(int argc, char *argv[]) | ||||||
|                 } |                 } | ||||||
|                 else |                 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); |                     exitCode = Codegen(rootNode, optimizationLevel); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
| #include "y.tab.h" |  | ||||||
| #include "ast.h" | #include "ast.h" | ||||||
|  | #include "y.tab.h" | ||||||
| 
 | 
 | ||||||
| extern FILE *yyin; | extern FILE *yyin; | ||||||
| extern int yydebug; | extern int yydebug; | ||||||
|  | @ -31,7 +31,7 @@ int Parse(char *inputFilename, Node **pRootNode, uint8_t parseVerbose) | ||||||
|     { |     { | ||||||
|         if (parseVerbose) |         if (parseVerbose) | ||||||
|         { |         { | ||||||
|             PrintTree(*pRootNode, 0); |             PrintNode(*pRootNode, 0); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else if (result == 1) |     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