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