Compare commits
	
		
			5 Commits 
		
	
	
		
			main
			...
			interfaces
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 1a21618bee | |
|  | f59be30791 | |
|  | 05b3707258 | |
|  | ff5011b813 | |
|  | 45004f83e0 | 
|  | @ -14,6 +14,7 @@ | ||||||
| "bool"                      return BOOL; | "bool"                      return BOOL; | ||||||
| "MemoryAddress"             return MEMORYADDRESS; | "MemoryAddress"             return MEMORYADDRESS; | ||||||
| "struct"                    return STRUCT; | "struct"                    return STRUCT; | ||||||
|  | "interface"                 return INTERFACE; | ||||||
| "return"                    return RETURN; | "return"                    return RETURN; | ||||||
| "static"                    return STATIC; | "static"                    return STATIC; | ||||||
| "Reference"                 return REFERENCE; | "Reference"                 return REFERENCE; | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ extern FILE *yyin; | ||||||
| %token BOOL | %token BOOL | ||||||
| %token MEMORYADDRESS | %token MEMORYADDRESS | ||||||
| %token STRUCT | %token STRUCT | ||||||
|  | %token INTERFACE | ||||||
| %token RETURN | %token RETURN | ||||||
| %token STATIC | %token STATIC | ||||||
| %token REFERENCE | %token REFERENCE | ||||||
|  | @ -150,6 +151,11 @@ AccessExpression        : Identifier POINT AccessExpression | ||||||
|                         { |                         { | ||||||
|                             $$ = $1; |                             $$ = $1; | ||||||
|                         } |                         } | ||||||
|  | 						| BaseType POINT AccessExpression | ||||||
|  | 						{ | ||||||
|  | 							$$ = MakeAccessExpressionNode($1, $3); | ||||||
|  | 						} | ||||||
|  | 						; | ||||||
| 
 | 
 | ||||||
