forked from cosmonaut/wraith-lang
				
			Compare commits
	
		
			6 Commits 
		
	
	
		
			generics_r
			...
			main
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 9adfaed54c | |
|  | a571edcf6d | |
|  | ea203e6c3c | |
|  | 61344f5b60 | |
|  | 506ee9ecad | |
|  | d9b01515eb | 
|  | @ -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,9 +351,32 @@ Body                    : LEFT_BRACE Statements RIGHT_BRACE | ||||||
|                             $$ = $2; |                             $$ = $2; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| GenericArgument         : Identifier | GenericDeclaration      : Identifier | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeGenericArgumentNode($1, NULL); |                             $$ = MakeGenericDeclarationNode($1, NULL); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | GenericDeclarations     : GenericDeclaration | ||||||
|  |                         { | ||||||
|  |                             $$ = StartGenericDeclarationsNode($1); | ||||||
|  |                         } | ||||||
|  |                         | GenericDeclarations COMMA GenericDeclaration | ||||||
|  |                         { | ||||||
|  |                             $$ = AddGenericDeclaration($1, $3); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | GenericDeclarationClause    : LESS_THAN GenericDeclarations GREATER_THAN | ||||||
|  |                             { | ||||||
|  |                                 $$ = $2; | ||||||
|  |                             } | ||||||
|  |                             | | ||||||
|  |                             { | ||||||
|  |                                 $$ = MakeEmptyGenericDeclarationsNode(); | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  | GenericArgument         : Type | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeGenericArgumentNode($1); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| GenericArguments        : GenericArgument | GenericArguments        : GenericArgument | ||||||
|  | @ -321,21 +388,23 @@ GenericArguments        : GenericArgument | ||||||
|                             $$ = AddGenericArgument($1, $3); |                             $$ = AddGenericArgument($1, $3); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| GenericArgumentsClause  : LESS_THAN GenericArguments GREATER_THAN | GenericArgumentClauseNonEmpty   : LESS_THAN GenericArguments GREATER_THAN | ||||||
|                         { |                                 { | ||||||
|                             $$ = $2; |                                     $$ = $2; | ||||||
|                         } |                                 } | ||||||
|  |                                 ; | ||||||
|  | 
 | ||||||
|  | GenericArgumentClause   : GenericArgumentClauseNonEmpty | ||||||
|                         | |                         | | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeEmptyGenericArgumentsNode(); |                             $$ = MakeEmptyGenericArgumentsNode(); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| 
 | FunctionSignature       : Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||||
| FunctionSignature       : Identifier GenericArgumentsClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type |  | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); |                             $$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2); | ||||||
|                         } |                         } | ||||||
|                         | STATIC Identifier GenericArgumentsClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type |                         | STATIC Identifier GenericDeclarationClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type | ||||||
|                         { |                         { | ||||||
|                             Node *modifier = MakeStaticNode(); |                             Node *modifier = MakeStaticNode(); | ||||||
|                             $$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3); |                             $$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3); | ||||||
|  | @ -346,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 | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								generic.w
								
								
								
								
							
							
						
						
									
										47
									
								
								generic.w
								
								
								
								
							|  | @ -5,14 +5,55 @@ struct Foo { | ||||||
| 
 | 
 | ||||||
|     static Func<T>(t: T): T { |     static Func<T>(t: T): T { | ||||||
|         foo: T = t; |         foo: T = t; | ||||||
|         return Func2(foo); |         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 { | struct Program { | ||||||
|     static main(): int { |     static Main(): int { | ||||||
|         x: int = 4; |         x: int = 4; | ||||||
|         y: int = Foo.Func(x); |         y: int = Foo.Func(x); | ||||||
|         return 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; | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										396
									
								
								src/ast.c
								
								
								
								
							
							
						
						
									
										396
									
								
								src/ast.c
								
								
								
								
							|  | @ -19,6 +19,8 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) | ||||||
|         return "BinaryExpression"; |         return "BinaryExpression"; | ||||||
|     case Comment: |     case Comment: | ||||||
|         return "Comment"; |         return "Comment"; | ||||||
|  |     case ConcreteGenericTypeNode: | ||||||
|  |         return "ConcreteGenericTypeNode"; | ||||||
|     case CustomTypeNode: |     case CustomTypeNode: | ||||||
|         return "CustomTypeNode"; |         return "CustomTypeNode"; | ||||||
|     case Declaration: |     case Declaration: | ||||||
|  | @ -27,6 +29,8 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) | ||||||
|         return "ForLoop"; |         return "ForLoop"; | ||||||
|     case DeclarationSequence: |     case DeclarationSequence: | ||||||
|         return "DeclarationSequence"; |         return "DeclarationSequence"; | ||||||
|  |     case FieldInit: | ||||||
|  |         return "FieldInit"; | ||||||
|     case FunctionArgumentSequence: |     case FunctionArgumentSequence: | ||||||
|         return "FunctionArgumentSequence"; |         return "FunctionArgumentSequence"; | ||||||
|     case FunctionCallExpression: |     case FunctionCallExpression: | ||||||
|  | @ -43,6 +47,10 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) | ||||||
|         return "GenericArgument"; |         return "GenericArgument"; | ||||||
|     case GenericArguments: |     case GenericArguments: | ||||||
|         return "GenericArguments"; |         return "GenericArguments"; | ||||||
|  |     case GenericDeclaration: | ||||||
|  |         return "GenericDeclaration"; | ||||||
|  |     case GenericDeclarations: | ||||||
|  |         return "GenericDeclarations"; | ||||||
|     case GenericTypeNode: |     case GenericTypeNode: | ||||||
|         return "GenericTypeNode"; |         return "GenericTypeNode"; | ||||||
|     case Identifier: |     case Identifier: | ||||||
|  | @ -67,6 +75,12 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) | ||||||
|         return "StringLiteral"; |         return "StringLiteral"; | ||||||
|     case StructDeclaration: |     case StructDeclaration: | ||||||
|         return "StructDeclaration"; |         return "StructDeclaration"; | ||||||
|  |     case StructInit: | ||||||
|  |         return "StructInit"; | ||||||
|  |     case StructInitFields: | ||||||
|  |         return "StructInitFields"; | ||||||
|  |     case SystemCall: | ||||||
|  |         return "SystemCall"; | ||||||
|     case Type: |     case Type: | ||||||
|         return "Type"; |         return "Type"; | ||||||
|     case UnaryExpression: |     case UnaryExpression: | ||||||
|  | @ -89,11 +103,12 @@ Node *MakePrimitiveTypeNode(PrimitiveType type) | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Node *MakeCustomTypeNode(char *name) | Node *MakeCustomTypeNode(Node *identifierNode) | ||||||
| { | { | ||||||
|     Node *node = (Node *)malloc(sizeof(Node)); |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|     node->syntaxKind = CustomTypeNode; |     node->syntaxKind = CustomTypeNode; | ||||||
|     node->customType.name = strdup(name); |     node->customType.name = strdup(identifierNode->identifier.name); | ||||||
|  |     free(identifierNode); | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -105,6 +120,18 @@ Node *MakeReferenceTypeNode(Node *typeNode) | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Node *MakeConcreteGenericTypeNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *genericArgumentsNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = ConcreteGenericTypeNode; | ||||||
|  |     node->concreteGenericType.name = strdup(identifierNode->identifier.name); | ||||||
|  |     node->concreteGenericType.genericArguments = genericArgumentsNode; | ||||||
|  |     free(identifierNode); | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Node *MakeTypeNode(Node *typeNode) | Node *MakeTypeNode(Node *typeNode) | ||||||
| { | { | ||||||
|     Node *node = (Node *)malloc(sizeof(Node)); |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  | @ -286,7 +313,7 @@ Node *MakeFunctionSignatureNode( | ||||||
|     node->functionSignature.type = typeNode; |     node->functionSignature.type = typeNode; | ||||||
|     node->functionSignature.arguments = arguments; |     node->functionSignature.arguments = arguments; | ||||||
|     node->functionSignature.modifiers = modifiersNode; |     node->functionSignature.modifiers = modifiersNode; | ||||||
|     node->functionSignature.genericArguments = genericArgumentsNode; |     node->functionSignature.genericDeclarations = genericArgumentsNode; | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -303,12 +330,14 @@ Node *MakeFunctionDeclarationNode( | ||||||
| 
 | 
 | ||||||
| Node *MakeStructDeclarationNode( | Node *MakeStructDeclarationNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *declarationSequenceNode) |     Node *declarationSequenceNode, | ||||||
|  |     Node *genericArgumentsNode) | ||||||
| { | { | ||||||
|     Node *node = (Node *)malloc(sizeof(Node)); |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|     node->syntaxKind = StructDeclaration; |     node->syntaxKind = StructDeclaration; | ||||||
|     node->structDeclaration.identifier = identifierNode; |     node->structDeclaration.identifier = identifierNode; | ||||||
|     node->structDeclaration.declarationSequence = declarationSequenceNode; |     node->structDeclaration.declarationSequence = declarationSequenceNode; | ||||||
|  |     node->structDeclaration.genericDeclarations = genericArgumentsNode; | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -367,12 +396,55 @@ Node *MakeEmptyFunctionArgumentSequenceNode() | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode) | Node *MakeGenericDeclarationNode(Node *identifierNode, Node *constraintNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = GenericDeclaration; | ||||||
|  |     node->genericDeclaration.identifier = identifierNode; | ||||||
|  |     node->genericDeclaration.constraint = constraintNode; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *StartGenericDeclarationsNode(Node *genericArgumentNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = GenericDeclarations; | ||||||
|  |     node->genericDeclarations.declarations = (Node **)malloc(sizeof(Node *)); | ||||||
|  |     node->genericDeclarations.declarations[0] = genericArgumentNode; | ||||||
|  |     node->genericDeclarations.count = 1; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *AddGenericDeclaration( | ||||||
|  |     Node *genericDeclarationsNode, | ||||||
|  |     Node *genericDeclarationNode) | ||||||
|  | { | ||||||
|  |     genericDeclarationsNode->genericDeclarations.declarations = | ||||||
|  |         (Node **)realloc( | ||||||
|  |             genericDeclarationsNode->genericDeclarations.declarations, | ||||||
|  |             sizeof(Node *) * | ||||||
|  |                 (genericDeclarationsNode->genericDeclarations.count + 1)); | ||||||
|  |     genericDeclarationsNode->genericDeclarations | ||||||
|  |         .declarations[genericDeclarationsNode->genericDeclarations.count] = | ||||||
|  |         genericDeclarationNode; | ||||||
|  |     genericDeclarationsNode->genericDeclarations.count += 1; | ||||||
|  |     return genericDeclarationsNode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *MakeEmptyGenericDeclarationsNode() | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = GenericDeclarations; | ||||||
|  |     node->genericDeclarations.declarations = NULL; | ||||||
|  |     node->genericDeclarations.count = 0; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *MakeGenericArgumentNode(Node *typeNode) | ||||||
| { | { | ||||||
|     Node *node = (Node *)malloc(sizeof(Node)); |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|     node->syntaxKind = GenericArgument; |     node->syntaxKind = GenericArgument; | ||||||
|     node->genericArgument.identifier = identifierNode; |     node->genericArgument.type = typeNode; | ||||||
|     node->genericArgument.constraint = constraintNode; |  | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -388,13 +460,13 @@ Node *StartGenericArgumentsNode(Node *genericArgumentNode) | ||||||
| 
 | 
 | ||||||
| Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode) | Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode) | ||||||
| { | { | ||||||
|     genericArgumentsNode->genericArguments.arguments = (Node **)realloc( |     genericArgumentsNode->genericArguments.arguments = realloc( | ||||||
|         genericArgumentsNode->genericArguments.arguments, |         genericArgumentsNode->genericArguments.arguments, | ||||||
|         sizeof(Node *) * (genericArgumentsNode->genericArguments.count + 1)); |         sizeof(Node *) * (genericArgumentsNode->genericArguments.count + 1)); | ||||||
|     genericArgumentsNode->genericArguments |     genericArgumentsNode->genericArguments | ||||||
|         .arguments[genericArgumentsNode->genericArguments.count] = |         .arguments[genericArgumentsNode->genericArguments.count] = | ||||||
|         genericArgumentNode; |         genericArgumentNode; | ||||||
|     genericArgumentsNode->genericArguments.count += 1; |     genericArgumentNode->genericArguments.count += 1; | ||||||
|     return genericArgumentsNode; |     return genericArgumentsNode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -417,12 +489,27 @@ Node *MakeGenericTypeNode(char *name) | ||||||
| 
 | 
 | ||||||
| Node *MakeFunctionCallExpressionNode( | Node *MakeFunctionCallExpressionNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *argumentSequenceNode) |     Node *argumentSequenceNode, | ||||||
|  |     Node *genericArgumentsNode) | ||||||
| { | { | ||||||
|     Node *node = (Node *)malloc(sizeof(Node)); |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|     node->syntaxKind = FunctionCallExpression; |     node->syntaxKind = FunctionCallExpression; | ||||||
|     node->functionCallExpression.identifier = identifierNode; |     node->functionCallExpression.identifier = identifierNode; | ||||||
|     node->functionCallExpression.argumentSequence = argumentSequenceNode; |     node->functionCallExpression.argumentSequence = argumentSequenceNode; | ||||||
|  |     node->functionCallExpression.genericArguments = genericArgumentsNode; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *MakeSystemCallExpressionNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *argumentSequenceNode, | ||||||
|  |     Node *genericArgumentsNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = SystemCall; | ||||||
|  |     node->systemCall.identifier = identifierNode; | ||||||
|  |     node->systemCall.argumentSequence = argumentSequenceNode; | ||||||
|  |     node->systemCall.genericArguments = genericArgumentsNode; | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -476,6 +563,55 @@ Node *MakeForLoopNode( | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Node *MakeFieldInitNode(Node *identifierNode, Node *expressionNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = FieldInit; | ||||||
|  |     node->fieldInit.identifier = identifierNode; | ||||||
|  |     node->fieldInit.expression = expressionNode; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *StartStructInitFieldsNode(Node *fieldInitNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = StructInitFields; | ||||||
|  |     node->structInitFields.fieldInits = (Node **)malloc(sizeof(Node *)); | ||||||
|  |     node->structInitFields.fieldInits[0] = fieldInitNode; | ||||||
|  |     node->structInitFields.count = 1; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *AddFieldInitNode(Node *structInitFieldsNode, Node *fieldInitNode) | ||||||
|  | { | ||||||
|  |     structInitFieldsNode->structInitFields.fieldInits = realloc( | ||||||
|  |         structInitFieldsNode->structInitFields.fieldInits, | ||||||
|  |         sizeof(Node *) * (structInitFieldsNode->structInitFields.count + 1)); | ||||||
|  |     structInitFieldsNode->structInitFields | ||||||
|  |         .fieldInits[structInitFieldsNode->structInitFields.count] = | ||||||
|  |         fieldInitNode; | ||||||
|  |     structInitFieldsNode->structInitFields.count += 1; | ||||||
|  |     return structInitFieldsNode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *MakeEmptyFieldInitNode() | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = StructInitFields; | ||||||
|  |     node->structInitFields.fieldInits = NULL; | ||||||
|  |     node->structInitFields.count = 0; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *MakeStructInitExpressionNode(Node *typeNode, Node *structInitFieldsNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = StructInit; | ||||||
|  |     node->structInit.type = typeNode; | ||||||
|  |     node->structInit.initFields = structInitFieldsNode; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const char *PrimitiveTypeToString(PrimitiveType type) | static const char *PrimitiveTypeToString(PrimitiveType type) | ||||||
| { | { | ||||||
|     switch (type) |     switch (type) | ||||||
|  | @ -486,6 +622,8 @@ static const char *PrimitiveTypeToString(PrimitiveType type) | ||||||
|         return "UInt"; |         return "UInt"; | ||||||
|     case Bool: |     case Bool: | ||||||
|         return "Bool"; |         return "Bool"; | ||||||
|  |     case MemoryAddress: | ||||||
|  |         return "MemoryAddress"; | ||||||
|     case Void: |     case Void: | ||||||
|         return "Void"; |         return "Void"; | ||||||
|     } |     } | ||||||
|  | @ -556,6 +694,11 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         PrintNode(node->binaryExpression.right, tabCount + 1); |         PrintNode(node->binaryExpression.right, tabCount + 1); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case ConcreteGenericTypeNode: | ||||||
|  |         printf("%s\n", node->concreteGenericType.name); | ||||||
|  |         PrintNode(node->concreteGenericType.genericArguments, tabCount + 1); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case CustomTypeNode: |     case CustomTypeNode: | ||||||
|         printf("%s\n", node->customType.name); |         printf("%s\n", node->customType.name); | ||||||
|         return; |         return; | ||||||
|  | @ -574,6 +717,12 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case FieldInit: | ||||||
|  |         printf("\n"); | ||||||
|  |         PrintNode(node->fieldInit.identifier, tabCount + 1); | ||||||
|  |         PrintNode(node->fieldInit.expression, tabCount + 1); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case ForLoop: |     case ForLoop: | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->forLoop.declaration, tabCount + 1); |         PrintNode(node->forLoop.declaration, tabCount + 1); | ||||||
|  | @ -594,6 +743,7 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->functionCallExpression.identifier, tabCount + 1); |         PrintNode(node->functionCallExpression.identifier, tabCount + 1); | ||||||
|         PrintNode(node->functionCallExpression.argumentSequence, tabCount + 1); |         PrintNode(node->functionCallExpression.argumentSequence, tabCount + 1); | ||||||
|  |         PrintNode(node->functionCallExpression.genericArguments, tabCount + 1); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case FunctionDeclaration: |     case FunctionDeclaration: | ||||||
|  | @ -613,7 +763,7 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|     case FunctionSignature: |     case FunctionSignature: | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->functionSignature.identifier, tabCount + 1); |         PrintNode(node->functionSignature.identifier, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.genericArguments, tabCount + 1); |         PrintNode(node->functionSignature.genericDeclarations, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.arguments, tabCount + 1); |         PrintNode(node->functionSignature.arguments, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.type, tabCount + 1); |         PrintNode(node->functionSignature.type, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.modifiers, tabCount + 1); |         PrintNode(node->functionSignature.modifiers, tabCount + 1); | ||||||
|  | @ -631,9 +781,7 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
| 
 | 
 | ||||||
|     case GenericArgument: |     case GenericArgument: | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->genericArgument.identifier, tabCount + 1); |         PrintNode(node->genericArgument.type, tabCount + 1); | ||||||
|         /* Constraint nodes are not implemented. */ |  | ||||||
|         /* PrintNode(node->genericArgument.constraint, tabCount + 1); */ |  | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case GenericArguments: |     case GenericArguments: | ||||||
|  | @ -644,6 +792,21 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case GenericDeclaration: | ||||||
|  |         printf("\n"); | ||||||
|  |         PrintNode(node->genericDeclaration.identifier, tabCount + 1); | ||||||
|  |         /* Constraint nodes are not implemented. */ | ||||||
|  |         /* PrintNode(node->genericDeclaration.constraint, tabCount + 1); */ | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case GenericDeclarations: | ||||||
|  |         printf("\n"); | ||||||
|  |         for (i = 0; i < node->genericDeclarations.count; i += 1) | ||||||
|  |         { | ||||||
|  |             PrintNode(node->genericDeclarations.declarations[i], tabCount + 1); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case GenericTypeNode: |     case GenericTypeNode: | ||||||
|         printf("%s\n", node->genericType.name); |         printf("%s\n", node->genericType.name); | ||||||
|         return; |         return; | ||||||
|  | @ -715,6 +878,27 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         PrintNode(node->structDeclaration.declarationSequence, tabCount + 1); |         PrintNode(node->structDeclaration.declarationSequence, tabCount + 1); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case StructInit: | ||||||
|  |         printf("\n"); | ||||||
|  |         PrintNode(node->structInit.type, tabCount + 1); | ||||||
|  |         PrintNode(node->structInit.initFields, tabCount + 1); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case StructInitFields: | ||||||
|  |         printf("\n"); | ||||||
|  |         for (i = 0; i < node->structInitFields.count; i += 1) | ||||||
|  |         { | ||||||
|  |             PrintNode(node->structInitFields.fieldInits[i], tabCount + 1); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case SystemCall: | ||||||
|  |         printf("\n"); | ||||||
|  |         PrintNode(node->systemCall.identifier, tabCount + 1); | ||||||
|  |         PrintNode(node->systemCall.argumentSequence, tabCount + 1); | ||||||
|  |         PrintNode(node->systemCall.genericArguments, tabCount + 1); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case Type: |     case Type: | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->type.typeNode, tabCount + 1); |         PrintNode(node->type.typeNode, tabCount + 1); | ||||||
|  | @ -754,6 +938,10 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|     case Comment: |     case Comment: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case ConcreteGenericTypeNode: | ||||||
|  |         func(node->concreteGenericType.genericArguments); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case CustomTypeNode: |     case CustomTypeNode: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -769,6 +957,11 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case FieldInit: | ||||||
|  |         func(node->fieldInit.identifier); | ||||||
|  |         func(node->fieldInit.expression); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case ForLoop: |     case ForLoop: | ||||||
|         func(node->forLoop.declaration); |         func(node->forLoop.declaration); | ||||||
|         func(node->forLoop.startNumber); |         func(node->forLoop.startNumber); | ||||||
|  | @ -786,6 +979,7 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|     case FunctionCallExpression: |     case FunctionCallExpression: | ||||||
|         func(node->functionCallExpression.identifier); |         func(node->functionCallExpression.identifier); | ||||||
|         func(node->functionCallExpression.argumentSequence); |         func(node->functionCallExpression.argumentSequence); | ||||||
|  |         func(node->functionCallExpression.genericArguments); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case FunctionDeclaration: |     case FunctionDeclaration: | ||||||
|  | @ -805,7 +999,7 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|         func(node->functionSignature.type); |         func(node->functionSignature.type); | ||||||
|         func(node->functionSignature.arguments); |         func(node->functionSignature.arguments); | ||||||
|         func(node->functionSignature.modifiers); |         func(node->functionSignature.modifiers); | ||||||
|         func(node->functionSignature.genericArguments); |         func(node->functionSignature.genericDeclarations); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case FunctionSignatureArguments: |     case FunctionSignatureArguments: | ||||||
|  | @ -816,9 +1010,8 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case GenericArgument: |     case GenericArgument: | ||||||
|         func(node->genericArgument.identifier); |         func(node->genericArgument.type); | ||||||
|         func(node->genericArgument.constraint); |         break; | ||||||
|         return; |  | ||||||
| 
 | 
 | ||||||
|     case GenericArguments: |     case GenericArguments: | ||||||
|         for (i = 0; i < node->genericArguments.count; i += 1) |         for (i = 0; i < node->genericArguments.count; i += 1) | ||||||
|  | @ -827,6 +1020,18 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case GenericDeclaration: | ||||||
|  |         func(node->genericDeclaration.identifier); | ||||||
|  |         func(node->genericDeclaration.constraint); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case GenericDeclarations: | ||||||
|  |         for (i = 0; i < node->genericDeclarations.count; i += 1) | ||||||
|  |         { | ||||||
|  |             func(node->genericDeclarations.declarations[i]); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case GenericTypeNode: |     case GenericTypeNode: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -878,7 +1083,26 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
|         func(node->structDeclaration.declarationSequence); |         func(node->structDeclaration.declarationSequence); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case StructInit: | ||||||
|  |         func(node->structInit.type); | ||||||
|  |         func(node->structInit.initFields); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case StructInitFields: | ||||||
|  |         for (i = 0; i < node->structInitFields.count; i += 1) | ||||||
|  |         { | ||||||
|  |             func(node->structInitFields.fieldInits[i]); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case SystemCall: | ||||||
|  |         func(node->systemCall.identifier); | ||||||
|  |         func(node->systemCall.argumentSequence); | ||||||
|  |         func(node->systemCall.genericArguments); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case Type: |     case Type: | ||||||
|  |         func(node->type.typeNode); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case UnaryExpression: |     case UnaryExpression: | ||||||
|  | @ -896,6 +1120,8 @@ void Recurse(Node *node, void (*func)(Node *)) | ||||||
| 
 | 
 | ||||||
| TypeTag *MakeTypeTag(Node *node) | TypeTag *MakeTypeTag(Node *node) | ||||||
| { | { | ||||||
|  |     uint32_t i; | ||||||
|  | 
 | ||||||
|     if (node == NULL) |     if (node == NULL) | ||||||
|     { |     { | ||||||
|         fprintf( |         fprintf( | ||||||
|  | @ -926,6 +1152,28 @@ TypeTag *MakeTypeTag(Node *node) | ||||||
|         tag->value.customType = strdup(node->customType.name); |         tag->value.customType = strdup(node->customType.name); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|  |     case ConcreteGenericTypeNode: | ||||||
|  |         tag->type = ConcreteGeneric; | ||||||
|  |         tag->value.concreteGenericType.name = | ||||||
|  |             strdup(node->concreteGenericType.name); | ||||||
|  |         tag->value.concreteGenericType.genericArgumentCount = | ||||||
|  |             node->concreteGenericType.genericArguments->genericArguments.count; | ||||||
|  |         tag->value.concreteGenericType.genericArguments = malloc( | ||||||
|  |             sizeof(TypeTag *) * | ||||||
|  |             tag->value.concreteGenericType.genericArgumentCount); | ||||||
|  | 
 | ||||||
|  |         for (i = 0; | ||||||
|  |              i < | ||||||
|  |              node->concreteGenericType.genericArguments->genericArguments.count; | ||||||
|  |              i += 1) | ||||||
|  |         { | ||||||
|  |             tag->value.concreteGenericType.genericArguments[i] = MakeTypeTag( | ||||||
|  |                 node->concreteGenericType.genericArguments->genericArguments | ||||||
|  |                     .arguments[i] | ||||||
|  |                     ->genericArgument.type); | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|     case Declaration: |     case Declaration: | ||||||
|         tag = MakeTypeTag(node->declaration.type); |         tag = MakeTypeTag(node->declaration.type); | ||||||
|         break; |         break; | ||||||
|  | @ -945,10 +1193,10 @@ TypeTag *MakeTypeTag(Node *node) | ||||||
|         tag = MakeTypeTag(node->allocExpression.type); |         tag = MakeTypeTag(node->allocExpression.type); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case GenericArgument: |     case GenericDeclaration: | ||||||
|         tag->type = Generic; |         tag->type = Generic; | ||||||
|         tag->value.genericType = |         tag->value.genericType = | ||||||
|             strdup(node->genericArgument.identifier->identifier.name); |             strdup(node->genericDeclaration.identifier->identifier.name); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case GenericTypeNode: |     case GenericTypeNode: | ||||||
|  | @ -970,6 +1218,8 @@ TypeTag *MakeTypeTag(Node *node) | ||||||
| 
 | 
 | ||||||
| char *TypeTagToString(TypeTag *tag) | char *TypeTagToString(TypeTag *tag) | ||||||
| { | { | ||||||
|  |     uint32_t i; | ||||||
|  | 
 | ||||||
|     if (tag == NULL) |     if (tag == NULL) | ||||||
|     { |     { | ||||||
|         fprintf( |         fprintf( | ||||||
|  | @ -988,24 +1238,82 @@ char *TypeTagToString(TypeTag *tag) | ||||||
|     { |     { | ||||||
|         char *inner = TypeTagToString(tag->value.referenceType); |         char *inner = TypeTagToString(tag->value.referenceType); | ||||||
|         size_t innerStrLen = strlen(inner); |         size_t innerStrLen = strlen(inner); | ||||||
|         char *result = malloc(sizeof(char) * (innerStrLen + 5)); |         char *result = malloc(sizeof(char) * (innerStrLen + 6)); | ||||||
|         sprintf(result, "Ref<%s>", inner); |         sprintf(result, "Ref<%s>", inner); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|     case Custom: |     case Custom: | ||||||
|     { |     { | ||||||
|         char *result = |         char *result = | ||||||
|             malloc(sizeof(char) * (strlen(tag->value.customType) + 8)); |             malloc(sizeof(char) * (strlen(tag->value.customType) + 9)); | ||||||
|         sprintf(result, "Custom<%s>", tag->value.customType); |         sprintf(result, "Custom<%s>", tag->value.customType); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|     case Generic: |     case Generic: | ||||||
|     { |     { | ||||||
|         char *result = |         char *result = | ||||||
|             malloc(sizeof(char) * (strlen(tag->value.customType) + 9)); |             malloc(sizeof(char) * (strlen(tag->value.genericType) + 10)); | ||||||
|         sprintf(result, "Generic<%s>", tag->value.customType); |         sprintf(result, "Generic<%s>", tag->value.genericType); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     case ConcreteGeneric: | ||||||
|  |     { | ||||||
|  |         char *result = strdup(tag->value.concreteGenericType.name); | ||||||
|  |         uint32_t len = strlen(result); | ||||||
|  |         len += 2; | ||||||
|  |         result = realloc(result, sizeof(char) * len); | ||||||
|  |         strcat(result, "<"); | ||||||
|  | 
 | ||||||
|  |         for (i = 0; i < tag->value.concreteGenericType.genericArgumentCount; | ||||||
|  |              i += 1) | ||||||
|  |         { | ||||||
|  |             char *inner = TypeTagToString( | ||||||
|  |                 tag->value.concreteGenericType.genericArguments[i]); | ||||||
|  |             len += strlen(inner); | ||||||
|  |             result = realloc(result, sizeof(char) * (len + 3)); | ||||||
|  |             if (i != tag->value.concreteGenericType.genericArgumentCount - 1) | ||||||
|  |             { | ||||||
|  |                 strcat(result, ", "); | ||||||
|  |             } | ||||||
|  |             strcat(result, inner); | ||||||
|  |         } | ||||||
|  |         result = realloc(result, sizeof(char) * (len + 1)); | ||||||
|  |         strcat(result, ">"); | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t TypeTagEqual(TypeTag *typeTagA, TypeTag *typeTagB) | ||||||
|  | { | ||||||
|  |     if (typeTagA->type != typeTagB->type) | ||||||
|  |     { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     switch (typeTagA->type) | ||||||
|  |     { | ||||||
|  |     case Primitive: | ||||||
|  |         return typeTagA->value.primitiveType == typeTagB->value.primitiveType; | ||||||
|  | 
 | ||||||
|  |     case Reference: | ||||||
|  |         return TypeTagEqual( | ||||||
|  |             typeTagA->value.referenceType, | ||||||
|  |             typeTagB->value.referenceType); | ||||||
|  | 
 | ||||||
|  |     case Custom: | ||||||
|  |         return strcmp(typeTagA->value.customType, typeTagB->value.customType) == | ||||||
|  |                0; | ||||||
|  | 
 | ||||||
|  |     case Generic: | ||||||
|  |         return strcmp( | ||||||
|  |                    typeTagA->value.genericType, | ||||||
|  |                    typeTagB->value.genericType) == 0; | ||||||
|  | 
 | ||||||
|  |     default: | ||||||
|  |         fprintf(stderr, "Invalid type comparison!"); | ||||||
|  |         return 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1056,6 +1364,11 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case FieldInit: | ||||||
|  |         LinkParentPointers(node->fieldInit.identifier, node); | ||||||
|  |         LinkParentPointers(node->fieldInit.expression, node); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case ForLoop: |     case ForLoop: | ||||||
|         LinkParentPointers(node->forLoop.declaration, node); |         LinkParentPointers(node->forLoop.declaration, node); | ||||||
|         LinkParentPointers(node->forLoop.startNumber, node); |         LinkParentPointers(node->forLoop.startNumber, node); | ||||||
|  | @ -1094,7 +1407,7 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         LinkParentPointers(node->functionSignature.type, node); |         LinkParentPointers(node->functionSignature.type, node); | ||||||
|         LinkParentPointers(node->functionSignature.arguments, node); |         LinkParentPointers(node->functionSignature.arguments, node); | ||||||
|         LinkParentPointers(node->functionSignature.modifiers, node); |         LinkParentPointers(node->functionSignature.modifiers, node); | ||||||
|         LinkParentPointers(node->functionSignature.genericArguments, node); |         LinkParentPointers(node->functionSignature.genericDeclarations, node); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case FunctionSignatureArguments: |     case FunctionSignatureArguments: | ||||||
|  | @ -1107,8 +1420,7 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case GenericArgument: |     case GenericArgument: | ||||||
|         LinkParentPointers(node->genericArgument.identifier, node); |         LinkParentPointers(node->genericArgument.type, node); | ||||||
|         LinkParentPointers(node->genericArgument.constraint, node); |  | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case GenericArguments: |     case GenericArguments: | ||||||
|  | @ -1118,6 +1430,18 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case GenericDeclaration: | ||||||
|  |         LinkParentPointers(node->genericDeclaration.identifier, node); | ||||||
|  |         LinkParentPointers(node->genericDeclaration.constraint, node); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case GenericDeclarations: | ||||||
|  |         for (i = 0; i < node->genericDeclarations.count; i += 1) | ||||||
|  |         { | ||||||
|  |             LinkParentPointers(node->genericDeclarations.declarations[i], node); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case GenericTypeNode: |     case GenericTypeNode: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -1169,6 +1493,24 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         LinkParentPointers(node->structDeclaration.declarationSequence, node); |         LinkParentPointers(node->structDeclaration.declarationSequence, node); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |     case StructInit: | ||||||
|  |         LinkParentPointers(node->structInit.type, node); | ||||||
|  |         LinkParentPointers(node->structInit.initFields, node); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case StructInitFields: | ||||||
|  |         for (i = 0; i < node->structInitFields.count; i += 1) | ||||||
|  |         { | ||||||
|  |             LinkParentPointers(node->structInitFields.fieldInits[i], node); | ||||||
|  |         } | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     case SystemCall: | ||||||
|  |         LinkParentPointers(node->systemCall.identifier, node); | ||||||
|  |         LinkParentPointers(node->systemCall.argumentSequence, node); | ||||||
|  |         LinkParentPointers(node->systemCall.genericArguments, node); | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|     case Type: |     case Type: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										107
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										107
									
								
								src/ast.h
								
								
								
								
							|  | @ -19,9 +19,11 @@ typedef enum | ||||||
|     Assignment, |     Assignment, | ||||||
|     BinaryExpression, |     BinaryExpression, | ||||||
|     Comment, |     Comment, | ||||||
|  |     ConcreteGenericTypeNode, | ||||||
|     CustomTypeNode, |     CustomTypeNode, | ||||||
|     Declaration, |     Declaration, | ||||||
|     DeclarationSequence, |     DeclarationSequence, | ||||||
|  |     FieldInit, | ||||||
|     ForLoop, |     ForLoop, | ||||||
|     FunctionArgumentSequence, |     FunctionArgumentSequence, | ||||||
|     FunctionCallExpression, |     FunctionCallExpression, | ||||||
|  | @ -31,6 +33,8 @@ typedef enum | ||||||
|     FunctionSignatureArguments, |     FunctionSignatureArguments, | ||||||
|     GenericArgument, |     GenericArgument, | ||||||
|     GenericArguments, |     GenericArguments, | ||||||
|  |     GenericDeclaration, | ||||||
|  |     GenericDeclarations, | ||||||
|     GenericTypeNode, |     GenericTypeNode, | ||||||
|     Identifier, |     Identifier, | ||||||
|     IfStatement, |     IfStatement, | ||||||
|  | @ -44,6 +48,9 @@ typedef enum | ||||||
|     StaticModifier, |     StaticModifier, | ||||||
|     StringLiteral, |     StringLiteral, | ||||||
|     StructDeclaration, |     StructDeclaration, | ||||||
|  |     StructInit, | ||||||
|  |     StructInitFields, | ||||||
|  |     SystemCall, | ||||||
|     Type, |     Type, | ||||||
|     UnaryExpression |     UnaryExpression | ||||||
| } SyntaxKind; | } SyntaxKind; | ||||||
|  | @ -73,7 +80,8 @@ typedef enum | ||||||
|     UInt, |     UInt, | ||||||
|     Float, |     Float, | ||||||
|     Double, |     Double, | ||||||
|     String |     String, | ||||||
|  |     MemoryAddress | ||||||
| } PrimitiveType; | } PrimitiveType; | ||||||
| 
 | 
 | ||||||
| typedef union | typedef union | ||||||
|  | @ -82,7 +90,16 @@ typedef union | ||||||
|     BinaryOperator binaryOperator; |     BinaryOperator binaryOperator; | ||||||
| } Operator; | } Operator; | ||||||
| 
 | 
 | ||||||
| typedef struct TypeTag | typedef struct TypeTag TypeTag; | ||||||
|  | 
 | ||||||
|  | typedef struct ConcreteGenericTypeTag | ||||||
|  | { | ||||||
|  |     char *name; | ||||||
|  |     TypeTag **genericArguments; | ||||||
|  |     uint32_t genericArgumentCount; | ||||||
|  | } ConcreteGenericTypeTag; | ||||||
|  | 
 | ||||||
|  | struct TypeTag | ||||||
| { | { | ||||||
|     enum Type |     enum Type | ||||||
|     { |     { | ||||||
|  | @ -90,7 +107,8 @@ typedef struct TypeTag | ||||||
|         Primitive, |         Primitive, | ||||||
|         Reference, |         Reference, | ||||||
|         Custom, |         Custom, | ||||||
|         Generic |         Generic, | ||||||
|  |         ConcreteGeneric | ||||||
|     } type; |     } type; | ||||||
|     union |     union | ||||||
|     { |     { | ||||||
|  | @ -102,8 +120,10 @@ typedef struct TypeTag | ||||||
|         char *customType; |         char *customType; | ||||||
|         /* Valid when type = Generic. */ |         /* Valid when type = Generic. */ | ||||||
|         char *genericType; |         char *genericType; | ||||||
|  |         /* Valid when type = ConcreteGeneric */ | ||||||
|  |         ConcreteGenericTypeTag concreteGenericType; | ||||||
|     } value; |     } value; | ||||||
| } TypeTag; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct Node Node; | typedef struct Node Node; | ||||||
| 
 | 
 | ||||||
|  | @ -142,6 +162,12 @@ struct Node | ||||||
| 
 | 
 | ||||||
|         } comment; |         } comment; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             char *name; | ||||||
|  |             Node *genericArguments; | ||||||
|  |         } concreteGenericType; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             char *name; |             char *name; | ||||||
|  | @ -159,6 +185,12 @@ struct Node | ||||||
|             uint32_t count; |             uint32_t count; | ||||||
|         } declarationSequence; |         } declarationSequence; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node *identifier; | ||||||
|  |             Node *expression; | ||||||
|  |         } fieldInit; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             Node *declaration; |             Node *declaration; | ||||||
|  | @ -177,6 +209,7 @@ struct Node | ||||||
|         { |         { | ||||||
|             Node *identifier; /* FIXME: need better name */ |             Node *identifier; /* FIXME: need better name */ | ||||||
|             Node *argumentSequence; |             Node *argumentSequence; | ||||||
|  |             Node *genericArguments; | ||||||
|         } functionCallExpression; |         } functionCallExpression; | ||||||
| 
 | 
 | ||||||
|         struct |         struct | ||||||
|  | @ -197,7 +230,7 @@ struct Node | ||||||
|             Node *type; |             Node *type; | ||||||
|             Node *arguments; |             Node *arguments; | ||||||
|             Node *modifiers; |             Node *modifiers; | ||||||
|             Node *genericArguments; |             Node *genericDeclarations; | ||||||
|         } functionSignature; |         } functionSignature; | ||||||
| 
 | 
 | ||||||
|         struct |         struct | ||||||
|  | @ -208,8 +241,7 @@ struct Node | ||||||
| 
 | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             Node *identifier; |             Node *type; | ||||||
|             Node *constraint; |  | ||||||
|         } genericArgument; |         } genericArgument; | ||||||
| 
 | 
 | ||||||
|         struct |         struct | ||||||
|  | @ -218,6 +250,18 @@ struct Node | ||||||
|             uint32_t count; |             uint32_t count; | ||||||
|         } genericArguments; |         } genericArguments; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node *identifier; | ||||||
|  |             Node *constraint; | ||||||
|  |         } genericDeclaration; | ||||||
|  | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node **declarations; | ||||||
|  |             uint32_t count; | ||||||
|  |         } genericDeclarations; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             char *name; |             char *name; | ||||||
|  | @ -285,8 +329,28 @@ struct Node | ||||||
|         { |         { | ||||||
|             Node *identifier; |             Node *identifier; | ||||||
|             Node *declarationSequence; |             Node *declarationSequence; | ||||||
|  |             Node *genericDeclarations; | ||||||
|         } structDeclaration; |         } structDeclaration; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node *type; | ||||||
|  |             Node *initFields; | ||||||
|  |         } structInit; | ||||||
|  | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node **fieldInits; | ||||||
|  |             uint32_t count; | ||||||
|  |         } structInitFields; | ||||||
|  | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node *identifier; | ||||||
|  |             Node *argumentSequence; | ||||||
|  |             Node *genericArguments; | ||||||
|  |         } systemCall; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             Node *typeNode; |             Node *typeNode; | ||||||
|  | @ -305,8 +369,11 @@ const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||||
| 
 | 
 | ||||||
| uint8_t IsPrimitiveType(Node *typeNode); | uint8_t IsPrimitiveType(Node *typeNode); | ||||||
| Node *MakePrimitiveTypeNode(PrimitiveType type); | Node *MakePrimitiveTypeNode(PrimitiveType type); | ||||||
| Node *MakeCustomTypeNode(char *string); | Node *MakeCustomTypeNode(Node *identifierNode); | ||||||
| Node *MakeReferenceTypeNode(Node *typeNode); | Node *MakeReferenceTypeNode(Node *typeNode); | ||||||
|  | Node *MakeConcreteGenericTypeNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *genericArgumentsNode); | ||||||
| Node *MakeTypeNode(Node *typeNode); | Node *MakeTypeNode(Node *typeNode); | ||||||
| Node *MakeIdentifierNode(const char *id); | Node *MakeIdentifierNode(const char *id); | ||||||
| Node *MakeNumberNode(const char *numberString); | Node *MakeNumberNode(const char *numberString); | ||||||
|  | @ -333,14 +400,21 @@ Node *MakeFunctionSignatureNode( | ||||||
| Node *MakeFunctionDeclarationNode( | Node *MakeFunctionDeclarationNode( | ||||||
|     Node *functionSignatureNode, |     Node *functionSignatureNode, | ||||||
|     Node *functionBodyNode); |     Node *functionBodyNode); | ||||||
| Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode); | 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 *MakeEmptyGenericArgumentsNode(); | ||||||
| Node *StartGenericArgumentsNode(Node *genericArgumentNode); | Node *StartGenericArgumentsNode(Node *genericArgumentNode); | ||||||
| Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | ||||||
| Node *MakeGenericTypeNode(char *name); | Node *MakeGenericTypeNode(char *name); | ||||||
| Node *MakeStructDeclarationNode( | Node *MakeStructDeclarationNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *declarationSequenceNode); |     Node *declarationSequenceNode, | ||||||
|  |     Node *genericArgumentsNode); | ||||||
| Node *StartDeclarationSequenceNode(Node *declarationNode); | Node *StartDeclarationSequenceNode(Node *declarationNode); | ||||||
| Node *AddDeclarationNode(Node *declarationSequenceNode, Node *declarationNode); | Node *AddDeclarationNode(Node *declarationSequenceNode, Node *declarationNode); | ||||||
| Node *StartFunctionArgumentSequenceNode(Node *argumentNode); | Node *StartFunctionArgumentSequenceNode(Node *argumentNode); | ||||||
|  | @ -348,7 +422,12 @@ 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 *MakeSystemCallExpressionNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *argumentSequenceNode, | ||||||
|  |     Node *genericArgumentsNode); | ||||||
| Node *MakeAccessExpressionNode(Node *accessee, Node *accessor); | Node *MakeAccessExpressionNode(Node *accessee, Node *accessor); | ||||||
| Node *MakeAllocNode(Node *typeNode); | Node *MakeAllocNode(Node *typeNode); | ||||||
| Node *MakeIfNode(Node *expressionNode, Node *statementSequenceNode); | Node *MakeIfNode(Node *expressionNode, Node *statementSequenceNode); | ||||||
|  | @ -361,6 +440,11 @@ Node *MakeForLoopNode( | ||||||
|     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 PrintNode(Node *node, uint32_t tabCount); | void PrintNode(Node *node, uint32_t tabCount); | ||||||
| const char *SyntaxKindString(SyntaxKind syntaxKind); | const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||||
|  | @ -376,6 +460,7 @@ void LinkParentPointers(Node *node, Node *prev); | ||||||
| 
 | 
 | ||||||
| TypeTag *MakeTypeTag(Node *node); | TypeTag *MakeTypeTag(Node *node); | ||||||
| char *TypeTagToString(TypeTag *tag); | char *TypeTagToString(TypeTag *tag); | ||||||
|  | uint8_t TypeTagEqual(TypeTag *typeTagA, TypeTag *typeTagB); | ||||||
| 
 | 
 | ||||||
| Node *LookupIdNode(Node *current, Node *prev, char *target); | Node *LookupIdNode(Node *current, Node *prev, char *target); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										1484
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										1484
									
								
								src/codegen.c
								
								
								
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										11
									
								
								src/util.c
								
								
								
								
							
							
						
						
									
										11
									
								
								src/util.c
								
								
								
								
							|  | @ -5,7 +5,7 @@ | ||||||
| char *strdup(const char *s) | char *strdup(const char *s) | ||||||
| { | { | ||||||
|     size_t slen = strlen(s); |     size_t slen = strlen(s); | ||||||
|     char *result = (char *)malloc(slen + 1); |     char *result = (char *)malloc(sizeof(char) * (slen + 1)); | ||||||
|     if (result == NULL) |     if (result == NULL) | ||||||
|     { |     { | ||||||
|         return NULL; |         return NULL; | ||||||
|  | @ -15,6 +15,15 @@ char *strdup(const char *s) | ||||||
|     return result; |     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 str_hash(char *str) | ||||||
| { | { | ||||||
|     uint64_t hash = 5381; |     uint64_t hash = 5381; | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| char *strdup(const char *s); | char *strdup(const char *s); | ||||||
|  | char *w_strcat(char *s, char *s2); | ||||||
| uint64_t str_hash(char *str); | uint64_t str_hash(char *str); | ||||||
| 
 | 
 | ||||||
| #endif /* WRAITH_UTIL_H */ | #endif /* WRAITH_UTIL_H */ | ||||||
|  |  | ||||||
|  | @ -261,7 +261,7 @@ void ValidateIdentifiers(Node *node) | ||||||
| 
 | 
 | ||||||
|     /* Skip over generic arguments. They contain Identifiers but are not
 |     /* Skip over generic arguments. They contain Identifiers but are not
 | ||||||
|      * actually identifiers, they declare types. */ |      * actually identifiers, they declare types. */ | ||||||
|     if (node->syntaxKind == GenericArguments) |     if (node->syntaxKind == GenericDeclarations) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     if (node->syntaxKind != Identifier) |     if (node->syntaxKind != Identifier) | ||||||
|  | @ -309,8 +309,12 @@ void TagIdentifierTypes(Node *node) | ||||||
|         node->structDeclaration.identifier->typeTag = MakeTypeTag(node); |         node->structDeclaration.identifier->typeTag = MakeTypeTag(node); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case GenericArgument: |     case GenericDeclaration: | ||||||
|         node->genericArgument.identifier->typeTag = MakeTypeTag(node); |         node->genericDeclaration.identifier->typeTag = MakeTypeTag(node); | ||||||
|  |         break; | ||||||
|  | 
 | ||||||
|  |     case Type: | ||||||
|  |         node->typeTag = MakeTypeTag(node); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|     case Identifier: |     case Identifier: | ||||||
|  | @ -351,17 +355,19 @@ Node *LookupType(Node *current, char *target) | ||||||
|     case FunctionDeclaration: |     case FunctionDeclaration: | ||||||
|     { |     { | ||||||
|         Node *typeArgs = current->functionDeclaration.functionSignature |         Node *typeArgs = current->functionDeclaration.functionSignature | ||||||
|                              ->functionSignature.genericArguments; |                              ->functionSignature.genericDeclarations; | ||||||
|         uint32_t i; |         uint32_t i; | ||||||
|         for (i = 0; i < typeArgs->genericArguments.count; i += 1) |         for (i = 0; i < typeArgs->genericDeclarations.count; i += 1) | ||||||
|         { |         { | ||||||
|             Node *arg = typeArgs->genericArguments.arguments[i]; |             Node *arg = typeArgs->genericDeclarations.declarations[i]; | ||||||
|             Node *argId = arg->genericArgument.identifier; |             Node *argId = arg->genericDeclaration.identifier; | ||||||
|             char *argName = argId->identifier.name; |             char *argName = argId->identifier.name; | ||||||
|             /* note: return the GenericArgument, not the Identifier, so that
 |             /* note: return the GenericDeclaration, not the Identifier, so that
 | ||||||
|              * the caller can differentiate between generics and customs. */ |              * the caller can differentiate between generics and customs. */ | ||||||
|             if (strcmp(target, argName) == 0) |             if (strcmp(target, argName) == 0) | ||||||
|  |             { | ||||||
|                 return arg; |                 return arg; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return LookupType(current->parent, target); |         return LookupType(current->parent, target); | ||||||
|  | @ -369,9 +375,26 @@ Node *LookupType(Node *current, char *target) | ||||||
| 
 | 
 | ||||||
|     case StructDeclaration: |     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); |         Node *structId = GetIdFromStruct(current); | ||||||
|         if (strcmp(target, structId->identifier.name) == 0) |         if (strcmp(target, structId->identifier.name) == 0) | ||||||
|  |         { | ||||||
|             return structId; |             return structId; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return LookupType(current->parent, target); |         return LookupType(current->parent, target); | ||||||
|     } |     } | ||||||
|  | @ -417,7 +440,8 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
|         { |         { | ||||||
|             char *target = id->typeTag->value.customType; |             char *target = id->typeTag->value.customType; | ||||||
|             Node *typeLookup = LookupType(node, target); |             Node *typeLookup = LookupType(node, target); | ||||||
|             if (typeLookup != NULL && typeLookup->syntaxKind == GenericArgument) |             if (typeLookup != NULL && | ||||||
|  |                 typeLookup->syntaxKind == GenericDeclaration) | ||||||
|             { |             { | ||||||
|                 id->typeTag->type = Generic; |                 id->typeTag->type = Generic; | ||||||
|                 free(node->declaration.type); |                 free(node->declaration.type); | ||||||
|  | @ -436,7 +460,8 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
|         { |         { | ||||||
|             char *target = id->typeTag->value.customType; |             char *target = id->typeTag->value.customType; | ||||||
|             Node *typeLookup = LookupType(node, target); |             Node *typeLookup = LookupType(node, target); | ||||||
|             if (typeLookup != NULL && typeLookup->syntaxKind == GenericArgument) |             if (typeLookup != NULL && | ||||||
|  |                 typeLookup->syntaxKind == GenericDeclaration) | ||||||
|             { |             { | ||||||
|                 id->typeTag->type = Generic; |                 id->typeTag->type = Generic; | ||||||
|                 free(node->functionSignature.type); |                 free(node->functionSignature.type); | ||||||
|  | @ -446,6 +471,22 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
|         } |         } | ||||||
|         break; |         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); |     Recurse(node, *ConvertCustomsToGenerics); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue