Compare commits
	
		
			1 Commits 
		
	
	
	| Author | SHA1 | Date | 
|---|---|---|
| 
							
							
								
								 | 
						f46630b0ab | 
							
								
								
									
										166
									
								
								.clang-format
								
								
								
								
							
							
						
						
									
										166
									
								
								.clang-format
								
								
								
								
							| 
						 | 
				
			
			@ -1,166 +0,0 @@
 | 
			
		|||
---
 | 
			
		||||
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")
 | 
			
		||||
BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t -Wcounterexamples")
 | 
			
		||||
FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c)
 | 
			
		||||
 | 
			
		||||
ADD_FLEX_BISON_DEPENDENCY(Scanner Parser)
 | 
			
		||||
| 
						 | 
				
			
			@ -42,13 +42,9 @@ 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}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								access.w
								
								
								
								
							
							
						
						
									
										13
									
								
								access.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,13 +0,0 @@
 | 
			
		|||
struct G {
 | 
			
		||||
    Foo(t: bool): bool {
 | 
			
		||||
        return t;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Program {
 | 
			
		||||
    static main(): int {
 | 
			
		||||
        g: G = alloc G;
 | 
			
		||||
        g.Foo(true);
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
struct Program { 
 | 
			
		||||
    // This triggers a parse error
 | 
			
		||||
    static Main(): int {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								example.w
								
								
								
								
							
							
						
						
									
										14
									
								
								example.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,6 +1,16 @@
 | 
			
		|||
interface Increments
 | 
			
		||||
{
 | 
			
		||||
    Increment(): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct YourStruct
 | 
			
		||||
{
 | 
			
		||||
    yourInt: int;
 | 
			
		||||
 | 
			
		||||
    IncrementOther<T: Increments>(other: T): void
 | 
			
		||||
    {
 | 
			
		||||
        other.Increment();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct MyStruct
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +64,6 @@ struct Program
 | 
			
		|||
            myStruct.myInt = 4;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Console.PrintLine("%i", myStruct.myInt);
 | 
			
		||||
 | 
			
		||||
        return 0;
 | 
			
		||||
        return myStruct.myInt;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,7 +41,6 @@
 | 
			
		|||
";"                         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,7 +55,6 @@ extern FILE *yyin;
 | 
			
		|||
%token SEMICOLON
 | 
			
		||||
%token COLON
 | 
			
		||||
%token QUESTION
 | 
			
		||||
%token AT
 | 
			
		||||
%token LEFT_PAREN
 | 
			
		||||
%token RIGHT_PAREN
 | 
			
		||||
%token LEFT_BRACE
 | 
			
		||||
| 
						 | 
				
			
			@ -109,17 +108,9 @@ BaseType                : VOID
 | 
			
		|||
                        {
 | 
			
		||||
                            $$ = MakePrimitiveTypeNode(Bool);
 | 
			
		||||
                        }
 | 
			
		||||
                        | MEMORYADDRESS
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakePrimitiveTypeNode(MemoryAddress);
 | 
			
		||||
                        }
 | 
			
		||||
                        | Identifier GenericArgumentClauseNonEmpty
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeConcreteGenericTypeNode($1, $2);
 | 
			
		||||
                        }
 | 
			
		||||
                        | Identifier
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeCustomTypeNode($1);
 | 
			
		||||
                            $$ = MakeCustomTypeNode(yytext);
 | 
			
		||||
                        }
 | 
			
		||||
                        | REFERENCE LESS_THAN Type GREATER_THAN
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			@ -151,40 +142,11 @@ 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
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +158,6 @@ PrimaryExpression       : Number
 | 
			
		|||
                        }
 | 
			
		||||
                        | FunctionCallExpression
 | 
			
		||||
                        | AccessExpression
 | 
			
		||||
                        | StructInitExpression
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
UnaryExpression         : BANG Expression
 | 
			
		||||
| 
						 | 
				
			
			@ -270,13 +231,9 @@ ReturnStatement         : RETURN Expression
 | 
			
		|||
                            $$ = MakeReturnVoidStatementNode();
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
FunctionCallExpression  : AccessExpression GenericArgumentClause LEFT_PAREN Arguments RIGHT_PAREN
 | 
			
		||||
FunctionCallExpression  : AccessExpression LEFT_PAREN Arguments RIGHT_PAREN
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeFunctionCallExpressionNode($1, $4, $2);
 | 
			
		||||
                        }
 | 
			
		||||
                        | SystemCallExpression GenericArgumentClause LEFT_PAREN Arguments RIGHT_PAREN
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeSystemCallExpressionNode($1, $4, $2);
 | 
			
		||||
                            $$ = MakeFunctionCallExpressionNode($1, $3);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
PartialStatement        : FunctionCallExpression
 | 
			
		||||
| 
						 | 
				
			
			@ -319,11 +276,11 @@ Statements              : Statement
 | 
			
		|||
                            $$ = AddStatement($1, $2);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
Arguments               : Expression
 | 
			
		||||
Arguments               : PrimaryExpression
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = StartFunctionArgumentSequenceNode($1);
 | 
			
		||||
                        }
 | 
			
		||||
                        | Arguments COMMA Expression
 | 
			
		||||
                        | Arguments COMMA PrimaryExpression
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = AddFunctionArgumentNode($1, $3);
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			@ -351,63 +308,40 @@ Body                    : LEFT_BRACE Statements RIGHT_BRACE
 | 
			
		|||
                            $$ = $2;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
GenericDeclaration      : Identifier
 | 
			
		||||
GenericConstraint       : Identifier COLON Identifier
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeGenericDeclarationNode($1, NULL);
 | 
			
		||||
                            $$ = MakeGenericConstraintNode($1, $3);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
GenericDeclarations     : GenericDeclaration
 | 
			
		||||
GenericConstraints      : GenericConstraint
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = StartGenericDeclarationsNode($1);
 | 
			
		||||
                            $$ = StartGenericConstraintsNode($1);
 | 
			
		||||
                        }
 | 
			
		||||
                        | GenericDeclarations COMMA GenericDeclaration
 | 
			
		||||
                        | GenericConstraints COMMA GenericConstraint
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = AddGenericDeclaration($1, $3);
 | 
			
		||||
                            $$ = AddGenericConstraint($1, $3);
 | 
			
		||||
                        }
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
GenericDeclarationClause    : LESS_THAN GenericDeclarations GREATER_THAN
 | 
			
		||||
                            {
 | 
			
		||||
                                $$ = $2;
 | 
			
		||||
                            }
 | 
			
		||||
                            |
 | 
			
		||||
                            {
 | 
			
		||||
                                $$ = MakeEmptyGenericDeclarationsNode();
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
GenericArgument         : Type
 | 
			
		||||
GenericConstraintClause : LESS_THAN GenericConstraints GREATER_THAN
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeGenericArgumentNode($1);
 | 
			
		||||
                            $$ = $2;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
GenericArguments        : GenericArgument
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = StartGenericArgumentsNode($1);
 | 
			
		||||
                        }
 | 
			
		||||
                        | GenericArguments COMMA GenericArgument
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = AddGenericArgument($1, $3);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
GenericArgumentClauseNonEmpty   : LESS_THAN GenericArguments GREATER_THAN
 | 
			
		||||
                                {
 | 
			
		||||
                                    $$ = $2;
 | 
			
		||||
                                }
 | 
			
		||||
                                ;
 | 
			
		||||
 | 
			
		||||
GenericArgumentClause   : GenericArgumentClauseNonEmpty
 | 
			
		||||
                        |
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeEmptyGenericArgumentsNode();
 | 
			
		||||
                            $$ = MakeEmptyGenericConstraintsNode();
 | 
			
		||||
                        }
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
FunctionSignature       : Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
 | 
			
		||||
/* FIXME: modifiers should be recursive */
 | 
			
		||||
FunctionSignature       : Identifier GenericConstraintClause 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
 | 
			
		||||
                        | STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
 | 
			
		||||
                        {
 | 
			
		||||
                            Node *modifier = MakeStaticNode();
 | 
			
		||||
                            $$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3);
 | 
			
		||||
                            $$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1), MakeEmptyGenericConstraintsNode());
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
FunctionDeclaration     : FunctionSignature Body
 | 
			
		||||
| 
						 | 
				
			
			@ -415,11 +349,29 @@ FunctionDeclaration     : FunctionSignature Body
 | 
			
		|||
                            $$ = MakeFunctionDeclarationNode($1, $2);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
StructDeclaration       : STRUCT Identifier GenericDeclarationClause LEFT_BRACE Declarations RIGHT_BRACE
 | 
			
		||||
StructDeclaration       : STRUCT Identifier LEFT_BRACE Declarations RIGHT_BRACE
 | 
			
		||||
                        {
 | 
			
		||||
                            $$ = MakeStructDeclarationNode($2, $5, $3);
 | 
			
		||||
                            $$ = MakeStructDeclarationNode($2, $4);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
                        ;
 | 
			
		||||
| 
						 | 
				
			
			@ -433,7 +385,9 @@ Declarations            : Declaration
 | 
			
		|||
                            $$ = AddDeclarationNode($1, $2);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
TopLevelDeclaration     : StructDeclaration;
 | 
			
		||||
TopLevelDeclaration     : StructDeclaration
 | 
			
		||||
                        | InterfaceDeclaration
 | 
			
		||||
                        ;
 | 
			
		||||
 | 
			
		||||
TopLevelDeclarations    : TopLevelDeclaration
 | 
			
		||||
                        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										59
									
								
								generic.w
								
								
								
								
							
							
						
						
									
										59
									
								
								generic.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,59 +0,0 @@
 | 
			
		|||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								iftest.w
								
								
								
								
							
							
						
						
									
										44
									
								
								iftest.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,44 +0,0 @@
 | 
			
		|||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								ordering.w
								
								
								
								
							
							
						
						
									
										15
									
								
								ordering.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,15 +0,0 @@
 | 
			
		|||
struct Foo {
 | 
			
		||||
    static Func(): void {
 | 
			
		||||
        Func2();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static Func2(): void {
 | 
			
		||||
        Func();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Program {
 | 
			
		||||
    static main(): int {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								reftest.w
								
								
								
								
							
							
						
						
									
										11
									
								
								reftest.w
								
								
								
								
							| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
struct MyStruct {
 | 
			
		||||
    foo: int;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Program {
 | 
			
		||||
    static Main(): int {
 | 
			
		||||
        myStruct: Reference<MyStruct>;
 | 
			
		||||
        myStruct = alloc MyStruct;
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										520
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										520
									
								
								src/ast.h
								
								
								
								
							| 
						 | 
				
			
			@ -3,15 +3,6 @@
 | 
			
		|||
 | 
			
		||||
#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,
 | 
			
		||||
| 
						 | 
				
			
			@ -19,11 +10,10 @@ typedef enum
 | 
			
		|||
    Assignment,
 | 
			
		||||
    BinaryExpression,
 | 
			
		||||
    Comment,
 | 
			
		||||
    ConcreteGenericTypeNode,
 | 
			
		||||
    CustomTypeNode,
 | 
			
		||||
    Declaration,
 | 
			
		||||
    DeclarationSequence,
 | 
			
		||||
    FieldInit,
 | 
			
		||||
    Expression,
 | 
			
		||||
    ForLoop,
 | 
			
		||||
    FunctionArgumentSequence,
 | 
			
		||||
    FunctionCallExpression,
 | 
			
		||||
| 
						 | 
				
			
			@ -31,14 +21,12 @@ typedef enum
 | 
			
		|||
    FunctionModifiers,
 | 
			
		||||
    FunctionSignature,
 | 
			
		||||
    FunctionSignatureArguments,
 | 
			
		||||
    GenericArgument,
 | 
			
		||||
    GenericArguments,
 | 
			
		||||
    GenericDeclaration,
 | 
			
		||||
    GenericDeclarations,
 | 
			
		||||
    GenericTypeNode,
 | 
			
		||||
    GenericConstraint,
 | 
			
		||||
    GenericConstraints,
 | 
			
		||||
    Identifier,
 | 
			
		||||
    IfStatement,
 | 
			
		||||
    IfElseStatement,
 | 
			
		||||
    InterfaceDeclaration,
 | 
			
		||||
    Number,
 | 
			
		||||
    PrimitiveTypeNode,
 | 
			
		||||
    ReferenceTypeNode,
 | 
			
		||||
| 
						 | 
				
			
			@ -48,9 +36,6 @@ typedef enum
 | 
			
		|||
    StaticModifier,
 | 
			
		||||
    StringLiteral,
 | 
			
		||||
    StructDeclaration,
 | 
			
		||||
    StructInit,
 | 
			
		||||
    StructInitFields,
 | 
			
		||||
    SystemCall,
 | 
			
		||||
    Type,
 | 
			
		||||
    UnaryExpression
 | 
			
		||||
} SyntaxKind;
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +65,7 @@ typedef enum
 | 
			
		|||
    UInt,
 | 
			
		||||
    Float,
 | 
			
		||||
    Double,
 | 
			
		||||
    String,
 | 
			
		||||
    MemoryAddress
 | 
			
		||||
    String
 | 
			
		||||
} PrimitiveType;
 | 
			
		||||
 | 
			
		||||
typedef union
 | 
			
		||||
| 
						 | 
				
			
			@ -90,378 +74,160 @@ typedef union
 | 
			
		|||
    BinaryOperator binaryOperator;
 | 
			
		||||
} Operator;
 | 
			
		||||
 | 
			
		||||
typedef struct TypeTag TypeTag;
 | 
			
		||||
 | 
			
		||||
typedef struct ConcreteGenericTypeTag
 | 
			
		||||
typedef struct Node
 | 
			
		||||
{
 | 
			
		||||
    char *name;
 | 
			
		||||
    TypeTag **genericArguments;
 | 
			
		||||
    uint32_t genericArgumentCount;
 | 
			
		||||
} ConcreteGenericTypeTag;
 | 
			
		||||
 | 
			
		||||
struct TypeTag
 | 
			
		||||
{
 | 
			
		||||
    enum Type
 | 
			
		||||
    {
 | 
			
		||||
        Unknown,
 | 
			
		||||
        Primitive,
 | 
			
		||||
        Reference,
 | 
			
		||||
        Custom,
 | 
			
		||||
        Generic,
 | 
			
		||||
        ConcreteGeneric
 | 
			
		||||
    } type;
 | 
			
		||||
    SyntaxKind syntaxKind;
 | 
			
		||||
    struct Node **children;
 | 
			
		||||
    uint32_t childCount;
 | 
			
		||||
    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;
 | 
			
		||||
    WRAITHNAMELESS union
 | 
			
		||||
        UnaryOperator unaryOperator;
 | 
			
		||||
        BinaryOperator binaryOperator;
 | 
			
		||||
    } operator;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
        struct
 | 
			
		||||
        {
 | 
			
		||||
            Node *accessee;
 | 
			
		||||
            Node *accessor;
 | 
			
		||||
        } accessExpression;
 | 
			
		||||
        char *string;
 | 
			
		||||
        uint64_t number;
 | 
			
		||||
    } value;
 | 
			
		||||
    PrimitiveType primitiveType;
 | 
			
		||||
} Node;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
        } 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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *SyntaxKindString(SyntaxKind syntaxKind);
 | 
			
		||||
char* strdup (const char* s);
 | 
			
		||||
const char* SyntaxKindString(SyntaxKind syntaxKind);
 | 
			
		||||
 | 
			
		||||
uint8_t IsPrimitiveType(Node *typeNode);
 | 
			
		||||
Node *MakePrimitiveTypeNode(PrimitiveType type);
 | 
			
		||||
Node *MakeCustomTypeNode(Node *identifierNode);
 | 
			
		||||
Node *MakeReferenceTypeNode(Node *typeNode);
 | 
			
		||||
Node *MakeConcreteGenericTypeNode(
 | 
			
		||||
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 *identifierNode,
 | 
			
		||||
    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 *interfaceNode
 | 
			
		||||
);
 | 
			
		||||
Node* StartGenericConstraintsNode(Node *genericNode);
 | 
			
		||||
Node* AddGenericConstraint(
 | 
			
		||||
    Node *genericsNode,
 | 
			
		||||
    Node *genericNode
 | 
			
		||||
);
 | 
			
		||||
Node* MakeEmptyGenericConstraintsNode();
 | 
			
		||||
Node* MakeFunctionSignatureNode(
 | 
			
		||||
    Node *identifierNode,
 | 
			
		||||
    Node *typeNode,
 | 
			
		||||
    Node *argumentsNode,
 | 
			
		||||
    Node *modifiersNode,
 | 
			
		||||
    Node *genericArgumentsNode);
 | 
			
		||||
Node *MakeFunctionDeclarationNode(
 | 
			
		||||
    Node *functionSignatureNode,
 | 
			
		||||
    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 *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 *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 *elseNode /* can be a conditional or a statement sequence */
 | 
			
		||||
    Node *genericConstraintsNode
 | 
			
		||||
);
 | 
			
		||||
Node *MakeForLoopNode(
 | 
			
		||||
Node* MakeFunctionDeclarationNode(
 | 
			
		||||
    Node *functionSignatureNode,
 | 
			
		||||
    Node *functionBodyNode
 | 
			
		||||
);
 | 
			
		||||
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 *MakeEmptyFunctionArgumentSequenceNode();
 | 
			
		||||
Node* MakeFunctionCallExpressionNode(
 | 
			
		||||
    Node *identifierNode,
 | 
			
		||||
    Node *argumentSequenceNode
 | 
			
		||||
);
 | 
			
		||||
Node* MakeAccessExpressionNode(
 | 
			
		||||
    Node *accessee,
 | 
			
		||||
    Node *accessor
 | 
			
		||||
);
 | 
			
		||||
Node* MakeAllocNode(
 | 
			
		||||
    Node *typeNode
 | 
			
		||||
);
 | 
			
		||||
Node* MakeIfNode(
 | 
			
		||||
    Node *expressionNode,
 | 
			
		||||
    Node *statementSequenceNode
 | 
			
		||||
);
 | 
			
		||||
Node* MakeIfElseNode(
 | 
			
		||||
    Node *ifNode,
 | 
			
		||||
    Node *statementSequenceNode
 | 
			
		||||
);
 | 
			
		||||
Node* MakeForLoopNode(
 | 
			
		||||
    Node *identifierNode,
 | 
			
		||||
    Node *startNumberNode,
 | 
			
		||||
    Node *endNumberNode,
 | 
			
		||||
    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);
 | 
			
		||||
    Node *statementSequenceNode
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
void PrintTree(Node *node, uint32_t tabCount);
 | 
			
		||||
 | 
			
		||||
#endif /* WRAITH_AST_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2280
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										2280
									
								
								src/codegen.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										46
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										46
									
								
								src/main.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,9 +1,8 @@
 | 
			
		|||
#include "../lib/dropt/dropt.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include "../lib/dropt/dropt.h"
 | 
			
		||||
 | 
			
		||||
#include "codegen.h"
 | 
			
		||||
#include "parser.h"
 | 
			
		||||
#include "validation.h"
 | 
			
		||||
#include "codegen.h"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -14,27 +13,10 @@ 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},
 | 
			
		||||
        {0} /* Required sentinel value. */
 | 
			
		||||
        { '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. */
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    dropt_context *droptContext = dropt_new_context(options);
 | 
			
		||||
| 
						 | 
				
			
			@ -50,13 +32,10 @@ int main(int argc, char *argv[])
 | 
			
		|||
    }
 | 
			
		||||
    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)
 | 
			
		||||
        {
 | 
			
		||||
            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)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,15 +64,6 @@ 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 "ast.h"
 | 
			
		||||
#include "y.tab.h"
 | 
			
		||||
#include "ast.h"
 | 
			
		||||
 | 
			
		||||
extern FILE *yyin;
 | 
			
		||||
extern int yydebug;
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ int Parse(char *inputFilename, Node **pRootNode, uint8_t parseVerbose)
 | 
			
		|||
    {
 | 
			
		||||
        if (parseVerbose)
 | 
			
		||||
        {
 | 
			
		||||
            PrintNode(*pRootNode, 0);
 | 
			
		||||
            PrintTree(*pRootNode, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else if (result == 1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										38
									
								
								src/util.c
								
								
								
								
							
							
						
						
									
										38
									
								
								src/util.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,38 +0,0 @@
 | 
			
		|||
#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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								src/util.h
								
								
								
								
							
							
						
						
									
										11
									
								
								src/util.h
								
								
								
								
							| 
						 | 
				
			
			@ -1,11 +0,0 @@
 | 
			
		|||
#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 */
 | 
			
		||||
							
								
								
									
										493
									
								
								src/validation.c
								
								
								
								
							
							
						
						
									
										493
									
								
								src/validation.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,493 +0,0 @@
 | 
			
		|||
#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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +0,0 @@
 | 
			
		|||
#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