| SystemCallExpression    : AT Identifier | SystemCallExpression    : AT Identifier | ||||||
|                         { |                         { | ||||||
|  | @ -355,6 +361,10 @@ GenericDeclaration      : Identifier | ||||||
|                         { |                         { | ||||||
|                             $$ = MakeGenericDeclarationNode($1, NULL); |                             $$ = MakeGenericDeclarationNode($1, NULL); | ||||||
|                         } |                         } | ||||||
|  |                         | Identifier COLON Type | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeGenericDeclarationNode($1, $3); | ||||||
|  |                         } | ||||||
| 
 | 
 | ||||||
| GenericDeclarations     : GenericDeclaration | GenericDeclarations     : GenericDeclaration | ||||||
|                         { |                         { | ||||||
|  | @ -433,7 +443,28 @@ Declarations            : Declaration | ||||||
|                             $$ = AddDeclarationNode($1, $2); |                             $$ = AddDeclarationNode($1, $2); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
| TopLevelDeclaration     : StructDeclaration; | InterfaceMember         : FunctionSignature SEMICOLON | ||||||
|  |                         { | ||||||
|  |                             $$ = $1; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | InterfaceMembers        : InterfaceMember | ||||||
|  |                         { | ||||||
|  |                             $$ = StartInterfaceMembersNode($1); | ||||||
|  |                         } | ||||||
|  |                         | InterfaceMembers InterfaceMember | ||||||
|  |                         { | ||||||
|  |                             $$ = AddInterfaceMemberNode($1, $2); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | InterfaceDeclaration    : INTERFACE Identifier GenericDeclarationClause LEFT_BRACE InterfaceMembers RIGHT_BRACE | ||||||
|  |                         { | ||||||
|  |                             $$ = MakeInterfaceDeclarationNode($2, $5, $3); | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  | TopLevelDeclaration     : StructDeclaration | ||||||
|  |                         | InterfaceDeclaration | ||||||
|  |                         ; | ||||||
| 
 | 
 | ||||||
| TopLevelDeclarations    : TopLevelDeclaration | TopLevelDeclarations    : TopLevelDeclaration | ||||||
|                         { |                         { | ||||||
|  |  | ||||||
							
								
								
									
										54
									
								
								generic.w
								
								
								
								
							
							
						
						
									
										54
									
								
								generic.w
								
								
								
								
							|  | @ -14,6 +14,15 @@ struct MemoryBlock<T> | ||||||
| 	start: MemoryAddress; | 	start: MemoryAddress; | ||||||
| 	capacity: uint; | 	capacity: uint; | ||||||
| 
 | 
 | ||||||
|  | 	static Init(capacity: uint): MemoryBlock<T> | ||||||
|  | 	{ | ||||||
|  | 		return MemoryBlock<T> | ||||||
|  | 		{ | ||||||
|  | 			capacity: capacity, | ||||||
|  | 			start: @malloc(capacity * @sizeof<T>()) | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	AddressOf(index: uint): MemoryAddress | 	AddressOf(index: uint): MemoryAddress | ||||||
|     { |     { | ||||||
|         return start + (index * @sizeof<T>()); |         return start + (index * @sizeof<T>()); | ||||||
|  | @ -35,25 +44,40 @@ struct MemoryBlock<T> | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct Array<T> | ||||||
|  | { | ||||||
|  |     memoryBlock: MemoryBlock<T>; | ||||||
|  | 
 | ||||||
|  |     static Init(capacity: uint): Array<T> | ||||||
|  |     { | ||||||
|  |         return Array<T> | ||||||
|  |         { | ||||||
|  |             memoryBlock: MemoryBlock<T>.Init(capacity) | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     Get(index: uint): T | ||||||
|  |     { | ||||||
|  |         return memoryBlock.Get(index); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 	Set(index: uint, value: T): void | ||||||
|  | 	{ | ||||||
|  | 		memoryBlock.Set(index, value); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct Program { | struct Program { | ||||||
|     static Main(): int { |     static Main(): int { | ||||||
|  |         array: Array<int> = Array<int>.Init(4); | ||||||
|         x: int = 4; |         x: int = 4; | ||||||
|         y: int = Foo.Func(x); |         y: int = Foo.Func(x); | ||||||
|         block: MemoryBlock<int> = MemoryBlock<int> | 		array.Set(0, 2); | ||||||
|         { | 		array.Set(1, 0); | ||||||
|             capacity: y, | 		array.Set(2, 5); | ||||||
|             start: @malloc(y * @sizeof<int>()) | 		array.Set(3, 9); | ||||||
|         }; |         Console.PrintLine("%i", array.Get(0)); | ||||||
|         block.Set(0, 5); | 		Console.PrintLine("%i", array.Get(3)); | ||||||
|         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; |         return 0; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | struct Ass | ||||||
|  | { | ||||||
|  |     Fart(): void | ||||||
|  |     { | ||||||
|  |         Console.PrintLine("Poot!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | interface Farter | ||||||
|  | { | ||||||
|  |     Fart(): void; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct FartDispatcher | ||||||
|  | { | ||||||
|  |     static Fart<T : Farter>(farter: T): void | ||||||
|  |     { | ||||||
|  |         farter.Fart(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct Program { | ||||||
|  |     static Main(): int { | ||||||
|  |         ass: Ass; | ||||||
|  | 
 | ||||||
|  |         FartDispatcher.Fart(ass); | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								src/ast.c
								
								
								
								
							
							
						
						
									
										48
									
								
								src/ast.c
								
								
								
								
							|  | @ -612,6 +612,43 @@ Node *MakeStructInitExpressionNode(Node *typeNode, Node *structInitFieldsNode) | ||||||
|     return node; |     return node; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Node *MakeInterfaceDeclarationNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *interfaceMembersNode, | ||||||
|  |     Node *genericDeclarationsNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = Interface; | ||||||
|  |     node->interface.identifier = identifierNode; | ||||||
|  |     node->interface.interfaceMembers = interfaceMembersNode; | ||||||
|  |     node->interface.genericDeclarations = genericDeclarationsNode; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *StartInterfaceMembersNode(Node *interfaceMemberNode) | ||||||
|  | { | ||||||
|  |     Node *node = (Node *)malloc(sizeof(Node)); | ||||||
|  |     node->syntaxKind = InterfaceMembers; | ||||||
|  |     node->interfaceMembers.members = (Node **)malloc(sizeof(Node *)); | ||||||
|  |     node->interfaceMembers.members[0] = interfaceMemberNode; | ||||||
|  |     node->interfaceMembers.count = 1; | ||||||
|  |     return node; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Node *AddInterfaceMemberNode( | ||||||
|  |     Node *interfaceMembersNode, | ||||||
|  |     Node *interfaceMemberNode) | ||||||
|  | { | ||||||
|  |     interfaceMembersNode->interfaceMembers.members = realloc( | ||||||
|  |         interfaceMembersNode->interfaceMembers.members, | ||||||
|  |         sizeof(Node *) * (interfaceMembersNode->interfaceMembers.count + 1)); | ||||||
|  |     interfaceMembersNode->interfaceMembers | ||||||
|  |         .members[interfaceMembersNode->interfaceMembers.count] = | ||||||
|  |         interfaceMemberNode; | ||||||
|  |     interfaceMembersNode->interfaceMembers.count += 1; | ||||||
|  |     return interfaceMembersNode; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const char *PrimitiveTypeToString(PrimitiveType type) | static const char *PrimitiveTypeToString(PrimitiveType type) | ||||||
| { | { | ||||||
|     switch (type) |     switch (type) | ||||||
|  | @ -1349,6 +1386,10 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|     case Comment: |     case Comment: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | 	case ConcreteGenericTypeNode: | ||||||
|  | 		LinkParentPointers(node->concreteGenericType.genericArguments, node); | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|     case CustomTypeNode: |     case CustomTypeNode: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -1388,6 +1429,7 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|     case FunctionCallExpression: |     case FunctionCallExpression: | ||||||
|         LinkParentPointers(node->functionCallExpression.identifier, node); |         LinkParentPointers(node->functionCallExpression.identifier, node); | ||||||
|         LinkParentPointers(node->functionCallExpression.argumentSequence, node); |         LinkParentPointers(node->functionCallExpression.argumentSequence, node); | ||||||
|  | 		LinkParentPointers(node->functionCallExpression.genericArguments, node); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case FunctionDeclaration: |     case FunctionDeclaration: | ||||||
|  | @ -1458,6 +1500,11 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         LinkParentPointers(node->ifElseStatement.elseStatement, node); |         LinkParentPointers(node->ifElseStatement.elseStatement, node); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | 	case Interface: | ||||||
|  | 		LinkParentPointers(node->interface.genericDeclarations, node); | ||||||
|  | 		LinkParentPointers(node->interface.interfaceMembers, node); | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|     case Number: |     case Number: | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -1512,6 +1559,7 @@ void LinkParentPointers(Node *node, Node *prev) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case Type: |     case Type: | ||||||
|  | 		LinkParentPointers(node->type.typeNode, node); | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     case UnaryExpression: |     case UnaryExpression: | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										23
									
								
								src/ast.h
								
								
								
								
							|  | @ -39,6 +39,8 @@ typedef enum | ||||||
|     Identifier, |     Identifier, | ||||||
|     IfStatement, |     IfStatement, | ||||||
|     IfElseStatement, |     IfElseStatement, | ||||||
|  |     Interface, | ||||||
|  |     InterfaceMembers, | ||||||
|     Number, |     Number, | ||||||
|     PrimitiveTypeNode, |     PrimitiveTypeNode, | ||||||
|     ReferenceTypeNode, |     ReferenceTypeNode, | ||||||
|  | @ -284,6 +286,19 @@ struct Node | ||||||
|             Node *elseStatement; |             Node *elseStatement; | ||||||
|         } ifElseStatement; |         } ifElseStatement; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node *identifier; | ||||||
|  |             Node *interfaceMembers; | ||||||
|  |             Node *genericDeclarations; | ||||||
|  |         } interface; | ||||||
|  | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             Node **members; | ||||||
|  |             uint32_t count; | ||||||
|  |         } interfaceMembers; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             uint64_t value; |             uint64_t value; | ||||||
|  | @ -445,6 +460,14 @@ Node *StartStructInitFieldsNode(Node *fieldInitNode); | ||||||
| Node *AddFieldInitNode(Node *structInitFieldsNode, Node *fieldInitNode); | Node *AddFieldInitNode(Node *structInitFieldsNode, Node *fieldInitNode); | ||||||
| Node *MakeEmptyFieldInitNode(); | Node *MakeEmptyFieldInitNode(); | ||||||
| Node *MakeStructInitExpressionNode(Node *typeNode, Node *structInitFieldsNode); | Node *MakeStructInitExpressionNode(Node *typeNode, Node *structInitFieldsNode); | ||||||
|  | Node *MakeInterfaceDeclarationNode( | ||||||
|  |     Node *identifierNode, | ||||||
|  |     Node *interfaceMembersNode, | ||||||
|  |     Node *genericDeclarationsNode); | ||||||
|  | Node *StartInterfaceMembersNode(Node *interfaceMemberNode); | ||||||
|  | Node *AddInterfaceMemberNode( | ||||||
|  |     Node *interfaceMembersNode, | ||||||
|  |     Node *interfaceMemberNode); | ||||||
| 
 | 
 | ||||||
| void PrintNode(Node *node, uint32_t tabCount); | void PrintNode(Node *node, uint32_t tabCount); | ||||||
| const char *SyntaxKindString(SyntaxKind syntaxKind); | const char *SyntaxKindString(SyntaxKind syntaxKind); | ||||||
|  |  | ||||||
							
								
								
									
										260
									
								
								src/codegen.c
								
								
								
								
							
							
						
						
									
										260
									
								
								src/codegen.c
								
								
								
								
							|  | @ -111,7 +111,7 @@ struct StructTypeDeclaration | ||||||
|     uint32_t genericFunctionCount; |     uint32_t genericFunctionCount; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| StructTypeDeclaration *structTypeDeclarations; | StructTypeDeclaration **structTypeDeclarations; | ||||||
| uint32_t structTypeDeclarationCount; | uint32_t structTypeDeclarationCount; | ||||||
| 
 | 
 | ||||||
| typedef struct MonomorphizedGenericStructHashEntry | typedef struct MonomorphizedGenericStructHashEntry | ||||||
|  | @ -401,9 +401,9 @@ static LLVMTypeRef LookupCustomType(char *name) | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (strcmp(structTypeDeclarations[i].name, name) == 0) |         if (strcmp(structTypeDeclarations[i]->name, name) == 0) | ||||||
|         { |         { | ||||||
|             return structTypeDeclarations[i].structType; |             return structTypeDeclarations[i]->structType; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -420,27 +420,30 @@ static StructTypeDeclaration *AddStructDeclaration( | ||||||
|     uint32_t index = structTypeDeclarationCount; |     uint32_t index = structTypeDeclarationCount; | ||||||
|     structTypeDeclarations = realloc( |     structTypeDeclarations = realloc( | ||||||
|         structTypeDeclarations, |         structTypeDeclarations, | ||||||
|         sizeof(StructTypeDeclaration) * (structTypeDeclarationCount + 1)); |         sizeof(StructTypeDeclaration*) * (structTypeDeclarationCount + 1)); | ||||||
|     structTypeDeclarations[index].module = module; | 	structTypeDeclarations[index] = malloc(sizeof(StructTypeDeclaration)); | ||||||
|     structTypeDeclarations[index].structType = wStructType; |     structTypeDeclarations[index]->module = module; | ||||||
|     structTypeDeclarations[index].structPointerType = wStructPointerType; |     structTypeDeclarations[index]->structType = wStructType; | ||||||
|     structTypeDeclarations[index].name = strdup(name); |     structTypeDeclarations[index]->structPointerType = wStructPointerType; | ||||||
|     structTypeDeclarations[index].fields = NULL; |     structTypeDeclarations[index]->name = strdup(name); | ||||||
|     structTypeDeclarations[index].fieldCount = 0; |     structTypeDeclarations[index]->fields = NULL; | ||||||
|     structTypeDeclarations[index].functions = NULL; |     structTypeDeclarations[index]->fieldCount = 0; | ||||||
|     structTypeDeclarations[index].functionCount = 0; |     structTypeDeclarations[index]->functions = NULL; | ||||||
|     structTypeDeclarations[index].genericFunctions = NULL; |     structTypeDeclarations[index]->functionCount = 0; | ||||||
|     structTypeDeclarations[index].genericFunctionCount = 0; |     structTypeDeclarations[index]->genericFunctions = NULL; | ||||||
|  |     structTypeDeclarations[index]->genericFunctionCount = 0; | ||||||
| 
 | 
 | ||||||
|     structTypeDeclarationCount += 1; |     structTypeDeclarationCount += 1; | ||||||
| 
 | 
 | ||||||
|     return &structTypeDeclarations[index]; |     return structTypeDeclarations[index]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static StructTypeDeclaration *CompileMonomorphizedGenericStruct( | static MonomorphizedGenericStructHashEntry *CompileMonomorphizedGenericStruct( | ||||||
|     GenericStructTypeDeclaration *genericStructTypeDeclaration, |     GenericStructTypeDeclaration *genericStructTypeDeclaration, | ||||||
|     TypeTag **genericArgumentTypes, |     TypeTag **genericArgumentTypes, | ||||||
|     uint32_t genericArgumentTypeCount) |     uint32_t genericArgumentTypeCount, | ||||||
|  | 	MonomorphizedGenericStructHashArray *hashArray, | ||||||
|  | 	uint64_t typeHash) | ||||||
| { | { | ||||||
|     uint32_t i = 0; |     uint32_t i = 0; | ||||||
|     uint32_t fieldCount = 0; |     uint32_t fieldCount = 0; | ||||||
|  | @ -486,6 +489,25 @@ static StructTypeDeclaration *CompileMonomorphizedGenericStruct( | ||||||
| 
 | 
 | ||||||
|     free(structName); |     free(structName); | ||||||
| 
 | 
 | ||||||
|  | 	/* add entry to the hash array here in case of recursion */ | ||||||
|  | 	hashArray->elements = realloc( | ||||||
|  | 		hashArray->elements, | ||||||
|  | 		sizeof(MonomorphizedGenericStructHashEntry) * | ||||||
|  | 			(hashArray->count + 1)); | ||||||
|  | 	hashArray->elements[hashArray->count].key = typeHash; | ||||||
|  | 	hashArray->elements[hashArray->count].types = | ||||||
|  | 		malloc(sizeof(TypeTag *) * genericArgumentTypeCount); | ||||||
|  | 	hashArray->elements[hashArray->count].typeCount = | ||||||
|  | 		genericArgumentTypeCount; | ||||||
|  | 	hashArray->elements[hashArray->count].structDeclaration = | ||||||
|  | 		declaration; | ||||||
|  | 	for (uint32_t j = 0; j < genericArgumentTypeCount; j += 1) | ||||||
|  | 	{ | ||||||
|  | 		hashArray->elements[hashArray->count].types[j] = | ||||||
|  | 			genericArgumentTypes[j]; | ||||||
|  | 	} | ||||||
|  | 	hashArray->count += 1; | ||||||
|  | 
 | ||||||
|     /* first build the structure def */ |     /* first build the structure def */ | ||||||
|     for (i = 0; i < declarationCount; i += 1) |     for (i = 0; i < declarationCount; i += 1) | ||||||
|     { |     { | ||||||
|  | @ -528,7 +550,7 @@ static StructTypeDeclaration *CompileMonomorphizedGenericStruct( | ||||||
| 
 | 
 | ||||||
|     PopScopeFrame(scope); |     PopScopeFrame(scope); | ||||||
| 
 | 
 | ||||||
|     return declaration; |     return &hashArray->elements[hashArray->count - 1];; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static StructTypeDeclaration *LookupGenericStructType( | static StructTypeDeclaration *LookupGenericStructType( | ||||||
|  | @ -578,38 +600,20 @@ static StructTypeDeclaration *LookupGenericStructType( | ||||||
| 
 | 
 | ||||||
|                 if (match) |                 if (match) | ||||||
|                 { |                 { | ||||||
|                     hashEntry = &hashArray->elements[i]; |                     hashEntry = &hashArray->elements[j]; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (hashEntry == NULL) |             if (hashEntry == NULL) | ||||||
|             { |             { | ||||||
|                 StructTypeDeclaration *structTypeDeclaration = |                 hashEntry = | ||||||
|                     CompileMonomorphizedGenericStruct( |                     CompileMonomorphizedGenericStruct( | ||||||
|                         &genericStructTypeDeclarations[i], |                         &genericStructTypeDeclarations[i], | ||||||
|                         genericTypeTags, |                         genericTypeTags, | ||||||
|                         typeTag->genericArgumentCount); |                         typeTag->genericArgumentCount, | ||||||
| 
 | 						hashArray, | ||||||
|                 hashArray->elements = realloc( | 						typeHash); | ||||||
|                     hashArray->elements, |  | ||||||
|                     sizeof(MonomorphizedGenericStructHashEntry) * |  | ||||||
|                         (hashArray->count + 1)); |  | ||||||
|                 hashArray->elements[hashArray->count].key = typeHash; |  | ||||||
|                 hashArray->elements[hashArray->count].types = |  | ||||||
|                     malloc(sizeof(TypeTag *) * typeTag->genericArgumentCount); |  | ||||||
|                 hashArray->elements[hashArray->count].typeCount = |  | ||||||
|                     typeTag->genericArgumentCount; |  | ||||||
|                 hashArray->elements[hashArray->count].structDeclaration = |  | ||||||
|                     structTypeDeclaration; |  | ||||||
|                 for (j = 0; j < typeTag->genericArgumentCount; j += 1) |  | ||||||
|                 { |  | ||||||
|                     hashArray->elements[hashArray->count].types[j] = |  | ||||||
|                         genericTypeTags[j]; |  | ||||||
|                 } |  | ||||||
|                 hashArray->count += 1; |  | ||||||
| 
 |  | ||||||
|                 hashEntry = &hashArray->elements[hashArray->count - 1]; |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return hashEntry->structDeclaration; |             return hashEntry->structDeclaration; | ||||||
|  | @ -688,9 +692,9 @@ static LLVMTypeRef LookupStructTypeByName(char *name) | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (strcmp(structTypeDeclarations[i].name, name) == 0) |         if (strcmp(structTypeDeclarations[i]->name, name) == 0) | ||||||
|         { |         { | ||||||
|             return structTypeDeclarations[i].structType; |             return structTypeDeclarations[i]->structType; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -703,9 +707,9 @@ static StructTypeDeclaration *LookupStructDeclaration(LLVMTypeRef structType) | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (structTypeDeclarations[i].structType == structType) |         if (structTypeDeclarations[i]->structType == structType) | ||||||
|         { |         { | ||||||
|             return &structTypeDeclarations[i]; |             return structTypeDeclarations[i]; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -724,18 +728,18 @@ static LLVMValueRef FindStructFieldPointer( | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (structTypeDeclarations[i].structPointerType == structPointerType) |         if (structTypeDeclarations[i]->structPointerType == structPointerType) | ||||||
|         { |         { | ||||||
|             for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) |             for (j = 0; j < structTypeDeclarations[i]->fieldCount; j += 1) | ||||||
|             { |             { | ||||||
|                 if (strcmp(structTypeDeclarations[i].fields[j].name, name) == 0) |                 if (strcmp(structTypeDeclarations[i]->fields[j].name, name) == 0) | ||||||
|                 { |                 { | ||||||
|                     char *ptrName = strdup(name); |                     char *ptrName = strdup(name); | ||||||
|                     ptrName = w_strcat(ptrName, "_ptr"); |                     ptrName = w_strcat(ptrName, "_ptr"); | ||||||
|                     return LLVMBuildStructGEP( |                     return LLVMBuildStructGEP( | ||||||
|                         builder, |                         builder, | ||||||
|                         structPointer, |                         structPointer, | ||||||
|                         structTypeDeclarations[i].fields[j].index, |                         structTypeDeclarations[i]->fields[j].index, | ||||||
|                         ptrName); |                         ptrName); | ||||||
|                     free(ptrName); |                     free(ptrName); | ||||||
|                 } |                 } | ||||||
|  | @ -1175,29 +1179,29 @@ static LLVMValueRef LookupFunctionByType( | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (structTypeDeclarations[i].structType == structType) |         if (structTypeDeclarations[i]->structType == structType) | ||||||
|         { |         { | ||||||
|             for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) |             for (j = 0; j < structTypeDeclarations[i]->functionCount; j += 1) | ||||||
|             { |             { | ||||||
|                 if (strcmp(structTypeDeclarations[i].functions[j].name, name) == |                 if (strcmp(structTypeDeclarations[i]->functions[j].name, name) == | ||||||
|                     0) |                     0) | ||||||
|                 { |                 { | ||||||
|                     *pReturnType = |                     *pReturnType = | ||||||
|                         structTypeDeclarations[i].functions[j].returnType; |                         structTypeDeclarations[i]->functions[j].returnType; | ||||||
|                     *pStatic = structTypeDeclarations[i].functions[j].isStatic; |                     *pStatic = structTypeDeclarations[i]->functions[j].isStatic; | ||||||
|                     return structTypeDeclarations[i].functions[j].function; |                     return structTypeDeclarations[i]->functions[j].function; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (j = 0; j < structTypeDeclarations[i].genericFunctionCount; |             for (j = 0; j < structTypeDeclarations[i]->genericFunctionCount; | ||||||
|                  j += 1) |                  j += 1) | ||||||
|             { |             { | ||||||
|                 if (strcmp( |                 if (strcmp( | ||||||
|                         structTypeDeclarations[i].genericFunctions[j].name, |                         structTypeDeclarations[i]->genericFunctions[j].name, | ||||||
|                         name) == 0) |                         name) == 0) | ||||||
|                 { |                 { | ||||||
|                     return LookupGenericFunction( |                     return LookupGenericFunction( | ||||||
|                         &structTypeDeclarations[i].genericFunctions[j], |                         &structTypeDeclarations[i]->genericFunctions[j], | ||||||
|                         functionCallExpression, |                         functionCallExpression, | ||||||
|                         pReturnType, |                         pReturnType, | ||||||
|                         pStatic); |                         pStatic); | ||||||
|  | @ -1221,29 +1225,29 @@ static LLVMValueRef LookupFunctionByPointerType( | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < structTypeDeclarationCount; i += 1) |     for (i = 0; i < structTypeDeclarationCount; i += 1) | ||||||
|     { |     { | ||||||
|         if (structTypeDeclarations[i].structPointerType == structPointerType) |         if (structTypeDeclarations[i]->structPointerType == structPointerType) | ||||||
|         { |         { | ||||||
|             for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) |             for (j = 0; j < structTypeDeclarations[i]->functionCount; j += 1) | ||||||
|             { |             { | ||||||
|                 if (strcmp(structTypeDeclarations[i].functions[j].name, name) == |                 if (strcmp(structTypeDeclarations[i]->functions[j].name, name) == | ||||||
|                     0) |                     0) | ||||||
|                 { |                 { | ||||||
|                     *pReturnType = |                     *pReturnType = | ||||||
|                         structTypeDeclarations[i].functions[j].returnType; |                         structTypeDeclarations[i]->functions[j].returnType; | ||||||
|                     *pStatic = structTypeDeclarations[i].functions[j].isStatic; |                     *pStatic = structTypeDeclarations[i]->functions[j].isStatic; | ||||||
|                     return structTypeDeclarations[i].functions[j].function; |                     return structTypeDeclarations[i]->functions[j].function; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (j = 0; j < structTypeDeclarations[i].genericFunctionCount; |             for (j = 0; j < structTypeDeclarations[i]->genericFunctionCount; | ||||||
|                  j += 1) |                  j += 1) | ||||||
|             { |             { | ||||||
|                 if (strcmp( |                 if (strcmp( | ||||||
|                         structTypeDeclarations[i].genericFunctions[j].name, |                         structTypeDeclarations[i]->genericFunctions[j].name, | ||||||
|                         name) == 0) |                         name) == 0) | ||||||
|                 { |                 { | ||||||
|                     return LookupGenericFunction( |                     return LookupGenericFunction( | ||||||
|                         &structTypeDeclarations[i].genericFunctions[j], |                         &structTypeDeclarations[i]->genericFunctions[j], | ||||||
|                         functionCallExpression, |                         functionCallExpression, | ||||||
|                         pReturnType, |                         pReturnType, | ||||||
|                         pStatic); |                         pStatic); | ||||||
|  | @ -1370,36 +1374,62 @@ static LLVMValueRef CompileFunctionCallExpression( | ||||||
|     if (functionCallExpression->functionCallExpression.identifier->syntaxKind == |     if (functionCallExpression->functionCallExpression.identifier->syntaxKind == | ||||||
|         AccessExpression) |         AccessExpression) | ||||||
|     { |     { | ||||||
|         LLVMTypeRef typeReference = LookupStructTypeByName( | 		if (functionCallExpression->functionCallExpression.identifier->accessExpression.accessee->syntaxKind == | ||||||
|             functionCallExpression->functionCallExpression.identifier | 			ConcreteGenericTypeNode) | ||||||
|                 ->accessExpression.accessee->identifier.name); | 		{ | ||||||
|  | 			TypeTag *typeTag = | ||||||
|  | 				MakeTypeTag( | ||||||
|  | 					functionCallExpression->functionCallExpression.identifier->accessExpression.accessee | ||||||
|  | 				); | ||||||
|  | 			LLVMTypeRef typeReference = ResolveType(typeTag); | ||||||
| 
 | 
 | ||||||
|         char *functionName = | 			char *functionName = | ||||||
|             functionCallExpression->functionCallExpression.identifier | 				functionCallExpression->functionCallExpression.identifier | ||||||
|                 ->accessExpression.accessor->identifier.name; | 					->accessExpression.accessor->identifier.name; | ||||||
| 
 | 
 | ||||||
|         if (typeReference != NULL) | 			function = LookupFunctionByType( | ||||||
|         { | 				typeReference, | ||||||
|             function = LookupFunctionByType( | 				functionName, | ||||||
|                 typeReference, | 				functionCallExpression, | ||||||
|                 functionName, | 				&functionReturnType, | ||||||
|                 functionCallExpression, | 				&isStatic | ||||||
|                 &functionReturnType, | 			); | ||||||
|                 &isStatic); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|         { |  | ||||||
|             structInstance = FindVariablePointer( |  | ||||||
|                 functionCallExpression->functionCallExpression.identifier |  | ||||||
|                     ->accessExpression.accessee->identifier.name); |  | ||||||
| 
 | 
 | ||||||
|             function = LookupFunctionByInstance( | 			free(typeTag); | ||||||
|                 structInstance, | 		} | ||||||
|                 functionName, | 		else | ||||||
|                 functionCallExpression, | 		{ | ||||||
|                 &functionReturnType, | 			LLVMTypeRef typeReference = LookupStructTypeByName( | ||||||
|                 &isStatic); | 				functionCallExpression->functionCallExpression.identifier | ||||||
|         } | 					->accessExpression.accessee->identifier.name); | ||||||
|  | 
 | ||||||
|  | 			char *functionName = | ||||||
|  | 				functionCallExpression->functionCallExpression.identifier | ||||||
|  | 					->accessExpression.accessor->identifier.name; | ||||||
|  | 
 | ||||||
|  | 			if (typeReference != NULL) | ||||||
|  | 			{ | ||||||
|  | 				function = LookupFunctionByType( | ||||||
|  | 					typeReference, | ||||||
|  | 					functionName, | ||||||
|  | 					functionCallExpression, | ||||||
|  | 					&functionReturnType, | ||||||
|  | 					&isStatic); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				structInstance = FindVariablePointer( | ||||||
|  | 					functionCallExpression->functionCallExpression.identifier | ||||||
|  | 						->accessExpression.accessee->identifier.name); | ||||||
|  | 
 | ||||||
|  | 				function = LookupFunctionByInstance( | ||||||
|  | 					structInstance, | ||||||
|  | 					functionName, | ||||||
|  | 					functionCallExpression, | ||||||
|  | 					&functionReturnType, | ||||||
|  | 					&isStatic); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|     } |     } | ||||||
|     else if ( |     else if ( | ||||||
|         functionCallExpression->functionCallExpression.identifier->syntaxKind == |         functionCallExpression->functionCallExpression.identifier->syntaxKind == | ||||||
|  | @ -1613,6 +1643,7 @@ static LLVMValueRef CompileStructInitExpression( | ||||||
|     LLVMTypeRef structType = ResolveType( |     LLVMTypeRef structType = ResolveType( | ||||||
|         ConcretizeType(structInitExpression->structInit.type->typeTag)); |         ConcretizeType(structInitExpression->structInit.type->typeTag)); | ||||||
| 
 | 
 | ||||||
|  | 	/* FIXME: this can be given by struct instead of allocated */ | ||||||
|     LLVMValueRef structPointer = |     LLVMValueRef structPointer = | ||||||
|         LLVMBuildAlloca(builder, structType, "structInit"); |         LLVMBuildAlloca(builder, structType, "structInit"); | ||||||
| 
 | 
 | ||||||
|  | @ -1628,19 +1659,40 @@ static LLVMValueRef CompileStructInitExpression( | ||||||
|                 .fieldInits[i] |                 .fieldInits[i] | ||||||
|                 ->fieldInit.identifier->identifier.name); |                 ->fieldInit.identifier->identifier.name); | ||||||
| 
 | 
 | ||||||
|         LLVMBuildStore( | 		LLVMValueRef fieldExpressionResult = CompileExpression( | ||||||
|             builder, |  | ||||||
|             CompileExpression( |  | ||||||
|                 structTypeDeclaration, |                 structTypeDeclaration, | ||||||
|                 selfParam, |                 selfParam, | ||||||
|                 builder, |                 builder, | ||||||
|                 structInitExpression->structInit.initFields->structInitFields |                 structInitExpression->structInit.initFields->structInitFields | ||||||
|                     .fieldInits[i] |                     .fieldInits[i] | ||||||
|                     ->fieldInit.expression), |                     ->fieldInit.expression); | ||||||
|             structFieldPointer); | 
 | ||||||
|  | 		LLVMTypeKind fieldExpressionTypeKind = LLVMGetTypeKind(LLVMTypeOf(fieldExpressionResult)); | ||||||
|  | 		if (fieldExpressionTypeKind == LLVMPointerTypeKind) | ||||||
|  | 		{ | ||||||
|  | 			LLVMBuildMemCpy( | ||||||
|  | 				builder, | ||||||
|  | 				structPointer, | ||||||
|  | 				LLVMGetAlignment(structPointer), | ||||||
|  | 				fieldExpressionResult, | ||||||
|  | 				LLVMGetAlignment(fieldExpressionResult), | ||||||
|  | 				LLVMSizeOf(LLVMTypeOf(fieldExpressionResult)) | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			LLVMBuildStore( | ||||||
|  | 				builder, | ||||||
|  | 				fieldExpressionResult, | ||||||
|  | 				structFieldPointer); | ||||||
|  | 		} | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return structPointer; | 	return LLVMBuildLoad( | ||||||
|  | 		builder, | ||||||
|  | 		structPointer, | ||||||
|  | 		"struct" | ||||||
|  | 	); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static LLVMValueRef CompileExpression( | static LLVMValueRef CompileExpression( | ||||||
|  | @ -2334,11 +2386,17 @@ static void Compile( | ||||||
|                 context, |                 context, | ||||||
|                 declarationSequenceNode->declarationSequence.sequence[i]); |                 declarationSequenceNode->declarationSequence.sequence[i]); | ||||||
|         } |         } | ||||||
|  |         else if ( | ||||||
|  |             declarationSequenceNode->declarationSequence.sequence[i] | ||||||
|  |                 ->syntaxKind == Interface) | ||||||
|  |         { | ||||||
|  |             /* Interfaces don't need to compile! */ | ||||||
|  |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             fprintf( |             fprintf( | ||||||
|                 stderr, |                 stderr, | ||||||
|                 "top level declarations that are not structs are " |                 "top level declarations that are not structs or interfaces are " | ||||||
|                 "forbidden!\n"); |                 "forbidden!\n"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
							
								
								
									
										103
									
								
								src/validation.c
								
								
								
								
							
							
						
						
									
										103
									
								
								src/validation.c
								
								
								
								
							|  | @ -432,6 +432,41 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
| 
 | 
 | ||||||
|     switch (node->syntaxKind) |     switch (node->syntaxKind) | ||||||
|     { |     { | ||||||
|  | 	case Type: | ||||||
|  | 	{ | ||||||
|  | 		Node *type = node->type.typeNode; | ||||||
|  | 		if (type->syntaxKind == CustomTypeNode) | ||||||
|  |         { | ||||||
|  |             char *target = type->customType.name; | ||||||
|  |             Node *typeLookup = LookupType(node, target); | ||||||
|  |             if (typeLookup != NULL && | ||||||
|  |                 typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  |             { | ||||||
|  |                 node->typeTag->type = Generic; | ||||||
|  |                 free(node->declaration.type); | ||||||
|  |                 node->declaration.type = | ||||||
|  |                     MakeGenericTypeNode(node->typeTag->value.genericType); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 		else if (type->syntaxKind == ConcreteGenericTypeNode) | ||||||
|  | 		{ | ||||||
|  | 			for (int32_t i = 0; i < node->typeTag->value.concreteGenericType.genericArgumentCount; i += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (node->typeTag->value.concreteGenericType.genericArguments[i]->type == Custom) | ||||||
|  | 				{ | ||||||
|  | 					char *target = node->typeTag->value.concreteGenericType.genericArguments[i]->value.customType; | ||||||
|  | 					Node *typeLookup = LookupType(node, target); | ||||||
|  | 					if (typeLookup != NULL && | ||||||
|  | 						typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  | 					{ | ||||||
|  | 						node->typeTag->value.concreteGenericType.genericArguments[i]->type = Generic; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|     case Declaration: |     case Declaration: | ||||||
|     { |     { | ||||||
|         Node *id = node->declaration.identifier; |         Node *id = node->declaration.identifier; | ||||||
|  | @ -449,6 +484,22 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
|                     MakeGenericTypeNode(id->typeTag->value.genericType); |                     MakeGenericTypeNode(id->typeTag->value.genericType); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 		else if (type->syntaxKind == ConcreteGenericTypeNode) | ||||||
|  | 		{ | ||||||
|  | 			for (int32_t i = 0; i < id->typeTag->value.concreteGenericType.genericArgumentCount; i += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (id->typeTag->value.concreteGenericType.genericArguments[i]->type == Custom) | ||||||
|  | 				{ | ||||||
|  | 					char *target = id->typeTag->value.concreteGenericType.genericArguments[i]->value.customType; | ||||||
|  | 					Node *typeLookup = LookupType(node, target); | ||||||
|  | 					if (typeLookup != NULL && | ||||||
|  | 						typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  | 					{ | ||||||
|  | 						id->typeTag->value.concreteGenericType.genericArguments[i]->type = Generic; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -469,9 +520,61 @@ void ConvertCustomsToGenerics(Node *node) | ||||||
|                     MakeGenericTypeNode(id->typeTag->value.genericType); |                     MakeGenericTypeNode(id->typeTag->value.genericType); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | 		else if (type->syntaxKind == ConcreteGenericTypeNode) | ||||||
|  | 		{ | ||||||
|  | 			for (int32_t i = 0; i < id->typeTag->value.concreteGenericType.genericArgumentCount; i += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (id->typeTag->value.concreteGenericType.genericArguments[i]->type == Custom) | ||||||
|  | 				{ | ||||||
|  | 					char *target = id->typeTag->value.concreteGenericType.genericArguments[i]->value.customType; | ||||||
|  | 					Node *typeLookup = LookupType(node, target); | ||||||
|  | 					if (typeLookup != NULL && | ||||||
|  | 						typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  | 					{ | ||||||
|  | 						id->typeTag->value.concreteGenericType.genericArguments[i]->type = Generic; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | 	case StructInit: | ||||||
|  | 	{ | ||||||
|  |         Node *type = node->structInit.type->type.typeNode; | ||||||
|  | 		TypeTag *typeTag = node->structInit.type->typeTag; | ||||||
|  |         if (type->syntaxKind == CustomTypeNode) | ||||||
|  |         { | ||||||
|  |             char *target = typeTag->value.customType; | ||||||
|  |             Node *typeLookup = LookupType(node, target); | ||||||
|  |             if (typeLookup != NULL && | ||||||
|  |                 typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  |             { | ||||||
|  |                 typeTag->type = Generic; | ||||||
|  |                 free(node->functionSignature.type); | ||||||
|  |                 node->functionSignature.type = | ||||||
|  |                     MakeGenericTypeNode(typeTag->value.genericType); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 		else if (type->syntaxKind == ConcreteGenericTypeNode) | ||||||
|  | 		{ | ||||||
|  | 			for (int32_t i = 0; i < typeTag->value.concreteGenericType.genericArgumentCount; i += 1) | ||||||
|  | 			{ | ||||||
|  | 				if (typeTag->value.concreteGenericType.genericArguments[i]->type == Custom) | ||||||
|  | 				{ | ||||||
|  | 					char *target = typeTag->value.concreteGenericType.genericArguments[i]->value.customType; | ||||||
|  | 					Node *typeLookup = LookupType(node, target); | ||||||
|  | 					if (typeLookup != NULL && | ||||||
|  | 						typeLookup->syntaxKind == GenericDeclaration) | ||||||
|  | 					{ | ||||||
|  | 						typeTag->value.concreteGenericType.genericArguments[i]->type = Generic; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|     case GenericArgument: |     case GenericArgument: | ||||||
|     { |     { | ||||||
|         Node *typeNode = node->genericArgument.type; |         Node *typeNode = node->genericArgument.type; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue