Skip to content

Commit

Permalink
修复名字查找bug (#29)
Browse files Browse the repository at this point in the history
* Support more codegen

* Implement LLVM Backend

* Implement error expression

* Fix name lookup
  • Loading branch information
heckerpowered authored Oct 2, 2024
1 parent 71af38b commit daa83e6
Show file tree
Hide file tree
Showing 27 changed files with 651 additions and 317 deletions.
48 changes: 25 additions & 23 deletions src/Mamba/Code Analysis/Binding/Binder.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
#include "Binder.h"
#include "BoundCallExpression.h"
#include "BoundCompoundAssignmentExpression.h"
#include "BoundErrorExpression.h"
#include "BoundExpression.h"
#include "BoundExpressionStatement.h"
#include "BoundScope.h"
#include "Constant.h"
#include "fast_io.h"
#include "MambaCore.h"
#include "SyntaxFacts.h"
#include "TypeSymbol.h"

#include <source_location>

using namespace Mamba;
Expand All @@ -31,22 +37,17 @@ void Binder::BindMember(const MemberSyntax* Member) noexcept
void Binder::BindFunctionDeclaration(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept
{
auto FunctionScope = EnterScope();
auto Parameters = BindParameter(FunctionDeclaration);

auto Body = BindStatement(FunctionDeclaration->Body);
auto BoundFunctionDeclaration = new class BoundFunctionDeclaration(FunctionDeclaration, Body);

FunctionScope.PreLeave();

DeclareFunction(FunctionDeclaration, BoundFunctionDeclaration);
DeclareFunction(FunctionDeclaration, BoundFunctionDeclaration, std::move(Parameters));
}

void Binder::DeclareFunction(
const FunctionDeclarationSyntax* FunctionDeclaration,
const BoundFunctionDeclaration* BoundFunctionDeclaration
) noexcept
void Binder::DeclareFunction(const FunctionDeclarationSyntax* FunctionDeclaration, const BoundFunctionDeclaration* BoundFunctionDeclaration, std::vector<const ParameterSymbol*>&& Parameters) noexcept
{
auto Name = FunctionDeclaration->Identifier->Text();
auto Parameters = BindParameter(FunctionDeclaration);
auto Type = BindTypeClause(FunctionDeclaration->Type);
auto FunctionSymbol = new class FunctionSymbol(Name, std::move(Parameters), Type ? Type : &TypeSymbol::Void, BoundFunctionDeclaration);

Expand Down Expand Up @@ -232,9 +233,9 @@ VariableSymbol* Binder::BindVariableDeclaration(const SyntaxToken* Identifier, b
BoundIfStatement* Binder::BindIfStatement(const IfStatementSyntax* IfStatement) noexcept
{
auto Condition = BindExpression(IfStatement->Condition);
if (Condition->ConstantValue().IsValid())
if (Condition->ConstantValue().IsValid() && Condition->ConstantValue().HoldsAlternative<ConstantType::Boolean>())
{
if (!Condition->ConstantValue().Get<bool>())
if (!Condition->ConstantValue().Get<ConstantType::Boolean>())
{
Diagnostics.ReportUnreachableCode(IfStatement->ElseClause->ElseStatement);
}
Expand All @@ -245,8 +246,13 @@ BoundIfStatement* Binder::BindIfStatement(const IfStatementSyntax* IfStatement)
}
}

if (Condition->Type() != &TypeSymbol::Bool)
{
Diagnostics.ReportTypeMismatch(IfStatement->Condition->Location(), TypeSymbol::Bool, *Condition->Type());
}

auto ThenStatement = BindStatement(IfStatement->ThenStatement);
auto ElseStatement = IfStatement->ElseClause ? nullptr : BindStatement(IfStatement->ElseClause->ElseStatement);
auto ElseStatement = IfStatement->ElseClause ? BindStatement(IfStatement->ElseClause->ElseStatement) : nullptr;
return new BoundIfStatement(IfStatement, Condition, ThenStatement, ElseStatement);
}

Expand Down Expand Up @@ -308,22 +314,19 @@ BoundLiteralExpression* Binder::BindLiteralExpression(const LiteralExpressionSyn
return new BoundLiteralExpression(LiteralExpression, LiteralExpression->Value);
}

BoundVariableExpression* Binder::BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept
BoundExpression* Binder::BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept
{
auto Name = NameExpression->IdentifierToken->Text();
auto Variables = Scope->LookupVariable(Name);
auto Variables = Scope->LookupParameterOrVariable(Name);
if (Variables.empty())
{
auto ErrorVariable = new VariableSymbol(TEXT("<error>"), false, &TypeSymbol::Void, {});
Scope->Declare(ErrorVariable);

Diagnostics.ReportUndeclaredIdentifier(NameExpression->Location(), Name);
return new BoundVariableExpression(NameExpression, ErrorVariable);
return new BoundErrorExpression(NameExpression);
}
else if (Variables.size() > 1)
{
Diagnostics.ReportAmbiguousIdentifier(NameExpression->Location(), Name);
return new BoundVariableExpression(NameExpression, Variables.front());
return new BoundErrorExpression(NameExpression);
}

return new BoundVariableExpression(NameExpression, Variables.front());
Expand Down Expand Up @@ -415,7 +418,7 @@ BoundExpression* Binder::BindAssignmentExpression(const AssignmentExpressionSynt
return new BoundAssignmentExpression(AssignmentExpression, Variable, BoundExpression);
}

BoundCallExpression* Binder::BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept
BoundExpression* Binder::BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept
{
auto BoundArguments = std::vector<const BoundExpression*>();
BoundArguments.reserve(CallExpression->Arguments.Count());
Expand All @@ -435,9 +438,8 @@ BoundCallExpression* Binder::BindCallExpression(const CallExpressionSyntax* Call
auto FunctionSet = Scope->LookupFunction(CallExpression->Identifier->Text());
if (FunctionSet.empty())
{
// TODO: Diagnostics - undeclaraed function
fast_io::io::perrln("Undeclaraed function '", fast_io::mnp::code_cvt(CallExpression->Identifier->Text()), "'");
return {};
Diagnostics.ReportUndeclaredIdentifier(CallExpression->Identifier->Location(), CallExpression->Identifier->Text());
return new BoundErrorExpression(CallExpression);
}

// TODO: Overload resolution. Before overload resolution is avaiable, function override is not permitted.
Expand All @@ -447,7 +449,7 @@ BoundCallExpression* Binder::BindCallExpression(const CallExpressionSyntax* Call
{
// TODO: Report argument count mismatch
fast_io::io::perrln("Failed to bind call expression: argument count mismatch.");
return {};
return new BoundErrorExpression(CallExpression);
}

// TODO: implement conversion
Expand Down
11 changes: 4 additions & 7 deletions src/Mamba/Code Analysis/Binding/Binder.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,7 @@ namespace Mamba
void BindMember(const MemberSyntax* Member) noexcept;
void BindFunctionDeclaration(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept;

void DeclareFunction(
const FunctionDeclarationSyntax* FunctionDeclaration,
const BoundFunctionDeclaration* BoundFunctionDeclaration
) noexcept;
void DeclareFunction(const FunctionDeclarationSyntax* FunctionDeclaration, const BoundFunctionDeclaration* BoundFunctionDeclaration, std::vector<const ParameterSymbol*>&& Parameters) noexcept;

VariableSymbol* BindVariableDeclaration(const SyntaxToken* Identifier, bool IsReadOnly, const TypeSymbol* Type, Constant Constant) noexcept;
std::vector<const ParameterSymbol*> BindParameter(const FunctionDeclarationSyntax* FunctionDeclaration) noexcept;
Expand All @@ -68,18 +65,18 @@ namespace Mamba
BoundExpression* BindParenthesizedExpression(const ParenthesizedExpressionSyntax* ParenthesizedExpression) noexcept;
BoundExpressionStatement* BindExpressionStatement(const ExpressionStatementSyntax* ExpressionStatement) noexcept;
BoundVariableDeclaration* BindVariableDeclaration(const VariableDeclarationSyntax* VariableDeclaration) noexcept;
BoundExpression* BindAssignmentExpression(const AssignmentExpressionSyntax* AssignmentExpression) noexcept;
NullablePointer<const TypeSymbol> BindTypeClause(NullablePointer<const TypeClauseSyntax> TypeClause) noexcept;
BoundExpression* BindAssignmentExpression(const AssignmentExpressionSyntax* AssignmentExpression) noexcept;
BoundLiteralExpression* BindLiteralExpression(const LiteralExpressionSyntax* LiteralExpression) noexcept;
BoundDoWhileStatement* BindDoWhileStatement(const DoWhileStatementSyntax* DoWhileStatement) noexcept;
BoundBinaryExpression* BindBinaryExpression(const BinaryExpressionSyntax* BinaryExpression) noexcept;
BoundUnaryExpression* BindUnaryExpression(const UnaryExpressionSyntax* UnaryExpression) noexcept;
BoundReturnStatement* BindReturnStatement(const ReturnStatementSyntax* ReturnStatement) noexcept;
BoundVariableExpression* BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept;
BoundStatement* BindContinueStatement(const ContinueStatementSyntax* ContinueStatement) noexcept;
BoundBlockStatement* BindBlockStatement(const BlockStatementSyntax* BlockStatement) noexcept;
BoundWhileStatement* BindWhileStatement(const WhileStatementSyntax* WhileStatement) noexcept;
BoundCallExpression* BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept;
BoundExpression* BindNameExpression(const NameExpressionSyntax* NameExpression) noexcept;
BoundExpression* BindCallExpression(const CallExpressionSyntax* CallExpression) noexcept;
BoundForStatement* BindForStatement(const ForStatementSyntax* ForStatement) noexcept;
BoundStatement* BindStatementInternal(const StatementSyntax* Statement) noexcept;
BoundIfStatement* BindIfStatement(const IfStatementSyntax* IfStatement) noexcept;
Expand Down
17 changes: 17 additions & 0 deletions src/Mamba/Code Analysis/Binding/BoundErrorExpression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include "BoundErrorExpression.h"
#include "TypeSymbol.h"

using namespace Mamba;

BoundErrorExpression::BoundErrorExpression(const SyntaxNode* Syntax) noexcept :
Super(Syntax) {}

BoundNodeKind BoundErrorExpression::Kind() const noexcept
{
return BoundNodeKind::ErrorExpression;
}

const TypeSymbol* BoundErrorExpression::Type() const noexcept
{
return &TypeSymbol::Error;
}
18 changes: 18 additions & 0 deletions src/Mamba/Code Analysis/Binding/BoundErrorExpression.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "BoundExpression.h"
#include "BoundNodeKind.h"

namespace Mamba
{
class BoundErrorExpression : public BoundExpression
{
public:
using Super = BoundExpression;

[[nodiscard]] BoundErrorExpression(const SyntaxNode* Syntax) noexcept;

BoundNodeKind Kind() const noexcept override;
const TypeSymbol* Type() const noexcept override;
};
} // namespace Mamba
8 changes: 8 additions & 0 deletions src/Mamba/Code Analysis/Binding/BoundScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ BoundScope* BoundScope::DeclareScope() noexcept
return ChildScope;
}

std::vector<const VariableSymbol*> BoundScope::LookupParameterOrVariable(StringView Name) const noexcept
{
return Lookup(Name) |
std::views::filter([](auto Symbol) { return Symbol->IsVariable() || Symbol->IsParameter(); }) |
std::views::transform([](auto Symbol) { return static_cast<const VariableSymbol*>(Symbol); }) |
std::ranges::to<std::vector>();
}

std::vector<const VariableSymbol*> BoundScope::LookupVariable(StringView Name) const noexcept
{
return Lookup(Name) |
Expand Down
3 changes: 2 additions & 1 deletion src/Mamba/Code Analysis/Binding/BoundScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ namespace Mamba
void Declare(const Symbol* Symbol) noexcept;
BoundScope* DeclareScope() noexcept;

std::vector<const VariableSymbol*> LookupParameterOrVariable(StringView Name) const noexcept;
std::vector<const ParameterSymbol*> LookupParameter(StringView Name) const noexcept;
std::vector<const VariableSymbol*> LookupVariable(StringView Name) const noexcept;
std::vector<const FunctionSymbol*> LookupFunction(StringView Name) const noexcept;
std::vector<const TypeSymbol*> LookupType(StringView Name) const noexcept;
std::vector<const ParameterSymbol*> LookupParameter(StringView Name) const noexcept;
std::vector<const Symbol*> Lookup(const StringView) const noexcept;

std::vector<const VariableSymbol*> DeclaredVariables() const noexcept;
Expand Down
10 changes: 8 additions & 2 deletions src/Mamba/Code Analysis/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ using namespace Mamba;

void PrintDiagnostics(std::span<const Diagnostic> Diagnostics) noexcept
{
auto HasError = false;
for (auto&& Diagnostic : Diagnostics)
{
if (Diagnostic.Severity == DiagnosticSeverity::Error)
{
HasError = true;
}

fast_io::io::println(Diagnostic);
}

if (!Diagnostics.empty())
if (HasError)
{
exit(0);
}
Expand Down Expand Up @@ -107,7 +113,7 @@ void Compiler::Compile() noexcept
PrintDiagnostics(Binder.Diagnostics);
}

LLVMBackend::GenerateCode(BoundCompilationUnits, "Main");
LLVMBackend::GenerateCode(BoundCompilationUnits, "main");

for (auto&& BoundCompilationUnit : BoundCompilationUnits)
{
Expand Down
48 changes: 46 additions & 2 deletions src/Mamba/Code Analysis/DiagnosticBag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "VariableDeclarationSyntax.h"
#include "WhileStatementSyntax.h"

#include <random>
#include <source_location>
#include <vector>

namespace Mamba
Expand Down Expand Up @@ -95,7 +97,44 @@ namespace Mamba

void DiagnosticBag::ReportUnreachableCode(const TextLocation Location) noexcept
{
ReportWarning(Location, TEXT("此处永远不会被执行"));
auto RandomDevice = std::random_device();
auto Distribution = std::uniform_int_distribution<int>(0, 6);

switch (Distribution(RandomDevice))
{
case 0:
ReportWarning(Location, TEXT("现在流行收无效代码税"));
break;
case 1:
ReportWarning(Location, TEXT("不可达的代码"));
break;
case 2:
ReportWarning(Location, TEXT("这段代码永远不会被执行"));
break;
case 3:
ReportWarning(Location, TEXT("关爱空巢代码"));
break;
case 4:
ReportWarning(Location, TEXT("你猜我会不会把这段代码优化掉"));
break;
case 5:
ReportWarning(Location, TEXT("b站搜索mq白, 问问他这段代码有什么问题"));
break;
case 6:
ReportWarning(Location, TEXT("b代码把👴气笑了"));
break;
default:
{
auto Distribution = std::uniform_int_distribution<int>(0, 1);
switch (Distribution(RandomDevice))
{
case 0:
InternalCompilerError(std::source_location::current(), "谁在用Intel? 害得我编译器ICE了");
case 1:
InternalCompilerError(std::source_location::current(), "谁在用AMD? 害得我编译器ICE了");
}
}
}
}

void DiagnosticBag::ReportUnreachableCode(const SyntaxNode* Node) noexcept
Expand All @@ -113,7 +152,7 @@ namespace Mamba
}

case SyntaxKind::VariableDeclaration:
ReportUnreachableCode(static_cast<const VariableDeclarationSyntax*>(Node)->Keyword->Location());
ReportUnreachableCode(static_cast<const VariableDeclarationSyntax*>(Node)->Location());
return;
case SyntaxKind::IfStatement:
ReportUnreachableCode(static_cast<const IfStatementSyntax*>(Node)->IfKeyword->Location());
Expand Down Expand Up @@ -156,4 +195,9 @@ namespace Mamba
{
ReportError(Location, TEXT("标识符有歧义 '"), Name, TEXT("'."));
}

void DiagnosticBag::ReportTypeMismatch(TextLocation Location, const TypeSymbol& ExpectedType, const TypeSymbol& ActualType) noexcept
{
ReportError(Location, Concat(TEXT("此处需要"), ExpectedType.Name(), TEXT("类型,实际类型: '"), ActualType.Name(), TEXT(", 无法进行隐式转换")));
}
} // namespace Mamba
3 changes: 3 additions & 0 deletions src/Mamba/Code Analysis/DiagnosticBag.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "SyntaxKind.h"
#include "SyntaxNode.h"
#include "TextLocation.h"
#include "TypeSymbol.h"

namespace Mamba
{
Expand Down Expand Up @@ -51,6 +52,8 @@ namespace Mamba

void ReportUndeclaredIdentifier(TextLocation Location, StringView Name) noexcept;
void ReportAmbiguousIdentifier(TextLocation Location, StringView Name) noexcept;

void ReportTypeMismatch(TextLocation Location, const TypeSymbol& ExpectedType, const TypeSymbol& ActualType) noexcept;
};

} // namespace Mamba
3 changes: 2 additions & 1 deletion src/Mamba/Code Analysis/Symbol/TypeSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ const TypeSymbol TypeSymbol::Int = TypeSymbol(TEXT("int"));
const TypeSymbol TypeSymbol::Bool = TypeSymbol(TEXT("bool"));
const TypeSymbol TypeSymbol::String = TypeSymbol(TEXT("string"));
const TypeSymbol TypeSymbol::Void = TypeSymbol(TEXT("void"));
const TypeSymbol TypeSymbol::Double = TypeSymbol(TEXT("double"));
const TypeSymbol TypeSymbol::Double = TypeSymbol(TEXT("double"));
const TypeSymbol TypeSymbol::Error = TypeSymbol(TEXT("error"));
1 change: 1 addition & 0 deletions src/Mamba/Code Analysis/Symbol/TypeSymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace Mamba
static const TypeSymbol String;
static const TypeSymbol Void;
static const TypeSymbol Double;
static const TypeSymbol Error;

static bool IsBuiltInType(const TypeSymbol* Type) noexcept;
};
Expand Down
6 changes: 6 additions & 0 deletions src/Mamba/Code Analysis/Syntax/Constant.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ namespace Mamba
return std::get<T>(Value);
}

template<typename T>
[[nodiscard]] constexpr bool HoldsAlternative() const noexcept
{
return std::holds_alternative<T>(Value);
}

[[nodiscard]] constexpr ValueType& GetValue() noexcept
{
return Value;
Expand Down
2 changes: 1 addition & 1 deletion src/Mamba/Code Analysis/Syntax/ElseClauseSyntax.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using namespace Mamba;
ElseClauseSyntax::ElseClauseSyntax(
const class SyntaxTree* SyntaxTree,
const SyntaxToken* ElseKeyword,
const StatementSyntax* ElseStatement
NullablePointer<const StatementSyntax> ElseStatement
) noexcept :
Super(SyntaxTree), ElseKeyword(ElseKeyword), ElseStatement(ElseStatement)
{
Expand Down
Loading

0 comments on commit daa83e6

Please sign in to comment.