Re-introduce let declarations

Closes #42
This commit is contained in:
Sam Vervaeck 2023-06-03 14:35:02 +02:00
parent 73559460ec
commit f63d892662
Signed by: samvv
SSH key fingerprint: SHA256:dIg0ywU1OP+ZYifrYxy8c5esO72cIKB+4/9wkZj1VaY
10 changed files with 173 additions and 309 deletions

View file

@ -104,9 +104,9 @@ namespace bolt {
RArrow,
RArrowAlt,
LetKeyword,
FnKeyword,
MutKeyword,
PubKeyword,
ForeignKeyword,
TypeKeyword,
ReturnKeyword,
ModKeyword,
@ -164,8 +164,7 @@ namespace bolt {
Parameter,
LetBlockBody,
LetExprBody,
FunctionDeclaration,
VariableDeclaration,
LetDeclaration,
RecordDeclarationField,
RecordDeclaration,
VariantDeclaration,
@ -549,20 +548,6 @@ namespace bolt {
};
class FnKeyword : public Token {
public:
inline FnKeyword(TextLoc StartLoc):
Token(NodeKind::FnKeyword, StartLoc) {}
std::string getText() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::FnKeyword;
}
};
class MutKeyword : public Token {
public:
@ -591,6 +576,20 @@ namespace bolt {
};
class ForeignKeyword : public Token {
public:
inline ForeignKeyword(TextLoc StartLoc):
Token(NodeKind::ForeignKeyword, StartLoc) {}
std::string getText() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::ForeignKeyword;
}
};
class TypeKeyword : public Token {
public:
@ -1718,7 +1717,7 @@ namespace bolt {
};
class FunctionDeclaration : public Node {
class LetDeclaration : public TypedNode {
Scope* TheScope = nullptr;
@ -1726,26 +1725,31 @@ namespace bolt {
bool IsCycleActive = false;
InferContext* Ctx;
class Type* Ty;
class PubKeyword* PubKeyword;
class FnKeyword* FnKeyword;
class Identifier* Name;
class ForeignKeyword* ForeignKeyword;
class LetKeyword* LetKeyword;
class MutKeyword* MutKeyword;
class Pattern* Pattern;
std::vector<Parameter*> Params;
class TypeAssert* TypeAssert;
LetBody* Body;
FunctionDeclaration(
LetDeclaration(
class PubKeyword* PubKeyword,
class FnKeyword* FnKeyword,
class Identifier* Name,
class ForeignKeyword* ForeignKeyword,
class LetKeyword* LetKeyword,
class MutKeyword* MutKeyword,
class Pattern* Pattern,
std::vector<Parameter*> Params,
class TypeAssert* TypeAssert,
LetBody* Body
): Node(NodeKind::FunctionDeclaration),
): TypedNode(NodeKind::LetDeclaration),
PubKeyword(PubKeyword),
FnKeyword(FnKeyword),
Name(Name),
ForeignKeyword(ForeignKeyword),
LetKeyword(LetKeyword),
MutKeyword(MutKeyword),
Pattern(Pattern),
Params(Params),
TypeAssert(TypeAssert),
Body(Body) {}
@ -1766,54 +1770,36 @@ namespace bolt {
}
bool isSignature() const noexcept {
return !Body;
return ForeignKeyword;
}
bool isVariable() const noexcept {
// Variables in classes and instances are never possible, so we reflect this by excluding them here.
return !isSignature() && !isClass() && !isInstance() && (Pattern->getKind() != NodeKind::BindPattern || !Body);
}
bool isFunction() const noexcept {
return !isSignature() && !isVariable();
}
Identifier* getName() const noexcept {
ZEN_ASSERT(Pattern->getKind() == NodeKind::BindPattern);
return static_cast<BindPattern*>(Pattern)->Name;
}
ByteString getNameAsString() const noexcept {
return getName()->getCanonicalText();
}
Token* getFirstToken() const override;
Token* getLastToken() const override;
static bool classof(const Node* N) {
return N->getKind() == NodeKind::FunctionDeclaration;
return N->getKind() == NodeKind::LetDeclaration;
}
};
class VariableDeclaration : public TypedNode {
Scope* TheScope = nullptr;
public:
bool IsCycleActive = false;
class PubKeyword* PubKeyword;
class LetKeyword* LetKeyword;
class MutKeyword* MutKeyword;
class Pattern* Pattern;
std::vector<Parameter*> Params;
class TypeAssert* TypeAssert;
LetBody* Body;
VariableDeclaration(
class PubKeyword* PubKeyword,
class LetKeyword* LetKeyword,
class MutKeyword* MutKeyword,
class Pattern* Pattern,
class TypeAssert* TypeAssert,
LetBody* Body
): TypedNode(NodeKind::VariableDeclaration),
PubKeyword(PubKeyword),
LetKeyword(LetKeyword),
MutKeyword(MutKeyword),
Pattern(Pattern),
TypeAssert(TypeAssert),
Body(Body) {}
Token* getFirstToken() const override;
Token* getLastToken() const override;
};
class InstanceDeclaration : public Node {
public:
@ -2063,7 +2049,7 @@ namespace bolt {
template<> inline NodeKind getNodeType<RArrow>() { return NodeKind::RArrow; }
template<> inline NodeKind getNodeType<RArrowAlt>() { return NodeKind::RArrowAlt; }
template<> inline NodeKind getNodeType<LetKeyword>() { return NodeKind::LetKeyword; }
template<> inline NodeKind getNodeType<FnKeyword>() { return NodeKind::FnKeyword; }
template<> inline NodeKind getNodeType<ForeignKeyword>() { return NodeKind::ForeignKeyword; }
template<> inline NodeKind getNodeType<MutKeyword>() { return NodeKind::MutKeyword; }
template<> inline NodeKind getNodeType<PubKeyword>() { return NodeKind::PubKeyword; }
template<> inline NodeKind getNodeType<TypeKeyword>() { return NodeKind::TypeKeyword; }
@ -2106,8 +2092,7 @@ namespace bolt {
template<> inline NodeKind getNodeType<Parameter>() { return NodeKind::Parameter; }
template<> inline NodeKind getNodeType<LetBlockBody>() { return NodeKind::LetBlockBody; }
template<> inline NodeKind getNodeType<LetExprBody>() { return NodeKind::LetExprBody; }
template<> inline NodeKind getNodeType<FunctionDeclaration>() { return NodeKind::FunctionDeclaration; }
template<> inline NodeKind getNodeType<VariableDeclaration>() { return NodeKind::VariableDeclaration; }
template<> inline NodeKind getNodeType<LetDeclaration>() { return NodeKind::LetDeclaration; }
template<> inline NodeKind getNodeType<RecordDeclarationField>() { return NodeKind::RecordDeclarationField; }
template<> inline NodeKind getNodeType<RecordDeclaration>() { return NodeKind::RecordDeclaration; }
template<> inline NodeKind getNodeType<ClassDeclaration>() { return NodeKind::ClassDeclaration; }

View file

@ -33,7 +33,7 @@ namespace bolt {
BOLT_GEN_CASE(RArrow)
BOLT_GEN_CASE(RArrowAlt)
BOLT_GEN_CASE(LetKeyword)
BOLT_GEN_CASE(FnKeyword)
BOLT_GEN_CASE(ForeignKeyword)
BOLT_GEN_CASE(MutKeyword)
BOLT_GEN_CASE(PubKeyword)
BOLT_GEN_CASE(TypeKeyword)
@ -93,8 +93,7 @@ namespace bolt {
BOLT_GEN_CASE(Parameter)
BOLT_GEN_CASE(LetBlockBody)
BOLT_GEN_CASE(LetExprBody)
BOLT_GEN_CASE(FunctionDeclaration)
BOLT_GEN_CASE(VariableDeclaration)
BOLT_GEN_CASE(LetDeclaration)
BOLT_GEN_CASE(RecordDeclaration)
BOLT_GEN_CASE(RecordDeclarationField)
BOLT_GEN_CASE(VariantDeclaration)
@ -176,7 +175,7 @@ namespace bolt {
visitToken(N);
}
void visitFnKeyword(FnKeyword* N) {
void visitForeignKeyword(ForeignKeyword* N) {
visitToken(N);
}
@ -440,11 +439,7 @@ namespace bolt {
visitLetBody(N);
}
void visitFunctionDeclaration(FunctionDeclaration* N) {
visitNode(N);
}
void visitVariableDeclaration(VariableDeclaration* N) {
void visitLetDeclaration(LetDeclaration* N) {
visitNode(N);
}
@ -509,7 +504,7 @@ namespace bolt {
BOLT_GEN_CHILD_CASE(RArrow)
BOLT_GEN_CHILD_CASE(RArrowAlt)
BOLT_GEN_CHILD_CASE(LetKeyword)
BOLT_GEN_CHILD_CASE(FnKeyword)
BOLT_GEN_CHILD_CASE(ForeignKeyword)
BOLT_GEN_CHILD_CASE(MutKeyword)
BOLT_GEN_CHILD_CASE(PubKeyword)
BOLT_GEN_CHILD_CASE(TypeKeyword)
@ -569,8 +564,7 @@ namespace bolt {
BOLT_GEN_CHILD_CASE(Parameter)
BOLT_GEN_CHILD_CASE(LetBlockBody)
BOLT_GEN_CHILD_CASE(LetExprBody)
BOLT_GEN_CHILD_CASE(FunctionDeclaration)
BOLT_GEN_CHILD_CASE(VariableDeclaration)
BOLT_GEN_CHILD_CASE(LetDeclaration)
BOLT_GEN_CHILD_CASE(RecordDeclaration)
BOLT_GEN_CHILD_CASE(RecordDeclarationField)
BOLT_GEN_CHILD_CASE(VariantDeclaration)
@ -629,7 +623,7 @@ namespace bolt {
void visitEachChild(LetKeyword* N) {
}
void visitEachChild(FnKeyword* N) {
void visitEachChild(ForeignKeyword* N) {
}
void visitEachChild(MutKeyword* N) {
@ -951,29 +945,18 @@ namespace bolt {
BOLT_VISIT(N->Expression);
}
void visitEachChild(FunctionDeclaration* N) {
void visitEachChild(LetDeclaration* N) {
if (N->PubKeyword) {
BOLT_VISIT(N->PubKeyword);
}
BOLT_VISIT(N->FnKeyword);
BOLT_VISIT(N->Name);
for (auto Param: N->Params) {
BOLT_VISIT(Param);
}
if (N->TypeAssert) {
BOLT_VISIT(N->TypeAssert);
}
if (N->Body) {
BOLT_VISIT(N->Body);
}
}
void visitEachChild(VariableDeclaration* N) {
if (N->PubKeyword) {
BOLT_VISIT(N->PubKeyword);
if (N->ForeignKeyword) {
BOLT_VISIT(N->ForeignKeyword);
}
BOLT_VISIT(N->LetKeyword);
BOLT_VISIT(N->Pattern);
for (auto Param: N->Params) {
BOLT_VISIT(Param);
}
if (N->TypeAssert) {
BOLT_VISIT(N->TypeAssert);
}

View file

@ -192,7 +192,7 @@ namespace bolt {
/// Type inference
void forwardDeclare(Node* Node);
void forwardDeclareFunctionDeclaration(FunctionDeclaration* N, TVSet* TVs, ConstraintSet* Constraints);
void forwardDeclareFunctionDeclaration(LetDeclaration* N, TVSet* TVs, ConstraintSet* Constraints);
Type* inferExpression(Expression* Expression);
Type* inferTypeExpression(TypeExpression* TE, bool IsPoly = true);
@ -200,7 +200,7 @@ namespace bolt {
Type* inferPattern(Pattern* Pattern, ConstraintSet* Constraints = new ConstraintSet, TVSet* TVs = new TVSet);
void infer(Node* node);
void inferFunctionDeclaration(FunctionDeclaration* N);
void inferFunctionDeclaration(LetDeclaration* N);
void inferConstraintExpression(ConstraintExpression* C);
/// Factory methods

View file

@ -126,9 +126,7 @@ namespace bolt {
Node* parseLetBodyElement();
FunctionDeclaration* parseFunctionDeclaration();
VariableDeclaration* parseVariableDeclaration();
LetDeclaration* parseLetDeclaration();
Node* parseClassElement();

View file

@ -321,7 +321,6 @@ namespace bolt {
return Curr;
}
static bool classof(const Type* Ty) {
return Ty->getKind() == TypeKind::Arrow;
}

View file

@ -78,9 +78,10 @@ namespace bolt {
}
break;
}
case NodeKind::FunctionDeclaration:
case NodeKind::LetDeclaration:
{
auto Decl = static_cast<FunctionDeclaration*>(X);
auto Decl = static_cast<LetDeclaration*>(X);
ZEN_ASSERT(Decl->isFunction());
for (auto Param: Decl->Params) {
visitPattern(Param->Pattern, Param);
}
@ -121,18 +122,14 @@ namespace bolt {
}
break;
}
case NodeKind::VariableDeclaration:
case NodeKind::LetDeclaration:
{
auto Decl = static_cast<VariableDeclaration*>(X);
auto Decl = static_cast<LetDeclaration*>(X);
// No matter if it is a function or a variable, by visiting the pattern
// we add all relevant bindings to the current scope.
visitPattern(Decl->Pattern, Decl);
break;
}
case NodeKind::FunctionDeclaration:
{
auto Decl = static_cast<FunctionDeclaration*>(X);
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Var);
break;
}
case NodeKind::RecordDeclaration:
{
auto Decl = static_cast<RecordDeclaration*>(X);
@ -651,14 +648,17 @@ namespace bolt {
return Expression->getLastToken();
}
Token* FunctionDeclaration::getFirstToken() const {
Token* LetDeclaration::getFirstToken() const {
if (PubKeyword) {
return PubKeyword;
}
return FnKeyword;
if (ForeignKeyword) {
return ForeignKeyword;
}
return LetKeyword;
}
Token* FunctionDeclaration::getLastToken() const {
Token* LetDeclaration::getLastToken() const {
if (Body) {
return Body->getLastToken();
}
@ -668,23 +668,6 @@ namespace bolt {
if (Params.size()) {
return Params.back()->getLastToken();
}
return Name;
}
Token* VariableDeclaration::getFirstToken() const {
if (PubKeyword) {
return PubKeyword;
}
return LetKeyword;
}
Token* VariableDeclaration::getLastToken() const {
if (Body) {
return Body->getLastToken();
}
if (TypeAssert) {
return TypeAssert->getLastToken();
}
return Pattern->getLastToken();
}
@ -837,8 +820,8 @@ namespace bolt {
return "let";
}
std::string FnKeyword::getText() const {
return "fn";
std::string ForeignKeyword::getText() const {
return "foreign";
}
std::string MutKeyword::getText() const {

View file

@ -274,13 +274,22 @@ namespace bolt {
break;
}
case NodeKind::FunctionDeclaration:
// These declarations will be handled separately in check()
break;
case NodeKind::VariableDeclaration:
// All of this node's semantics will be handled in infer()
case NodeKind::LetDeclaration:
{
// Function declarations are handled separately in forwardDeclareLetDeclaration()
auto Decl = static_cast<LetDeclaration*>(X);
if (!Decl->isVariable()) {
break;
}
Type* Ty;
if (Decl->TypeAssert) {
Ty = inferTypeExpression(Decl->TypeAssert->TypeExpression, false);
} else {
Ty = createTypeVar();
}
Decl->setType(Ty);
break;
}
case NodeKind::VariantDeclaration:
{
@ -405,11 +414,13 @@ namespace bolt {
Contexts.pop();
}
void visitFunctionDeclaration(FunctionDeclaration* Let) {
Let->Ctx = createDerivedContext();
Contexts.push(Let->Ctx);
visitEachChild(Let);
Contexts.pop();
void visitLetDeclaration(LetDeclaration* Let) {
if (Let->isFunction()) {
Let->Ctx = createDerivedContext();
Contexts.push(Let->Ctx);
visitEachChild(Let);
Contexts.pop();
}
}
// void visitVariableDeclaration(VariableDeclaration* Var) {
@ -424,7 +435,11 @@ namespace bolt {
}
void Checker::forwardDeclareFunctionDeclaration(FunctionDeclaration* Let, TVSet* TVs, ConstraintSet* Constraints) {
void Checker::forwardDeclareFunctionDeclaration(LetDeclaration* Let, TVSet* TVs, ConstraintSet* Constraints) {
if (!Let->isFunction()) {
return;
}
setContext(Let->Ctx);
@ -460,7 +475,7 @@ namespace bolt {
} else {
Ty = createTypeVar();
}
Let->Ty = Ty;
Let->setType(Ty);
// If declaring a let-declaration inside a type instance declaration,
// we need to perform some work to make sure the type asserts of the
@ -470,7 +485,7 @@ namespace bolt {
auto Instance = static_cast<InstanceDeclaration*>(Let->Parent);
auto Class = llvm::cast<ClassDeclaration>(Instance->getScope()->lookup({ {}, Instance->Name->getCanonicalText() }, SymbolKind::Class));
auto SigLet = llvm::cast<FunctionDeclaration>(Class->getScope()->lookupDirect({ {}, Let->Name->getCanonicalText() }, SymbolKind::Var));
auto SigLet = llvm::cast<LetDeclaration>(Class->getScope()->lookupDirect({ {}, Let->getNameAsString() }, SymbolKind::Var));
auto Params = addClassVars(Class, false);
@ -526,14 +541,14 @@ namespace bolt {
}
if (!Let->isInstance()) {
Let->Ctx->Parent->Env.emplace(Let->Name->getCanonicalText(), new Forall(Let->Ctx->TVs, Let->Ctx->Constraints, Ty));
Let->Ctx->Parent->Env.emplace(Let->getNameAsString(), new Forall(Let->Ctx->TVs, Let->Ctx->Constraints, Ty));
}
}
void Checker::inferFunctionDeclaration(FunctionDeclaration* Decl) {
void Checker::inferFunctionDeclaration(LetDeclaration* Decl) {
if (Decl->isSignature()) {
if (!Decl->isFunction()) {
return;
}
@ -570,7 +585,7 @@ namespace bolt {
RetType = createTypeVar();
}
makeEqual(Decl->Ty, TArrow::build(ParamTypes, RetType), Decl);
makeEqual(Decl->getType(), TArrow::build(ParamTypes, RetType), Decl);
}
@ -624,9 +639,6 @@ namespace bolt {
break;
}
case NodeKind::FunctionDeclaration:
break;
case NodeKind::ReturnStatement:
{
auto RetStmt = static_cast<ReturnStatement*>(N);
@ -640,30 +652,22 @@ namespace bolt {
break;
}
case NodeKind::VariableDeclaration:
case NodeKind::LetDeclaration:
{
auto Decl = static_cast<VariableDeclaration*>(N);
Type* Ty = nullptr;
if (Decl->TypeAssert) {
Ty = inferTypeExpression(Decl->TypeAssert->TypeExpression, false);
// Function declarations are handled separately in inferLetDeclaration()
auto Decl = static_cast<LetDeclaration*>(N);
if (!Decl->isVariable()) {
break;
}
auto Ty = Decl->getType();
if (Decl->Body) {
ZEN_ASSERT(Decl->Body->getKind() == NodeKind::LetExprBody);
auto E = static_cast<LetExprBody*>(Decl->Body);
auto Ty2 = inferExpression(E->Expression);
if (Ty) {
makeEqual(Ty, Ty2, Decl);
} else {
Ty = Ty2;
}
makeEqual(Ty, Ty2, Decl);
}
auto Ty3 = inferPattern(Decl->Pattern);
if (Ty) {
makeEqual(Ty, Ty3, Decl);
} else {
Ty = Ty3;
}
Decl->setType(Ty);
makeEqual(Ty, Ty3, Decl);
break;
}
@ -759,7 +763,9 @@ namespace bolt {
auto D = static_cast<TypeclassConstraintExpression*>(C);
std::vector<Type*> Types;
for (auto TE: D->TEs) {
auto TV = static_cast<TVarRigid*>(inferTypeExpression(TE));
auto Ty = inferTypeExpression(TE);
ZEN_ASSERT(Ty->getKind() == TypeKind::Var && static_cast<TVar*>(Ty)->isRigid());
auto TV = static_cast<TVarRigid*>(Ty);
TV->Provided.emplace(D->Name->getCanonicalText());
Types.push_back(TV);
}
@ -938,10 +944,10 @@ namespace bolt {
auto Ref = static_cast<ReferenceExpression*>(X);
ZEN_ASSERT(Ref->ModulePath.empty());
auto Target = Ref->getScope()->lookup(Ref->getSymbolPath());
if (Target && llvm::isa<FunctionDeclaration>(Target)) {
auto Let = static_cast<FunctionDeclaration*>(Target);
if (Target && llvm::isa<LetDeclaration>(Target)) {
auto Let = static_cast<LetDeclaration*>(Target);
if (Let->IsCycleActive) {
return Let->Ty;
return Let->getType();
}
}
auto Scm = lookup(Ref->Name->getCanonicalText());
@ -1133,7 +1139,7 @@ namespace bolt {
std::stack<Node*> Stack;
void visitFunctionDeclaration(FunctionDeclaration* N) {
void visitLetDeclaration(LetDeclaration* N) {
RefGraph.addVertex(N);
Stack.push(N);
visitEachChild(N);
@ -1154,7 +1160,7 @@ namespace bolt {
RefGraph.addEdge(Stack.top(), Def->Parent);
return;
}
ZEN_ASSERT(Def->getKind() == NodeKind::FunctionDeclaration || Def->getKind() == NodeKind::VariableDeclaration);
ZEN_ASSERT(Def->getKind() == NodeKind::LetDeclaration);
if (!Stack.empty()) {
RefGraph.addEdge(Def, Stack.top());
}
@ -1193,33 +1199,33 @@ namespace bolt {
auto TVs = new TVSet;
auto Constraints = new ConstraintSet;
for (auto N: Nodes) {
if (N->getKind() != NodeKind::FunctionDeclaration) {
if (N->getKind() != NodeKind::LetDeclaration) {
continue;
}
auto Decl = static_cast<FunctionDeclaration*>(N);
auto Decl = static_cast<LetDeclaration*>(N);
forwardDeclareFunctionDeclaration(Decl, TVs, Constraints);
}
}
for (auto Nodes: SCCs) {
for (auto N: Nodes) {
if (N->getKind() != NodeKind::FunctionDeclaration) {
if (N->getKind() != NodeKind::LetDeclaration) {
continue;
}
auto Decl = static_cast<FunctionDeclaration*>(N);
auto Decl = static_cast<LetDeclaration*>(N);
Decl->IsCycleActive = true;
}
for (auto N: Nodes) {
if (N->getKind() != NodeKind::FunctionDeclaration) {
if (N->getKind() != NodeKind::LetDeclaration) {
continue;
}
auto Decl = static_cast<FunctionDeclaration*>(N);
auto Decl = static_cast<LetDeclaration*>(N);
inferFunctionDeclaration(Decl);
}
for (auto N: Nodes) {
if (N->getKind() != NodeKind::FunctionDeclaration) {
if (N->getKind() != NodeKind::LetDeclaration) {
continue;
}
auto Decl = static_cast<FunctionDeclaration*>(N);
auto Decl = static_cast<LetDeclaration*>(N);
Decl->IsCycleActive = false;
}
}

View file

@ -100,8 +100,8 @@ namespace bolt {
return "'pub'";
case NodeKind::LetKeyword:
return "'let'";
case NodeKind::FnKeyword:
return "'fn'";
case NodeKind::ForeignKeyword:
return "'foreign'";
case NodeKind::MutKeyword:
return "'mut'";
case NodeKind::MatchKeyword:
@ -112,10 +112,8 @@ namespace bolt {
return "'type'";
case NodeKind::ReferenceTypeExpression:
return "a type reference";
case NodeKind::FunctionDeclaration:
return "a function declaration";
case NodeKind::VariableDeclaration:
return "a variable declaration";
case NodeKind::LetDeclaration:
return "a let-declaration";
case NodeKind::CallExpression:
return "a call-expression";
case NodeKind::InfixExpression:

View file

@ -919,9 +919,10 @@ finish:
return new IfStatement(Parts);
}
VariableDeclaration* Parser::parseVariableDeclaration() {
LetDeclaration* Parser::parseLetDeclaration() {
PubKeyword* Pub = nullptr;
ForeignKeyword* Foreign = nullptr;
LetKeyword* Let;
MutKeyword* Mut = nullptr;
TypeAssert* TA = nullptr;
@ -932,26 +933,36 @@ VariableDeclaration* Parser::parseVariableDeclaration() {
Pub = static_cast<PubKeyword*>(T0);
T0 = Tokens.get();
}
if (T0->getKind() == NodeKind::ForeignKeyword) {
Foreign = static_cast<ForeignKeyword*>(T0);
T0 = Tokens.get();
}
if (T0->getKind() != NodeKind::LetKeyword) {
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LetKeyword });
if (Pub) {
Pub->unref();
}
if (Foreign) {
Foreign->unref();
}
skipToLineFoldEnd();
return nullptr;
}
Let = static_cast<LetKeyword*>(T0);
auto T1 = Tokens.peek();
if (T1->getKind() == NodeKind::MutKeyword) {
Mut = static_cast<MutKeyword*>(T1);
Tokens.get();
Mut = static_cast<MutKeyword*>(T1);
}
auto P = parseWidePattern();
if (!P) {
auto Pattern = parseNarrowPattern();
if (!Pattern) {
if (Pub) {
Pub->unref();
}
if (Foreign) {
Foreign->unref();
}
Let->unref();
if (Mut) {
Mut->unref();
@ -960,103 +971,6 @@ VariableDeclaration* Parser::parseVariableDeclaration() {
return nullptr;
}
auto T2 = Tokens.peek();
if (T2->getKind() == NodeKind::Colon) {
Tokens.get();
auto TE = parseTypeExpression();
if (TE) {
TA = new TypeAssert(static_cast<Colon*>(T2), TE);
} else {
skipToLineFoldEnd();
goto finish;
}
T2 = Tokens.peek();
}
switch (T2->getKind()) {
case NodeKind::BlockStart:
{
Tokens.get();
std::vector<Node*> Elements;
for (;;) {
auto T3 = Tokens.peek();
if (T3->getKind() == NodeKind::BlockEnd) {
break;
}
auto Element = parseLetBodyElement();
if (Element) {
Elements.push_back(Element);
}
}
Tokens.get()->unref(); // Always a BlockEnd
Body = new LetBlockBody(static_cast<BlockStart*>(T2), Elements);
break;
}
case NodeKind::Equals:
{
Tokens.get();
auto E = parseExpression();
if (E == nullptr) {
skipToLineFoldEnd();
goto finish;
}
if (E) {
Body = new LetExprBody(static_cast<Equals*>(T2), E);
}
break;
}
case NodeKind::LineFoldEnd:
break;
default:
std::vector<NodeKind> Expected { NodeKind::BlockStart, NodeKind::LineFoldEnd, NodeKind::Equals };
if (TA == nullptr) {
// First tokens of TypeAssert
Expected.push_back(NodeKind::Colon);
// First tokens of Pattern
Expected.push_back(NodeKind::Identifier);
}
DE.add<UnexpectedTokenDiagnostic>(File, T2, Expected);
}
checkLineFoldEnd();
finish:
return new VariableDeclaration { Pub, Let, Mut, P, TA, Body };
}
FunctionDeclaration* Parser::parseFunctionDeclaration() {
PubKeyword* Pub = nullptr;
FnKeyword* Fn;
TypeAssert* TA = nullptr;
LetBody* Body = nullptr;
auto T0 = Tokens.get();
if (T0->getKind() == NodeKind::PubKeyword) {
Pub = static_cast<PubKeyword*>(T0);
T0 = Tokens.get();
}
if (T0->getKind() != NodeKind::FnKeyword) {
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::FnKeyword });
if (Pub) {
Pub->unref();
}
skipToLineFoldEnd();
return nullptr;
}
Fn = static_cast<FnKeyword*>(T0);
auto Name = expectToken<Identifier>();
if (!Name) {
if (Pub) {
Pub->unref();
}
Fn->unref();
skipToLineFoldEnd();
return nullptr;
}
std::vector<Parameter*> Params;
Token* T2;
for (;;) {
@ -1138,10 +1052,12 @@ after_params:
finish:
return new FunctionDeclaration(
return new LetDeclaration(
Pub,
Fn,
Name,
Foreign,
Let,
Mut,
Pattern,
Params,
TA,
Body
@ -1152,9 +1068,7 @@ finish:
auto T0 = peekFirstTokenAfterModifiers();
switch (T0->getKind()) {
case NodeKind::LetKeyword:
return parseVariableDeclaration();
case NodeKind::FnKeyword:
return parseFunctionDeclaration();
return parseLetDeclaration();
case NodeKind::ReturnKeyword:
return parseReturnStatement();
case NodeKind::IfKeyword:
@ -1558,12 +1472,12 @@ next_member:
Node* Parser::parseClassElement() {
auto T0 = Tokens.peek();
switch (T0->getKind()) {
case NodeKind::FnKeyword:
return parseFunctionDeclaration();
case NodeKind::LetKeyword:
return parseLetDeclaration();
case NodeKind::TypeKeyword:
// TODO
default:
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector<NodeKind> { NodeKind::FnKeyword, NodeKind::TypeKeyword });
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector<NodeKind> { NodeKind::LetKeyword, NodeKind::TypeKeyword });
skipToLineFoldEnd();
return nullptr;
}
@ -1573,9 +1487,7 @@ next_member:
auto T0 = peekFirstTokenAfterModifiers();
switch (T0->getKind()) {
case NodeKind::LetKeyword:
return parseVariableDeclaration();
case NodeKind::FnKeyword:
return parseFunctionDeclaration();
return parseLetDeclaration();
case NodeKind::IfKeyword:
return parseIfStatement();
case NodeKind::ClassKeyword:

View file

@ -62,7 +62,7 @@ namespace bolt {
std::unordered_map<ByteString, NodeKind> Keywords = {
{ "pub", NodeKind::PubKeyword },
{ "let", NodeKind::LetKeyword },
{ "fn", NodeKind::FnKeyword },
{ "foreign", NodeKind::ForeignKeyword },
{ "mut", NodeKind::MutKeyword },
{ "return", NodeKind::ReturnKeyword },
{ "type", NodeKind::TypeKeyword },
@ -227,8 +227,8 @@ digit_finish:
return new PubKeyword(StartLoc);
case NodeKind::LetKeyword:
return new LetKeyword(StartLoc);
case NodeKind::FnKeyword:
return new FnKeyword(StartLoc);
case NodeKind::ForeignKeyword:
return new ForeignKeyword(StartLoc);
case NodeKind::MutKeyword:
return new MutKeyword(StartLoc);
case NodeKind::TypeKeyword: