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