generics_retry #4
			
				
			
		
		
		
	|  | @ -43,11 +43,13 @@ add_executable( | ||||||
| 	src/codegen.h | 	src/codegen.h | ||||||
| 	src/identcheck.h | 	src/identcheck.h | ||||||
| 	src/parser.h | 	src/parser.h | ||||||
|  | 	src/typeutils.h | ||||||
| 	src/util.h | 	src/util.h | ||||||
|     src/ast.c |     src/ast.c | ||||||
| 	src/codegen.c | 	src/codegen.c | ||||||
| 	src/identcheck.c | 	src/identcheck.c | ||||||
| 	src/parser.c | 	src/parser.c | ||||||
|  | 	src/typeutils.c | ||||||
| 	src/util.c | 	src/util.c | ||||||
| 	src/main.c | 	src/main.c | ||||||
| 	# Generated code | 	# 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"; |         return "FunctionSignature"; | ||||||
|     case FunctionSignatureArguments: |     case FunctionSignatureArguments: | ||||||
|         return "FunctionSignatureArguments"; |         return "FunctionSignatureArguments"; | ||||||
|  |     case GenericArgument: | ||||||
|  |         return "GenericArgument"; | ||||||
|  |     case GenericArguments: | ||||||
|  |         return "GenericArguments"; | ||||||
|  |     case GenericTypeNode: | ||||||
|  |         return "GenericTypeNode"; | ||||||
|     case Identifier: |     case Identifier: | ||||||
|         return "Identifier"; |         return "Identifier"; | ||||||
|     case IfStatement: |     case IfStatement: | ||||||
|  | @ -401,6 +407,14 @@ Node *MakeEmptyGenericArgumentsNode() | ||||||
|     return node; |     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 *MakeFunctionCallExpressionNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *argumentSequenceNode) |     Node *argumentSequenceNode) | ||||||
|  | @ -599,6 +613,7 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|     case FunctionSignature: |     case FunctionSignature: | ||||||
|         printf("\n"); |         printf("\n"); | ||||||
|         PrintNode(node->functionSignature.identifier, tabCount + 1); |         PrintNode(node->functionSignature.identifier, tabCount + 1); | ||||||
|  |         PrintNode(node->functionSignature.genericArguments, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.arguments, tabCount + 1); |         PrintNode(node->functionSignature.arguments, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.type, tabCount + 1); |         PrintNode(node->functionSignature.type, tabCount + 1); | ||||||
|         PrintNode(node->functionSignature.modifiers, tabCount + 1); |         PrintNode(node->functionSignature.modifiers, tabCount + 1); | ||||||
|  | @ -614,6 +629,24 @@ void PrintNode(Node *node, uint32_t tabCount) | ||||||
|         } |         } | ||||||
|         return; |         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: |     case Identifier: | ||||||
|         if (node->typeTag == NULL) |         if (node->typeTag == NULL) | ||||||
|         { |         { | ||||||
|  | @ -744,6 +777,10 @@ TypeTag *MakeTypeTag(Node *node) | ||||||
|         tag = MakeTypeTag(node->allocExpression.type); |         tag = MakeTypeTag(node->allocExpression.type); | ||||||
|         break; |         break; | ||||||
| 
 | 
 | ||||||
|  |     case GenericTypeNode: | ||||||
|  |         tag->type = Generic; | ||||||
|  |         tag->value.genericType = strdup(node->genericType.name); | ||||||
|  | 
 | ||||||
|     default: |     default: | ||||||
|         fprintf( |         fprintf( | ||||||
|             stderr, |             stderr, | ||||||
|  | @ -780,6 +817,16 @@ char *TypeTagToString(TypeTag *tag) | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|     case Custom: |     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, |     FunctionSignatureArguments, | ||||||
|     GenericArgument, |     GenericArgument, | ||||||
|     GenericArguments, |     GenericArguments, | ||||||
|  |     GenericTypeNode, | ||||||
|     Identifier, |     Identifier, | ||||||
|     IfStatement, |     IfStatement, | ||||||
|     IfElseStatement, |     IfElseStatement, | ||||||
|  | @ -89,7 +90,8 @@ typedef struct TypeTag | ||||||
|         Unknown, |         Unknown, | ||||||
|         Primitive, |         Primitive, | ||||||
|         Reference, |         Reference, | ||||||
|         Custom |         Custom, | ||||||
|  |         Generic | ||||||
|     } type; |     } type; | ||||||
|     union |     union | ||||||
|     { |     { | ||||||
|  | @ -99,6 +101,8 @@ typedef struct TypeTag | ||||||
|         struct TypeTag *referenceType; |         struct TypeTag *referenceType; | ||||||
|         /* Valid when type = Custom. */ |         /* Valid when type = Custom. */ | ||||||
|         char *customType; |         char *customType; | ||||||
|  |         /* Valid when type = Generic. */ | ||||||
|  |         char *genericType; | ||||||
|     } value; |     } value; | ||||||
| } TypeTag; | } TypeTag; | ||||||
| 
 | 
 | ||||||
|  | @ -215,6 +219,11 @@ struct Node | ||||||
|             uint32_t count; |             uint32_t count; | ||||||
|         } genericArguments; |         } genericArguments; | ||||||
| 
 | 
 | ||||||
|  |         struct | ||||||
|  |         { | ||||||
|  |             char *name; | ||||||
|  |         } genericType; | ||||||
|  | 
 | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|             char *name; |             char *name; | ||||||
|  | @ -330,6 +339,7 @@ Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode); | ||||||
| Node *MakeEmptyGenericArgumentsNode(); | Node *MakeEmptyGenericArgumentsNode(); | ||||||
| Node *StartGenericArgumentsNode(Node *genericArgumentNode); | Node *StartGenericArgumentsNode(Node *genericArgumentNode); | ||||||
| Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode); | ||||||
|  | Node *MakeGenericTypeNode(char *name); | ||||||
| Node *MakeStructDeclarationNode( | Node *MakeStructDeclarationNode( | ||||||
|     Node *identifierNode, |     Node *identifierNode, | ||||||
|     Node *declarationSequenceNode); |     Node *declarationSequenceNode); | ||||||
|  |  | ||||||
|  | @ -150,9 +150,9 @@ IdNode *MakeIdTree(Node *astNode, IdNode *parent) | ||||||
|         mainNode = MakeIdNode(Function, funcName, parent); |         mainNode = MakeIdNode(Function, funcName, parent); | ||||||
|         mainNode->typeTag = MakeTypeTag(astNode); |         mainNode->typeTag = MakeTypeTag(astNode); | ||||||
|         idNode->typeTag = mainNode->typeTag; |         idNode->typeTag = mainNode->typeTag; | ||||||
|  |         MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); | ||||||
|         MakeIdTree(sigNode->functionSignature.arguments, mainNode); |         MakeIdTree(sigNode->functionSignature.arguments, mainNode); | ||||||
|         MakeIdTree(astNode->functionDeclaration.functionBody, mainNode); |         MakeIdTree(astNode->functionDeclaration.functionBody, mainNode); | ||||||
|         MakeIdTree(sigNode->functionSignature.genericArguments, mainNode); |  | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										11
									
								
								src/main.c
								
								
								
								
							|  | @ -4,6 +4,7 @@ | ||||||
| #include "codegen.h" | #include "codegen.h" | ||||||
| #include "identcheck.h" | #include "identcheck.h" | ||||||
| #include "parser.h" | #include "parser.h" | ||||||
|  | #include "typeutils.h" | ||||||
| 
 | 
 | ||||||
| int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|  | @ -87,9 +88,19 @@ int main(int argc, char *argv[]) | ||||||
|                 { |                 { | ||||||
|                     { |                     { | ||||||
|                         IdNode *idTree = MakeIdTree(rootNode, NULL); |                         IdNode *idTree = MakeIdTree(rootNode, NULL); | ||||||
|  |                         printf("\n"); | ||||||
|                         PrintIdTree(idTree, /*tabCount=*/0); |                         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"); |                         printf("\n"); | ||||||
|                         PrintNode(rootNode, /*tabCount=*/0); |                         PrintNode(rootNode, /*tabCount=*/0); | ||||||
|  | 
 | ||||||
|                     } |                     } | ||||||
|                     exitCode = Codegen(rootNode, optimizationLevel); |                     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