forked from cosmonaut/wraith-lang
initial generics stuff
parent
473b706ad9
commit
24bcef6d87
|
@ -307,14 +307,38 @@ Body : LEFT_BRACE Statements RIGHT_BRACE
|
|||
$$ = $2;
|
||||
}
|
||||
|
||||
FunctionSignature : Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
|
||||
GenericArgument : Identifier
|
||||
{
|
||||
$$ = MakeFunctionSignatureNode($1, $6, $3, MakeFunctionModifiersNode(NULL, 0));
|
||||
$$ = MakeGenericArgumentNode($1, NULL);
|
||||
}
|
||||
| STATIC Identifier LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
|
||||
|
||||
GenericArguments : GenericArgument
|
||||
{
|
||||
$$ = StartGenericArgumentsNode($1);
|
||||
}
|
||||
| GenericArguments COMMA GenericArgument
|
||||
{
|
||||
$$ = AddGenericArgument($1, $3);
|
||||
}
|
||||
|
||||
GenericArgumentsClause : LESS_THAN GenericArguments GREATER_THAN
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
|
||||
{
|
||||
$$ = MakeEmptyGenericArgumentsNode();
|
||||
}
|
||||
|
||||
|
||||
FunctionSignature : Identifier GenericArgumentsClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
|
||||
{
|
||||
$$ = MakeFunctionSignatureNode($1, $7, $4, MakeFunctionModifiersNode(NULL, 0), $2);
|
||||
}
|
||||
| STATIC Identifier GenericArgumentsClause LEFT_PAREN SignatureArguments RIGHT_PAREN COLON Type
|
||||
{
|
||||
Node *modifier = MakeStaticNode();
|
||||
$$ = MakeFunctionSignatureNode($2, $7, $4, MakeFunctionModifiersNode(&modifier, 1));
|
||||
$$ = MakeFunctionSignatureNode($2, $8, $5, MakeFunctionModifiersNode(&modifier, 1), $3);
|
||||
}
|
||||
|
||||
FunctionDeclaration : FunctionSignature Body
|
||||
|
|
44
src/ast.c
44
src/ast.c
|
@ -271,7 +271,8 @@ Node *MakeFunctionSignatureNode(
|
|||
Node *identifierNode,
|
||||
Node *typeNode,
|
||||
Node *arguments,
|
||||
Node *modifiersNode)
|
||||
Node *modifiersNode,
|
||||
Node *genericArgumentsNode)
|
||||
{
|
||||
Node *node = (Node *)malloc(sizeof(Node));
|
||||
node->syntaxKind = FunctionSignature;
|
||||
|
@ -279,6 +280,7 @@ Node *MakeFunctionSignatureNode(
|
|||
node->functionSignature.type = typeNode;
|
||||
node->functionSignature.arguments = arguments;
|
||||
node->functionSignature.modifiers = modifiersNode;
|
||||
node->functionSignature.genericArguments = genericArgumentsNode;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -359,6 +361,46 @@ Node *MakeEmptyFunctionArgumentSequenceNode()
|
|||
return node;
|
||||
}
|
||||
|
||||
Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode)
|
||||
{
|
||||
Node *node = (Node *)malloc(sizeof(Node));
|
||||
node->syntaxKind = GenericArgument;
|
||||
node->genericArgument.identifier = identifierNode;
|
||||
node->genericArgument.constraint = constraintNode;
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *StartGenericArgumentsNode(Node *genericArgumentNode)
|
||||
{
|
||||
Node *node = (Node *)malloc(sizeof(Node));
|
||||
node->syntaxKind = GenericArguments;
|
||||
node->genericArguments.arguments = (Node **)malloc(sizeof(Node *));
|
||||
node->genericArguments.arguments[0] = genericArgumentNode;
|
||||
node->genericArguments.count = 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode)
|
||||
{
|
||||
genericArgumentsNode->genericArguments.arguments = (Node **)realloc(
|
||||
genericArgumentsNode->genericArguments.arguments,
|
||||
sizeof(Node *) * (genericArgumentsNode->genericArguments.count + 1));
|
||||
genericArgumentsNode->genericArguments
|
||||
.arguments[genericArgumentsNode->genericArguments.count] =
|
||||
genericArgumentNode;
|
||||
genericArgumentsNode->genericArguments.count += 1;
|
||||
return genericArgumentsNode;
|
||||
}
|
||||
|
||||
Node *MakeEmptyGenericArgumentsNode()
|
||||
{
|
||||
Node *node = (Node *)malloc(sizeof(Node));
|
||||
node->syntaxKind = GenericArguments;
|
||||
node->genericArguments.arguments = NULL;
|
||||
node->genericArguments.count = 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *MakeFunctionCallExpressionNode(
|
||||
Node *identifierNode,
|
||||
Node *argumentSequenceNode)
|
||||
|
|
22
src/ast.h
22
src/ast.h
|
@ -30,6 +30,8 @@ typedef enum
|
|||
FunctionModifiers,
|
||||
FunctionSignature,
|
||||
FunctionSignatureArguments,
|
||||
GenericArgument,
|
||||
GenericArguments,
|
||||
Identifier,
|
||||
IfStatement,
|
||||
IfElseStatement,
|
||||
|
@ -192,6 +194,7 @@ struct Node
|
|||
Node *type;
|
||||
Node *arguments;
|
||||
Node *modifiers;
|
||||
Node *genericArguments;
|
||||
} functionSignature;
|
||||
|
||||
struct
|
||||
|
@ -200,6 +203,18 @@ struct Node
|
|||
uint32_t count;
|
||||
} functionSignatureArguments;
|
||||
|
||||
struct
|
||||
{
|
||||
Node *identifier;
|
||||
Node *constraint;
|
||||
} genericArgument;
|
||||
|
||||
struct
|
||||
{
|
||||
Node **arguments;
|
||||
uint32_t count;
|
||||
} genericArguments;
|
||||
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
|
@ -306,10 +321,15 @@ Node *MakeFunctionSignatureNode(
|
|||
Node *identifierNode,
|
||||
Node *typeNode,
|
||||
Node *argumentsNode,
|
||||
Node *modifiersNode);
|
||||
Node *modifiersNode,
|
||||
Node *genericArgumentsNode);
|
||||
Node *MakeFunctionDeclarationNode(
|
||||
Node *functionSignatureNode,
|
||||
Node *functionBodyNode);
|
||||
Node *MakeGenericArgumentNode(Node *identifierNode, Node *constraintNode);
|
||||
Node *MakeEmptyGenericArgumentsNode();
|
||||
Node *StartGenericArgumentsNode(Node *genericArgumentNode);
|
||||
Node *AddGenericArgument(Node *genericArgumentsNode, Node *genericArgumentNode);
|
||||
Node *MakeStructDeclarationNode(
|
||||
Node *identifierNode,
|
||||
Node *declarationSequenceNode);
|
||||
|
|
229
src/codegen.c
229
src/codegen.c
|
@ -56,6 +56,24 @@ typedef struct StructTypeFunction
|
|||
uint8_t isStatic;
|
||||
} StructTypeFunction;
|
||||
|
||||
typedef struct StructTypeGenericFunction
|
||||
{
|
||||
char *name;
|
||||
Node *functionDeclarationNode;
|
||||
} StructTypeGenericFunction;
|
||||
|
||||
typedef struct MonomorphizedGenericFunctionHashEntry
|
||||
{
|
||||
uint64_t key;
|
||||
StructTypeFunction function;
|
||||
} MonomorphizedGenericFunctionHashEntry;
|
||||
|
||||
typedef struct MonomorphizedGenericFunctionHashArray
|
||||
{
|
||||
MonomorphizedGenericFunctionHashEntry *elements;
|
||||
uint32_t count;
|
||||
} MonomorphizedGenericFunctionHashArray;
|
||||
|
||||
typedef struct StructTypeDeclaration
|
||||
{
|
||||
char *name;
|
||||
|
@ -66,6 +84,11 @@ typedef struct StructTypeDeclaration
|
|||
|
||||
StructTypeFunction *functions;
|
||||
uint32_t functionCount;
|
||||
|
||||
StructTypeGenericFunction *genericFunctions;
|
||||
uint32_t genericFunctionCount;
|
||||
|
||||
MonomorphizedGenericFunctionHashArray monomorphizedGenericFunctions;
|
||||
} StructTypeDeclaration;
|
||||
|
||||
StructTypeDeclaration *structTypeDeclarations;
|
||||
|
@ -271,6 +294,10 @@ static void AddStructDeclaration(
|
|||
structTypeDeclarations[index].fieldCount = 0;
|
||||
structTypeDeclarations[index].functions = NULL;
|
||||
structTypeDeclarations[index].functionCount = 0;
|
||||
structTypeDeclarations[index].genericFunctions = NULL;
|
||||
structTypeDeclarations[index].genericFunctionCount = 0;
|
||||
structTypeDeclarations[index].monomorphizedGenericFunctions.elements = NULL;
|
||||
structTypeDeclarations[index].monomorphizedGenericFunctions.count = 0;
|
||||
|
||||
for (i = 0; i < fieldDeclarationCount; i += 1)
|
||||
{
|
||||
|
@ -287,6 +314,7 @@ static void AddStructDeclaration(
|
|||
structTypeDeclarationCount += 1;
|
||||
}
|
||||
|
||||
/* FIXME: pass the declaration itself */
|
||||
static void DeclareStructFunction(
|
||||
LLVMTypeRef wStructPointerType,
|
||||
LLVMValueRef function,
|
||||
|
@ -318,6 +346,31 @@ static void DeclareStructFunction(
|
|||
fprintf(stderr, "Could not find struct type for function!\n");
|
||||
}
|
||||
|
||||
/* FIXME: pass the declaration itself */
|
||||
static void DeclareGenericStructFunction(
|
||||
LLVMTypeRef wStructPointerType,
|
||||
Node *functionDeclarationNode,
|
||||
char *name)
|
||||
{
|
||||
uint32_t i, index;
|
||||
|
||||
for (i = 0; i < structTypeDeclarationCount; i += 1)
|
||||
{
|
||||
if (structTypeDeclarations[i].structPointerType == wStructPointerType)
|
||||
{
|
||||
index = structTypeDeclarations[i].genericFunctionCount;
|
||||
structTypeDeclarations[i].genericFunctions[index].name =
|
||||
strdup(name);
|
||||
structTypeDeclarations[i]
|
||||
.genericFunctions[index]
|
||||
.functionDeclarationNode = functionDeclarationNode;
|
||||
structTypeDeclarations[i].genericFunctionCount += 1;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LLVMTypeRef LookupCustomType(char *name)
|
||||
{
|
||||
uint32_t i;
|
||||
|
@ -1023,101 +1076,115 @@ static void CompileFunction(
|
|||
}
|
||||
}
|
||||
|
||||
if (!isStatic)
|
||||
{
|
||||
paramTypes[paramIndex] = wStructPointerType;
|
||||
paramIndex += 1;
|
||||
}
|
||||
|
||||
PushScopeFrame(scope);
|
||||
|
||||
/* FIXME: should work for non-primitive types */
|
||||
for (i = 0; i < functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.count;
|
||||
i += 1)
|
||||
{
|
||||
paramTypes[paramIndex] =
|
||||
ResolveType(functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.type);
|
||||
paramIndex += 1;
|
||||
}
|
||||
|
||||
LLVMTypeRef returnType =
|
||||
ResolveType(functionSignature->functionSignature.type);
|
||||
LLVMTypeRef functionType =
|
||||
LLVMFunctionType(returnType, paramTypes, paramIndex, 0);
|
||||
|
||||
char *functionName = strdup(parentStructName);
|
||||
strcat(functionName, "_");
|
||||
strcat(
|
||||
functionName,
|
||||
functionSignature->functionSignature.identifier->identifier.name);
|
||||
LLVMValueRef function = LLVMAddFunction(module, functionName, functionType);
|
||||
free(functionName);
|
||||
|
||||
DeclareStructFunction(
|
||||
wStructPointerType,
|
||||
function,
|
||||
returnType,
|
||||
isStatic,
|
||||
functionSignature->functionSignature.identifier->identifier.name);
|
||||
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
|
||||
LLVMBuilderRef builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
|
||||
if (!isStatic)
|
||||
if (functionSignature->functionSignature.genericArguments->genericArguments
|
||||
.count == 0)
|
||||
{
|
||||
LLVMValueRef wStructPointer = LLVMGetParam(function, 0);
|
||||
AddStructVariablesToScope(builder, wStructPointer);
|
||||
}
|
||||
PushScopeFrame(scope);
|
||||
|
||||
for (i = 0; i < functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.count;
|
||||
i += 1)
|
||||
{
|
||||
char *ptrName = strdup(functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.identifier->identifier.name);
|
||||
strcat(ptrName, "_ptr");
|
||||
LLVMValueRef argument = LLVMGetParam(function, i + !isStatic);
|
||||
LLVMValueRef argumentCopy =
|
||||
LLVMBuildAlloca(builder, LLVMTypeOf(argument), ptrName);
|
||||
LLVMBuildStore(builder, argument, argumentCopy);
|
||||
free(ptrName);
|
||||
AddLocalVariable(
|
||||
scope,
|
||||
argumentCopy,
|
||||
NULL,
|
||||
functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.identifier->identifier.name);
|
||||
}
|
||||
if (!isStatic)
|
||||
{
|
||||
paramTypes[paramIndex] = wStructPointerType;
|
||||
paramIndex += 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < functionBody->statementSequence.count; i += 1)
|
||||
{
|
||||
CompileStatement(
|
||||
builder,
|
||||
for (i = 0; i < functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.count;
|
||||
i += 1)
|
||||
{
|
||||
paramTypes[paramIndex] =
|
||||
ResolveType(functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.type);
|
||||
paramIndex += 1;
|
||||
}
|
||||
|
||||
LLVMTypeRef returnType =
|
||||
ResolveType(functionSignature->functionSignature.type);
|
||||
LLVMTypeRef functionType =
|
||||
LLVMFunctionType(returnType, paramTypes, paramIndex, 0);
|
||||
|
||||
LLVMValueRef function =
|
||||
LLVMAddFunction(module, functionName, functionType);
|
||||
|
||||
DeclareStructFunction(
|
||||
wStructPointerType,
|
||||
function,
|
||||
functionBody->statementSequence.sequence[i]);
|
||||
returnType,
|
||||
isStatic,
|
||||
functionSignature->functionSignature.identifier->identifier.name);
|
||||
|
||||
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry");
|
||||
LLVMBuilderRef builder = LLVMCreateBuilder();
|
||||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
|
||||
if (!isStatic)
|
||||
{
|
||||
LLVMValueRef wStructPointer = LLVMGetParam(function, 0);
|
||||
AddStructVariablesToScope(builder, wStructPointer);
|
||||
}
|
||||
|
||||
for (i = 0; i < functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.count;
|
||||
i += 1)
|
||||
{
|
||||
char *ptrName =
|
||||
strdup(functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.identifier->identifier.name);
|
||||
strcat(ptrName, "_ptr");
|
||||
LLVMValueRef argument = LLVMGetParam(function, i + !isStatic);
|
||||
LLVMValueRef argumentCopy =
|
||||
LLVMBuildAlloca(builder, LLVMTypeOf(argument), ptrName);
|
||||
LLVMBuildStore(builder, argument, argumentCopy);
|
||||
free(ptrName);
|
||||
AddLocalVariable(
|
||||
scope,
|
||||
argumentCopy,
|
||||
NULL,
|
||||
functionSignature->functionSignature.arguments
|
||||
->functionSignatureArguments.sequence[i]
|
||||
->declaration.identifier->identifier.name);
|
||||
}
|
||||
|
||||
for (i = 0; i < functionBody->statementSequence.count; i += 1)
|
||||
{
|
||||
CompileStatement(
|
||||
builder,
|
||||
function,
|
||||
functionBody->statementSequence.sequence[i]);
|
||||
}
|
||||
|
||||
hasReturn = LLVMGetBasicBlockTerminator(
|
||||
LLVMGetLastBasicBlock(function)) != NULL;
|
||||
|
||||
if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn)
|
||||
{
|
||||
LLVMBuildRetVoid(builder);
|
||||
}
|
||||
else if (LLVMGetTypeKind(returnType) != LLVMVoidTypeKind && !hasReturn)
|
||||
{
|
||||
fprintf(stderr, "Return statement not provided!");
|
||||
}
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
|
||||
PopScopeFrame(scope);
|
||||
}
|
||||
|
||||
hasReturn =
|
||||
LLVMGetBasicBlockTerminator(LLVMGetLastBasicBlock(function)) != NULL;
|
||||
|
||||
if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn)
|
||||
else
|
||||
{
|
||||
LLVMBuildRetVoid(builder);
|
||||
}
|
||||
else if (LLVMGetTypeKind(returnType) != LLVMVoidTypeKind && !hasReturn)
|
||||
{
|
||||
fprintf(stderr, "Return statement not provided!");
|
||||
DeclareGenericStructFunction(
|
||||
wStructPointerType,
|
||||
functionDeclaration,
|
||||
functionName);
|
||||
}
|
||||
|
||||
PopScopeFrame(scope);
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
free(functionName);
|
||||
}
|
||||
|
||||
static void CompileStruct(
|
||||
|
|
Loading…
Reference in New Issue