groundwork for struct generics

pull/11/head
cosmonaut 2021-06-02 19:03:58 -07:00
parent a571edcf6d
commit f3435f8659
4 changed files with 115 additions and 11 deletions

View File

@ -113,9 +113,13 @@ BaseType : VOID
{ {
$$ = MakePrimitiveTypeNode(MemoryAddress); $$ = MakePrimitiveTypeNode(MemoryAddress);
} }
| Identifier GenericArgumentClauseNonEmpty
{
$$ = MakeConcreteGenericTypeNode($1, $2);
}
| Identifier | Identifier
{ {
$$ = MakeCustomTypeNode(yytext); $$ = MakeCustomTypeNode($1);
} }
| REFERENCE LESS_THAN Type GREATER_THAN | REFERENCE LESS_THAN Type GREATER_THAN
{ {
@ -359,11 +363,13 @@ GenericArguments : GenericArgument
$$ = AddGenericArgument($1, $3); $$ = AddGenericArgument($1, $3);
} }
GenericArgumentClauseNonEmpty : LESS_THAN GenericArguments GREATER_THAN
GenericArgumentClause : LESS_THAN GenericArguments GREATER_THAN
{ {
$$ = $2; $$ = $2;
} }
;
GenericArgumentClause : GenericArgumentClauseNonEmpty
| |
{ {
$$ = MakeEmptyGenericArgumentsNode(); $$ = MakeEmptyGenericArgumentsNode();

View File

@ -24,6 +24,7 @@ struct Program {
static Main(): int { static Main(): int {
x: int = 4; x: int = 4;
y: int = Foo.Func(x); y: int = Foo.Func(x);
block: MemoryBlock<int>;
addr: MemoryAddress = @malloc(y); addr: MemoryAddress = @malloc(y);
@free(addr); @free(addr);
return x; return x;

View File

@ -19,6 +19,8 @@ const char *SyntaxKindString(SyntaxKind syntaxKind)
return "BinaryExpression"; return "BinaryExpression";
case Comment: case Comment:
return "Comment"; return "Comment";
case ConcreteGenericTypeNode:
return "ConcreteGenericTypeNode";
case CustomTypeNode: case CustomTypeNode:
return "CustomTypeNode"; return "CustomTypeNode";
case Declaration: case Declaration:
@ -95,11 +97,12 @@ Node *MakePrimitiveTypeNode(PrimitiveType type)
return node; return node;
} }
Node *MakeCustomTypeNode(char *name) Node *MakeCustomTypeNode(Node *identifierNode)
{ {
Node *node = (Node *)malloc(sizeof(Node)); Node *node = (Node *)malloc(sizeof(Node));
node->syntaxKind = CustomTypeNode; node->syntaxKind = CustomTypeNode;
node->customType.name = strdup(name); node->customType.name = strdup(identifierNode->identifier.name);
free(identifierNode);
return node; return node;
} }
@ -111,6 +114,18 @@ Node *MakeReferenceTypeNode(Node *typeNode)
return node; 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 *MakeTypeNode(Node *typeNode)
{ {
Node *node = (Node *)malloc(sizeof(Node)); Node *node = (Node *)malloc(sizeof(Node));
@ -624,6 +639,11 @@ void PrintNode(Node *node, uint32_t tabCount)
PrintNode(node->binaryExpression.right, tabCount + 1); PrintNode(node->binaryExpression.right, tabCount + 1);
return; return;
case ConcreteGenericTypeNode:
printf("%s\n", node->concreteGenericType.name);
PrintNode(node->concreteGenericType.genericArguments, tabCount + 1);
return;
case CustomTypeNode: case CustomTypeNode:
printf("%s\n", node->customType.name); printf("%s\n", node->customType.name);
return; return;
@ -843,6 +863,10 @@ void Recurse(Node *node, void (*func)(Node *))
case Comment: case Comment:
return; return;
case ConcreteGenericTypeNode:
func(node->concreteGenericType.genericArguments);
return;
case CustomTypeNode: case CustomTypeNode:
return; return;
@ -1004,6 +1028,8 @@ void Recurse(Node *node, void (*func)(Node *))
TypeTag *MakeTypeTag(Node *node) TypeTag *MakeTypeTag(Node *node)
{ {
uint32_t i;
if (node == NULL) if (node == NULL)
{ {
fprintf( fprintf(
@ -1034,6 +1060,28 @@ TypeTag *MakeTypeTag(Node *node)
tag->value.customType = strdup(node->customType.name); tag->value.customType = strdup(node->customType.name);
break; 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: case Declaration:
tag = MakeTypeTag(node->declaration.type); tag = MakeTypeTag(node->declaration.type);
break; break;
@ -1078,6 +1126,8 @@ TypeTag *MakeTypeTag(Node *node)
char *TypeTagToString(TypeTag *tag) char *TypeTagToString(TypeTag *tag)
{ {
uint32_t i;
if (tag == NULL) if (tag == NULL)
{ {
fprintf( fprintf(
@ -1114,6 +1164,31 @@ char *TypeTagToString(TypeTag *tag)
sprintf(result, "Generic<%s>", tag->value.genericType); sprintf(result, "Generic<%s>", tag->value.genericType);
return result; 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;
}
} }
} }

View File

@ -19,6 +19,7 @@ typedef enum
Assignment, Assignment,
BinaryExpression, BinaryExpression,
Comment, Comment,
ConcreteGenericTypeNode,
CustomTypeNode, CustomTypeNode,
Declaration, Declaration,
DeclarationSequence, DeclarationSequence,
@ -86,7 +87,16 @@ typedef union
BinaryOperator binaryOperator; BinaryOperator binaryOperator;
} Operator; } Operator;
typedef struct TypeTag typedef struct TypeTag TypeTag;
typedef struct ConcreteGenericTypeTag
{
char *name;
TypeTag **genericArguments;
uint32_t genericArgumentCount;
} ConcreteGenericTypeTag;
struct TypeTag
{ {
enum Type enum Type
{ {
@ -94,7 +104,8 @@ typedef struct TypeTag
Primitive, Primitive,
Reference, Reference,
Custom, Custom,
Generic Generic,
ConcreteGeneric
} type; } type;
union union
{ {
@ -106,8 +117,10 @@ typedef struct TypeTag
char *customType; char *customType;
/* Valid when type = Generic. */ /* Valid when type = Generic. */
char *genericType; char *genericType;
/* Valid when type = ConcreteGeneric */
ConcreteGenericTypeTag concreteGenericType;
} value; } value;
} TypeTag; };
typedef struct Node Node; typedef struct Node Node;
@ -146,6 +159,12 @@ struct Node
} comment; } comment;
struct
{
char *name;
Node *genericArguments;
} concreteGenericType;
struct struct
{ {
char *name; char *name;
@ -329,8 +348,11 @@ const char *SyntaxKindString(SyntaxKind syntaxKind);
uint8_t IsPrimitiveType(Node *typeNode); uint8_t IsPrimitiveType(Node *typeNode);
Node *MakePrimitiveTypeNode(PrimitiveType type); Node *MakePrimitiveTypeNode(PrimitiveType type);
Node *MakeCustomTypeNode(char *string); Node *MakeCustomTypeNode(Node *identifierNode);
Node *MakeReferenceTypeNode(Node *typeNode); Node *MakeReferenceTypeNode(Node *typeNode);
Node *MakeConcreteGenericTypeNode(
Node *identifierNode,
Node *genericArgumentsNode);
Node *MakeTypeNode(Node *typeNode); Node *MakeTypeNode(Node *typeNode);
Node *MakeIdentifierNode(const char *id); Node *MakeIdentifierNode(const char *id);
Node *MakeNumberNode(const char *numberString); Node *MakeNumberNode(const char *numberString);