You can now forward declare functions!
This commit is contained in:
parent
bae0d82f26
commit
b1c7a26cfb
@ -59,6 +59,8 @@ add_executable(
|
||||
src/AST/FunctionPrototype.h
|
||||
src/AST/FunctionNode.cpp
|
||||
src/AST/FunctionNode.h
|
||||
src/AST/EmptyFunctionNode.cpp
|
||||
src/AST/EmptyFunctionNode.h
|
||||
src/GlobalContext.cpp
|
||||
src/GlobalContext.h
|
||||
src/utils.cpp
|
||||
|
27
src/AST/EmptyFunctionNode.cpp
Normal file
27
src/AST/EmptyFunctionNode.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "EmptyFunctionNode.h"
|
||||
#include "../Error.h"
|
||||
#include "../utils.h"
|
||||
|
||||
EmptyFunctionNode::EmptyFunctionNode(FunctionPrototype prototype) : TopLevelNode(), prototype(prototype)
|
||||
{
|
||||
}
|
||||
|
||||
void EmptyFunctionNode::codegen(IRBuilder* generator, llvm::Module* module)
|
||||
{
|
||||
llvm::Function* Function = module->getFunction(prototype.name);
|
||||
if (!Function)
|
||||
{
|
||||
llvm::FunctionType* Type = prototype.toFunctionType();
|
||||
|
||||
Function = llvm::Function::Create(Type, llvm::Function::ExternalLinkage, prototype.name, *module);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!equals(Function->getFunctionType(), prototype.toFunctionType()))
|
||||
{
|
||||
// FIXME: add location information to AST nodes, to add information to these errors
|
||||
Error::throw_error_without_location(
|
||||
format_string("Function %s redefined with different prototype", prototype.name.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
16
src/AST/EmptyFunctionNode.h
Normal file
16
src/AST/EmptyFunctionNode.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "../IRBuilder.h"
|
||||
#include "FunctionPrototype.h"
|
||||
#include "TopLevelNode.h"
|
||||
|
||||
class EmptyFunctionNode final : public TopLevelNode
|
||||
{
|
||||
private:
|
||||
FunctionPrototype prototype;
|
||||
|
||||
public:
|
||||
EmptyFunctionNode(FunctionPrototype prototype);
|
||||
~EmptyFunctionNode() = default;
|
||||
|
||||
void codegen(IRBuilder* generator, llvm::Module* module) override;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
#include "Parser.h"
|
||||
#include "AST/EmptyFunctionNode.h"
|
||||
#include "AST/FunctionNode.h"
|
||||
#include "AST/MulNode.h"
|
||||
#include "AST/SumNode.h"
|
||||
@ -97,6 +98,7 @@ Result<TopLevelNode> Parser::toplevel()
|
||||
Result<TopLevelNode> Parser::function()
|
||||
{
|
||||
FunctionPrototype proto;
|
||||
Token* ftoken = current_token;
|
||||
proto.returnType = llvm::IntegerType::getInt32Ty(*globalContext); // FIXME: allow specifying return type
|
||||
proto.arguments = {}; // FIXME: allow specifying arguments
|
||||
if (current_token->tk_type != TT_Let)
|
||||
@ -110,9 +112,12 @@ Result<TopLevelNode> Parser::function()
|
||||
proto.name = current_token->string_value;
|
||||
advance();
|
||||
if (current_token->tk_type != TT_In && current_token->tk_type != TT_Semicolon)
|
||||
return Err<TopLevelNode>("Expected 'in'", current_token);
|
||||
return Err<TopLevelNode>("Expected 'in' or semicolon", current_token);
|
||||
if (current_token->tk_type == TT_Semicolon)
|
||||
return Err<TopLevelNode>("Functions without a body are unsupported (for now)", current_token);
|
||||
{
|
||||
advance();
|
||||
return Ok<TopLevelNode>(new EmptyFunctionNode(proto), ftoken);
|
||||
}
|
||||
advance();
|
||||
if (current_token->tk_type != TT_LBracket)
|
||||
return Err<TopLevelNode>("Invalid syntax",
|
||||
@ -123,5 +128,5 @@ Result<TopLevelNode> Parser::function()
|
||||
if (current_token->tk_type != TT_RBracket)
|
||||
return Err<TopLevelNode>(format_string("Invalid syntax %d", current_token->tk_type), current_token);
|
||||
advance();
|
||||
return Ok<TopLevelNode>(new FunctionNode(proto, body.get()), current_token);
|
||||
return Ok<TopLevelNode>(new FunctionNode(proto, body.get()), ftoken);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user