diff --git a/generators/wraith.y b/generators/wraith.y index 803d922..53678f9 100644 --- a/generators/wraith.y +++ b/generators/wraith.y @@ -113,9 +113,13 @@ BaseType : VOID { $$ = MakePrimitiveTypeNode(MemoryAddress); } + | Identifier GenericArgumentClauseNonEmpty + { + $$ = MakeConcreteGenericTypeNode($1, $2); + } | Identifier { - $$ = MakeCustomTypeNode(yytext); + $$ = MakeCustomTypeNode($1); } | REFERENCE LESS_THAN Type GREATER_THAN { @@ -359,11 +363,13 @@ GenericArguments : GenericArgument $$ = AddGenericArgument($1, $3); } +GenericArgumentClauseNonEmpty : LESS_THAN GenericArguments GREATER_THAN + { + $$ = $2; + } + ; -GenericArgumentClause : LESS_THAN GenericArguments GREATER_THAN - { - $$ = $2; - } +GenericArgumentClause : GenericArgumentClauseNonEmpty | { $$ = MakeEmptyGenericArgumentsNode(); diff --git a/generic.w b/generic.w index b7f6013..8007da7 100644 --- a/generic.w +++ b/generic.w @@ -24,6 +24,7 @@ struct Program { static Main(): int { x: int = 4; y: int = Foo.Func(x); + block: MemoryBlock; addr: MemoryAddress = @malloc(y); @free(addr); return x; diff --git a/src/ast.c b/src/ast.c index dc014bb..d761850 100644 --- a/src/ast.c +++ b/src/ast.c @@ -19,6 +19,8 @@ const char *SyntaxKindString(SyntaxKind syntaxKind) return "BinaryExpression"; case Comment: return "Comment"; + case ConcreteGenericTypeNode: + return "ConcreteGenericTypeNode"; case CustomTypeNode: return "CustomTypeNode"; case Declaration: @@ -95,11 +97,12 @@ Node *MakePrimitiveTypeNode(PrimitiveType type) return node; } -Node *MakeCustomTypeNode(char *name) +Node *MakeCustomTypeNode(Node *identifierNode) { Node *node = (Node *)malloc(sizeof(Node)); node->syntaxKind = CustomTypeNode; - node->customType.name = strdup(name); + node->customType.name = strdup(identifierNode->identifier.name); + free(identifierNode); return node; } @@ -111,6 +114,18 @@ Node *MakeReferenceTypeNode(Node *typeNode) return node; } +Node *MakeConcreteGenericTypeNode( + Node *identifierNode, + Node *genericArgumentsNode) +{ + Node *node = (Node *)malloc(sizeof(Node)); + node->syntaxKind = ConcreteGenericTypeNode; + node->concreteGenericType.name = strdup(identifierNode->identifier.name); + node->concreteGenericType.genericArguments = genericArgumentsNode; + free(identifierNode); + return node; +} + Node *MakeTypeNode(Node *typeNode) { Node *node = (Node *)malloc(sizeof(Node)); @@ -624,6 +639,11 @@ void PrintNode(Node *node, uint32_t tabCount) PrintNode(node->binaryExpression.right, tabCount + 1); return; + case ConcreteGenericTypeNode: + printf("%s\n", node->concreteGenericType.name); + PrintNode(node->concreteGenericType.genericArguments, tabCount + 1); + return; + case CustomTypeNode: printf("%s\n", node->customType.name); return; @@ -843,6 +863,10 @@ void Recurse(Node *node, void (*func)(Node *)) case Comment: return; + case ConcreteGenericTypeNode: + func(node->concreteGenericType.genericArguments); + return; + case CustomTypeNode: return; @@ -1004,6 +1028,8 @@ void Recurse(Node *node, void (*func)(Node *)) TypeTag *MakeTypeTag(Node *node) { + uint32_t i; + if (node == NULL) { fprintf( @@ -1034,6 +1060,28 @@ TypeTag *MakeTypeTag(Node *node) tag->value.customType = strdup(node->customType.name); break; + case ConcreteGenericTypeNode: + tag->type = ConcreteGeneric; + tag->value.concreteGenericType.name = + strdup(node->concreteGenericType.name); + tag->value.concreteGenericType.genericArgumentCount = + node->concreteGenericType.genericArguments->genericArguments.count; + tag->value.concreteGenericType.genericArguments = malloc( + sizeof(TypeTag *) * + tag->value.concreteGenericType.genericArgumentCount); + + for (i = 0; + i < + node->concreteGenericType.genericArguments->genericArguments.count; + i += 1) + { + tag->value.concreteGenericType.genericArguments[i] = MakeTypeTag( + node->concreteGenericType.genericArguments->genericArguments + .arguments[i] + ->genericArgument.type); + } + break; + case Declaration: tag = MakeTypeTag(node->declaration.type); break; @@ -1078,6 +1126,8 @@ TypeTag *MakeTypeTag(Node *node) char *TypeTagToString(TypeTag *tag) { + uint32_t i; + if (tag == NULL) { fprintf( @@ -1114,6 +1164,31 @@ char *TypeTagToString(TypeTag *tag) sprintf(result, "Generic<%s>", tag->value.genericType); return result; } + + case ConcreteGeneric: + { + char *result = strdup(tag->value.concreteGenericType.name); + uint32_t len = strlen(result); + result = realloc(result, len + 2); + strcat(result, "<"); + + for (i = 0; i < tag->value.concreteGenericType.genericArgumentCount; + i += 1) + { + char *inner = TypeTagToString( + tag->value.concreteGenericType.genericArguments[i]); + len += strlen(inner); + result = realloc(result, sizeof(char) * (len + 3)); + if (i != tag->value.concreteGenericType.genericArgumentCount - 1) + { + strcat(result, ", "); + } + strcat(result, inner); + } + result = realloc(result, sizeof(char) * (len + 2)); + strcat(result, ">"); + return result; + } } } diff --git a/src/ast.h b/src/ast.h index c7fd974..531064b 100644 --- a/src/ast.h +++ b/src/ast.h @@ -19,6 +19,7 @@ typedef enum Assignment, BinaryExpression, Comment, + ConcreteGenericTypeNode, CustomTypeNode, Declaration, DeclarationSequence, @@ -86,7 +87,16 @@ typedef union BinaryOperator binaryOperator; } Operator; -typedef struct TypeTag +typedef struct TypeTag TypeTag; + +typedef struct ConcreteGenericTypeTag +{ + char *name; + TypeTag **genericArguments; + uint32_t genericArgumentCount; +} ConcreteGenericTypeTag; + +struct TypeTag { enum Type { @@ -94,7 +104,8 @@ typedef struct TypeTag Primitive, Reference, Custom, - Generic + Generic, + ConcreteGeneric } type; union { @@ -106,8 +117,10 @@ typedef struct TypeTag char *customType; /* Valid when type = Generic. */ char *genericType; + /* Valid when type = ConcreteGeneric */ + ConcreteGenericTypeTag concreteGenericType; } value; -} TypeTag; +}; typedef struct Node Node; @@ -146,6 +159,12 @@ struct Node } comment; + struct + { + char *name; + Node *genericArguments; + } concreteGenericType; + struct { char *name; @@ -329,8 +348,11 @@ const char *SyntaxKindString(SyntaxKind syntaxKind); uint8_t IsPrimitiveType(Node *typeNode); Node *MakePrimitiveTypeNode(PrimitiveType type); -Node *MakeCustomTypeNode(char *string); +Node *MakeCustomTypeNode(Node *identifierNode); Node *MakeReferenceTypeNode(Node *typeNode); +Node *MakeConcreteGenericTypeNode( + Node *identifierNode, + Node *genericArgumentsNode); Node *MakeTypeNode(Node *typeNode); Node *MakeIdentifierNode(const char *id); Node *MakeNumberNode(const char *numberString);