generics_retry #4
			
				
			
		
		
		
	|  | @ -43,11 +43,13 @@ add_executable( | |||
| 	src/codegen.h | ||||
| 	src/identcheck.h | ||||
| 	src/parser.h | ||||
| 	src/typeutils.h | ||||
| 	src/util.h | ||||
|     src/ast.c | ||||
| 	src/codegen.c | ||||
| 	src/identcheck.c | ||||
| 	src/parser.c | ||||
| 	src/typeutils.c | ||||
| 	src/util.c | ||||
| 	src/main.c | ||||
| 	# Generated code | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| struct Foo { | ||||
|     static Func2<U>(u: U) : U { | ||||
|         return u; | ||||
|     } | ||||
| 
 | ||||
|     static Func<T>(t: T): T { | ||||
|         foo: T = t; | ||||
|         return Func2(foo); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| struct Program { | ||||
|     static main(): int { | ||||
|         x: int = 4; | ||||
|         y: int = Foo.Func(x); | ||||
|         return x; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										49
									
								
								src/ast.c
								
								
								
								
							
							
						
						
									
										49
									
								
								src/ast.c
								
								
								
								
							|  | @ -39,6 +39,12 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) | |||
|         return "FunctionSignature"; | ||||
|     case FunctionSignatureArguments: | ||||
|         return "FunctionSignatureArguments"; | ||||
|     case GenericArgument: | ||||
|         return "GenericArgument"; | ||||
|     case GenericArguments: | ||||
|         return "GenericArguments"; | ||||
|     case GenericTypeNode: | ||||
|         return "GenericTypeNode"; | ||||
|     case Identifier: | ||||
|         return "Identifier"; | ||||
|     case IfStatement: | ||||
|  | @ -401,6 +407,14 @@ Node *MakeEmptyGenericArgumentsNode() | |||
|     return node; | ||||
| } | ||||
| 
 | ||||
| Node *MakeGenericTypeNode(char *name) | ||||
| { | ||||
|     Node *node = (Node *)malloc(sizeof(Node)); | ||||
|     node->syntaxKind = GenericTypeNode; | ||||
|     node->genericType.name = strdup(name); | ||||
|     return node; | ||||
| } | ||||
| 
 | ||||
| Node *MakeFunctionCallExpressionNode( | ||||
|     Node *identifierNode, | ||||
|     Node *argumentSequenceNode) | ||||
|  | @ -599,6 +613,7 @@ void PrintNode(Node *node, uint32_t tabCount) | |||
|     case FunctionSignature: | ||||
|         printf("\n"); | ||||
|         PrintNode(node->functionSignature.identifier, tabCount + 1); | ||||
|         PrintNode(node->functionSignature.genericArguments, tabCount + 1); | ||||
|         PrintNode(node->functionSignature.arguments, tabCount + 1); | ||||
|         PrintNode(node->functionSignature.type, tabCount + 1); | ||||
|         PrintNode(node->functionSignature.modifiers, tabCount + 1); | ||||
|  | @ -614,6 +629,24 @@ void PrintNode(Node *node, uint32_t tabCount) | |||
|         } | ||||
|         return; | ||||
| 
 | ||||
|     case GenericArgument: | ||||
|         printf("\n"); | ||||
|         PrintNode(node->genericArgument.identifier, tabCount + 1); | ||||
|         /* Constraint nodes are not implemented. */ | ||||
|         /* PrintNode(node->genericArgument.constraint, tabCount + 1); */ | ||||
|         return; | ||||
| 
 | ||||
|     case GenericArguments: | ||||
|         printf("\n"); | ||||
|         for (i = 0; i < node->genericArguments.count; i += 1) { | ||||
|             PrintNode(node->genericArguments.arguments[i], tabCount + 1); | ||||
|         } | ||||
|         return; | ||||
| 
 | ||||
|     case GenericTypeNode: | ||||
|         printf("%s\n", node->genericType.name); | ||||
|         return; | ||||
| 
 | ||||
|     case Identifier: | ||||
|         if (node->typeTag == NULL) | ||||
|         { | ||||
|  | @ -744,6 +777,10 @@ TypeTag *MakeTypeTag(Node *node) | |||
|         tag = MakeTypeTag(node->allocExpression.type); | ||||
|         break; | ||||
| 
 | ||||
|     case GenericTypeNode: | ||||
|         tag->type = Generic; | ||||
|         tag->value.genericType = strdup(node->genericType.name); | ||||
| 
 | ||||
|     default: | ||||
|         fprintf( | ||||
|             stderr, | ||||
|  | @ -780,6 +817,16 @@ char *TypeTagToString(TypeTag *tag) | |||
|         return result; | ||||
|     } | ||||
|     case Custom: | ||||
|         return tag->value.customType; | ||||
|     { | ||||
|         char *result = malloc(sizeof(char) * (strlen(tag->value.customType) + 8)); | ||||
|         sprintf(result, "Custom<%s>", tag->value.customType); | ||||
|         return result; | ||||
|     } | ||||
|     case Generic: | ||||
|     { | ||||
|         char *result = malloc(sizeof(char) * (strlen(tag->value.customType) + 9)); | ||||
|         sprintf(result, "Generic<%s>", tag->value.customType); | ||||
|         return result; | ||||
|     } | ||||
|     } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/ast.h
								
								
								
								
							
							
						
						
									
										12
									
								
								src/ast.h
								
								
								
								
							|  | @ -32,6 +32,7 @@ typedef enum | |||
|     FunctionSignatureArguments, | ||||
|     GenericArgument, | ||||
|     GenericArguments, | ||||
|     GenericTypeNode, | ||||
|     Identifier, | ||||
|     IfStatement, | ||||
|     IfElseStatement, | ||||
|  | @ -89,7 +90,8 @@ typedef struct TypeTag | |||
|         Unknown, | ||||
|         Primitive, | ||||
|         Reference, | ||||
|         Custom | ||||
|         Custom, | ||||
|         Generic | ||||
|     } type; | ||||
|     union | ||||
|     { | ||||
|  | @ -99,6 +101,8 @@ typedef struct TypeTag | |||
|         struct TypeTag *referenceType; | ||||
|         /* Valid when type = Custom. */ | ||||
|         char *customType; | ||||
|         /* Valid when type = Generic. */ | ||||
|         char *genericType; | ||||
|     } value; | ||||
| } TypeTag; | ||||
| 
 | ||||
