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