|  | @ -215,6 +219,11 @@ struct Node | |||
|             uint32_t count; | ||||
|         } genericArguments; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|         } genericType; | ||||
| 
 | ||||
|         struct | ||||
|         { | ||||
|             char *name; | ||||
|  | @ -330,6 +339,7 @@ Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode); | |||
| Node *MakeEmptyGenericArgumentsNode(); | ||||
| Node *StartGenericArgumentsNode(Node *genericArgumentNode); | ||||
| Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | ||||
| Node *MakeGenericTypeNode(char *name); | ||||
| Node *MakeStructDeclarationNode( | ||||
|     Node *identifierNode, | ||||
|     Node *declarationSequenceNode); | ||||
|  |  | |||
|  | @ -150,9 +150,9 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | |||
|         mainNode = MakeIdNode(Function, funcName, parent); | ||||
|         mainNode->typeTag = MakeTypeTag(astNode); | ||||
|         idNode->typeTag = mainNode->typeTag; | ||||
|         MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); | ||||
|         MakeIdTree(sigNode->functionSignature.arguments, mainNode); | ||||
|         MakeIdTree(astNode->functionDeclaration.functionBody, mainNode); | ||||
|         MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										11
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										11
									
								
								src/main.c
								
								
								
								
							|  | @ -4,6 +4,7 @@ | |||
| #include "codegen.h" | ||||
| #include "identcheck.h" | ||||
| #include "parser.h" | ||||
| #include "typeutils.h" | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|  | @ -87,9 +88,19 @@ int main(int argc, char *argv[]) | |||
|                 { | ||||
|                     { | ||||
|                         IdNode *idTree = MakeIdTree(rootNode, NULL); | ||||
|                         printf("\n"); | ||||
|                         PrintIdTree(idTree, /*tabCount=*/0); | ||||
| 
 | ||||
|                         printf("\nConverting custom types in the ID-tree.\n"); | ||||
|                         ConvertIdCustomsToGenerics(idTree); | ||||
|                         printf("\n"); | ||||
|                         PrintIdTree(idTree, /*tabCount=*/0); | ||||
| 
 | ||||
|                         printf("\nConverting custom type nodes in the AST.\n"); | ||||
|                         ConvertASTCustomsToGenerics(rootNode); | ||||
|                         printf("\n"); | ||||
|                         PrintNode(rootNode, /*tabCount=*/0); | ||||
| 
 | ||||
|                     } | ||||
|                     exitCode = Codegen(rootNode, optimizationLevel); | ||||
|                 } | ||||
|  |  | |||
|  | @ -0,0 +1,202 @@ | |||
| #include "typeutils.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| void ConvertIdCustomsToGenerics(IdNode *node) { | ||||
|     uint32_t i; | ||||
|     switch(node->type) | ||||
|     { | ||||
|         case UnorderedScope: | ||||
|         case OrderedScope: | ||||
|         case Struct: | ||||
|             /* FIXME: This case will need to be modified to handle type parameters over structs. */ | ||||
|             for (i = 0; i < node->childCount; i += 1) { | ||||
|                 ConvertIdCustomsToGenerics(node->children[i]); | ||||
|             } | ||||
|             return; | ||||
| 
 | ||||
|         case Variable: { | ||||
|             TypeTag *varType = node->typeTag; | ||||
|             if (varType->type == Custom) { | ||||
|                 IdNode *x = LookupId(node->parent, node, varType->value.customType); | ||||
|                 if (x != NULL && x->type == GenericType) { | ||||
|                     varType->type = Generic; | ||||
|                 } | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         case Function: { | ||||
|             TypeTag *funcType = node->typeTag; | ||||
|             if (funcType->type == Custom) { | ||||
|                 /* For functions we have to handle the type lookup manually since the generic type
 | ||||
|                  * identifiers are declared as children of the function's IdNode. */ | ||||
|                 for (i = 0; i < node->childCount; i += 1) { | ||||
|                     IdNode *child = node->children[i]; | ||||
|                     if (child->type == GenericType && strcmp(child->name, funcType->value.customType) == 0) { | ||||
|                         funcType->type = Generic; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             for (i = 0; i < node->childCount; i += 1) { | ||||
|                 ConvertIdCustomsToGenerics(node->children[i]); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ConvertASTCustomsToGenerics(Node *node) { | ||||
|     uint32_t i; | ||||
|     switch (node->syntaxKind) { | ||||
|         case AccessExpression: | ||||
|             ConvertASTCustomsToGenerics(node->accessExpression.accessee); | ||||
|             ConvertASTCustomsToGenerics(node->accessExpression.accessor); | ||||
|             return; | ||||
| 
 | ||||
|         case AllocExpression: | ||||
|             ConvertASTCustomsToGenerics(node->allocExpression.type); | ||||
|             return; | ||||
| 
 | ||||
|         case Assignment: | ||||
|             ConvertASTCustomsToGenerics(node->assignmentStatement.left); | ||||
|             ConvertASTCustomsToGenerics(node->assignmentStatement.right); | ||||
|             return; | ||||
| 
 | ||||
|         case BinaryExpression: | ||||
|             ConvertASTCustomsToGenerics(node->binaryExpression.left); | ||||
|             ConvertASTCustomsToGenerics(node->binaryExpression.right); | ||||
|             return; | ||||
| 
 | ||||
|         case Comment:  | ||||
|             return; | ||||
| 
 | ||||
|         case CustomTypeNode:  | ||||
|             return; | ||||
| 
 | ||||
|         case Declaration: { | ||||
|             Node *type = node->declaration.type->type.typeNode; | ||||
|             Node *id = node->declaration.identifier; | ||||
|             if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) { | ||||
|                 free(node->declaration.type); | ||||
|                 node->declaration.type = MakeGenericTypeNode(id->typeTag->value.genericType); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         case DeclarationSequence: | ||||
|             for (i = 0; i < node->declarationSequence.count; i += 1) { | ||||
|                 ConvertASTCustomsToGenerics(node->declarationSequence.sequence[i]); | ||||
|             } | ||||
|             return; | ||||
| 
 | ||||
|         case ForLoop: | ||||
|             ConvertASTCustomsToGenerics(node->forLoop.declaration); | ||||
|             ConvertASTCustomsToGenerics(node->forLoop.startNumber); | ||||
|             ConvertASTCustomsToGenerics(node->forLoop.endNumber); | ||||
|             ConvertASTCustomsToGenerics(node->forLoop.statementSequence); | ||||
|             return; | ||||
| 
 | ||||
|         case FunctionArgumentSequence: | ||||
|             for (i = 0; i < node->functionArgumentSequence.count; i += 1) { | ||||
|                 ConvertASTCustomsToGenerics(node->functionArgumentSequence.sequence[i]); | ||||
|             } | ||||
|             return; | ||||
| 
 | ||||
|         case FunctionCallExpression: | ||||
|             ConvertASTCustomsToGenerics(node->functionCallExpression.identifier); | ||||
|             ConvertASTCustomsToGenerics(node->functionCallExpression.argumentSequence); | ||||
|             return; | ||||
| 
 | ||||
|         case FunctionDeclaration: | ||||
|             ConvertASTCustomsToGenerics(node->functionDeclaration.functionSignature); | ||||
|             ConvertASTCustomsToGenerics(node->functionDeclaration.functionBody); | ||||
|             return; | ||||
|              | ||||
|         case FunctionModifiers: | ||||
|             return; | ||||
| 
 | ||||
|         case FunctionSignature:{ | ||||
|             Node *id = node->functionSignature.identifier; | ||||
|             Node *type = node->functionSignature.type; | ||||
|             if (id->typeTag->type == Generic && type->syntaxKind == CustomTypeNode) { | ||||
|                 free(node->functionSignature.type); | ||||
|                 node->functionSignature.type = MakeGenericTypeNode(id->typeTag->value.genericType); | ||||
|             } | ||||
|             ConvertASTCustomsToGenerics(node->functionSignature.arguments); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         case FunctionSignatureArguments: | ||||
|             for (i = 0; i < node->functionSignatureArguments.count; i += 1) { | ||||
|                 ConvertASTCustomsToGenerics(node->functionSignatureArguments.sequence[i]); | ||||
|             } | ||||
|             return; | ||||
| 
 | ||||
|         case GenericArgument: | ||||
|             return; | ||||
| 
 | ||||
|         case GenericArguments:  | ||||
|             return; | ||||
| 
 | ||||
|         case GenericTypeNode:  | ||||
|             return; | ||||
| 
 | ||||
|         case Identifier:  | ||||
|             return; | ||||
| 
 | ||||
|         case IfStatement: | ||||
|             ConvertASTCustomsToGenerics(node->ifStatement.expression); | ||||
|             ConvertASTCustomsToGenerics(node->ifStatement.statementSequence); | ||||
|             return; | ||||
| 
 | ||||
|         case IfElseStatement:  | ||||
|             ConvertASTCustomsToGenerics(node->ifElseStatement.ifStatement); | ||||
|             ConvertASTCustomsToGenerics(node->ifElseStatement.elseStatement); | ||||
|             return; | ||||
| 
 | ||||
|         case Number: | ||||
|             return; | ||||
| 
 | ||||
|         case PrimitiveTypeNode: | ||||
|             return; | ||||
| 
 | ||||
|         case ReferenceTypeNode: | ||||
|             return; | ||||
| 
 | ||||
|         case Return:  | ||||
|             ConvertASTCustomsToGenerics(node->returnStatement.expression); | ||||
|             return; | ||||
| 
 | ||||
|         case ReturnVoid:  | ||||
|             return; | ||||
| 
 | ||||
|         case StatementSequence: | ||||
|             for (i = 0; i < node->statementSequence.count; i += 1) { | ||||
|                 ConvertASTCustomsToGenerics(node->statementSequence.sequence[i]); | ||||
|             } | ||||
|             return; | ||||
| 
 | ||||
|         case StaticModifier: | ||||
|             return; | ||||
| 
 | ||||
|         case StringLiteral: | ||||
|             return; | ||||
| 
 | ||||
|         case StructDeclaration: | ||||
|             /* FIXME: This case will need to be modified to handle type parameters over structs. */ | ||||
|             ConvertASTCustomsToGenerics(node->structDeclaration.identifier); | ||||
|             ConvertASTCustomsToGenerics(node->structDeclaration.declarationSequence); | ||||
|             return; | ||||
| 
 | ||||
|         case Type:  | ||||
|             return; | ||||
| 
 | ||||
|         case UnaryExpression: | ||||
|             ConvertASTCustomsToGenerics(node->unaryExpression.child); | ||||
|             return; | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,13 @@ | |||
| /* Helper functions for working with types in the AST and ID-tree. */ | ||||
| 
 | ||||
| #ifndef WRAITH_TYPEUTILS_H | ||||
| #define WRAITH_TYPEUTILS_H | ||||
| 
 | ||||
| #include "ast.h" | ||||
| #include "identcheck.h" | ||||
| 
 | ||||
| /* FIXME: These two functions will need to be modified to handle type parameters over structs. */ | ||||
| void ConvertIdCustomsToGenerics(IdNode *node); | ||||
| void ConvertASTCustomsToGenerics(Node *node); | ||||
| 
 | ||||
| #endif /* WRAITH_TYPEUTILS_H */ | ||||
		Loading…
	
		Reference in New Issue