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, RArrow,
RArrowAlt, RArrowAlt,
LetKeyword, LetKeyword,
FnKeyword,
MutKeyword, MutKeyword,
PubKeyword, PubKeyword,
ForeignKeyword,
TypeKeyword, TypeKeyword,
ReturnKeyword, ReturnKeyword,
ModKeyword, ModKeyword,
@ -164,8 +164,7 @@ namespace bolt {
Parameter, Parameter,
LetBlockBody, LetBlockBody,
LetExprBody, LetExprBody,
FunctionDeclaration, LetDeclaration,
VariableDeclaration,
RecordDeclarationField, RecordDeclarationField,
RecordDeclaration, RecordDeclaration,
VariantDeclaration, 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 { class MutKeyword : public Token {
public: 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 { class TypeKeyword : public Token {
public: public:
@ -1718,7 +1717,7 @@ namespace bolt {
}; };
class FunctionDeclaration : public Node { class LetDeclaration : public TypedNode {
Scope* TheScope = nullptr; Scope* TheScope = nullptr;
@ -1726,26 +1725,31 @@ namespace bolt {
bool IsCycleActive = false; bool IsCycleActive = false;
InferContext* Ctx; InferContext* Ctx;
class Type* Ty;
class PubKeyword* PubKeyword; class PubKeyword* PubKeyword;
class FnKeyword* FnKeyword; class ForeignKeyword* ForeignKeyword;
class Identifier* Name; class LetKeyword* LetKeyword;
class MutKeyword* MutKeyword;
class Pattern* Pattern;
std::vector<Parameter*> Params; std::vector<Parameter*> Params;
class TypeAssert* TypeAssert; class TypeAssert* TypeAssert;
LetBody* Body; LetBody* Body;
FunctionDeclaration( LetDeclaration(
class PubKeyword* PubKeyword, class PubKeyword* PubKeyword,
class FnKeyword* FnKeyword, class ForeignKeyword* ForeignKeyword,
class Identifier* Name, class LetKeyword* LetKeyword,
class MutKeyword* MutKeyword,
class Pattern* Pattern,
std::vector<Parameter*> Params, std::vector<Parameter*> Params,
class TypeAssert* TypeAssert, class TypeAssert* TypeAssert,
LetBody* Body LetBody* Body
): Node(NodeKind::FunctionDeclaration), ): TypedNode(NodeKind::LetDeclaration),
PubKeyword(PubKeyword), PubKeyword(PubKeyword),
FnKeyword(FnKeyword), ForeignKeyword(ForeignKeyword),
Name(Name), LetKeyword(LetKeyword),
MutKeyword(MutKeyword),
Pattern(Pattern),
Params(Params), Params(Params),
TypeAssert(TypeAssert), TypeAssert(TypeAssert),
Body(Body) {} Body(Body) {}
@ -1766,54 +1770,36 @@ namespace bolt {
} }
bool isSignature() const noexcept { 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* getFirstToken() const override;
Token* getLastToken() const override; Token* getLastToken() const override;
static bool classof(const Node* N) { 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 { class InstanceDeclaration : public Node {
public: public:
@ -2063,7 +2049,7 @@ namespace bolt {
template<> inline NodeKind getNodeType<RArrow>() { return NodeKind::RArrow; } template<> inline NodeKind getNodeType<RArrow>() { return NodeKind::RArrow; }
template<> inline NodeKind getNodeType<RArrowAlt>() { return NodeKind::RArrowAlt; } template<> inline NodeKind getNodeType<RArrowAlt>() { return NodeKind::RArrowAlt; }
template<> inline NodeKind getNodeType<LetKeyword>() { return NodeKind::LetKeyword; } 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<MutKeyword>() { return NodeKind::MutKeyword; }
template<> inline NodeKind getNodeType<PubKeyword>() { return NodeKind::PubKeyword; } template<> inline NodeKind getNodeType<PubKeyword>() { return NodeKind::PubKeyword; }
template<> inline NodeKind getNodeType<TypeKeyword>() { return NodeKind::TypeKeyword; } 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<Parameter>() { return NodeKind::Parameter; }
template<> inline NodeKind getNodeType<LetBlockBody>() { return NodeKind::LetBlockBody; } template<> inline NodeKind getNodeType<LetBlockBody>() { return NodeKind::LetBlockBody; }
template<> inline NodeKind getNodeType<LetExprBody>() { return NodeKind::LetExprBody; } template<> inline NodeKind getNodeType<LetExprBody>() { return NodeKind::LetExprBody; }
template<> inline NodeKind getNodeType<FunctionDeclaration>() { return NodeKind::FunctionDeclaration; } template<> inline NodeKind getNodeType<LetDeclaration>() { return NodeKind::LetDeclaration; }
template<> inline NodeKind getNodeType<VariableDeclaration>() { return NodeKind::VariableDeclaration; }
template<> inline NodeKind getNodeType<RecordDeclarationField>() { return NodeKind::RecordDeclarationField; } template<> inline NodeKind getNodeType<RecordDeclarationField>() { return NodeKind::RecordDeclarationField; }
template<> inline NodeKind getNodeType<RecordDeclaration>() { return NodeKind::RecordDeclaration; } template<> inline NodeKind getNodeType<RecordDeclaration>() { return NodeKind::RecordDeclaration; }
template<> inline NodeKind getNodeType<ClassDeclaration>() { return NodeKind::ClassDeclaration; } template<> inline NodeKind getNodeType<ClassDeclaration>() { return NodeKind::ClassDeclaration; }

View file

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

View file

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

View file

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

View file

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

View file

@ -78,9 +78,10 @@ namespace bolt {
} }
break; 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) { for (auto Param: Decl->Params) {
visitPattern(Param->Pattern, Param); visitPattern(Param->Pattern, Param);
} }
@ -121,18 +122,14 @@ namespace bolt {
} }
break; 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); visitPattern(Decl->Pattern, Decl);
break; break;
} }
case NodeKind::FunctionDeclaration:
{
auto Decl = static_cast<FunctionDeclaration*>(X);
addSymbol(Decl->Name->getCanonicalText(), Decl, SymbolKind::Var);
break;
}
case NodeKind::RecordDeclaration: case NodeKind::RecordDeclaration:
{ {
auto Decl = static_cast<RecordDeclaration*>(X); auto Decl = static_cast<RecordDeclaration*>(X);
@ -651,14 +648,17 @@ namespace bolt {
return Expression->getLastToken(); return Expression->getLastToken();
} }
Token* FunctionDeclaration::getFirstToken() const { Token* LetDeclaration::getFirstToken() const {
if (PubKeyword) { if (PubKeyword) {
return PubKeyword; return PubKeyword;
} }
return FnKeyword; if (ForeignKeyword) {
return ForeignKeyword;
}
return LetKeyword;
} }
Token* FunctionDeclaration::getLastToken() const { Token* LetDeclaration::getLastToken() const {
if (Body) { if (Body) {
return Body->getLastToken(); return Body->getLastToken();
} }
@ -668,23 +668,6 @@ namespace bolt {
if (Params.size()) { if (Params.size()) {
return Params.back()->getLastToken(); 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(); return Pattern->getLastToken();
} }
@ -837,8 +820,8 @@ namespace bolt {
return "let"; return "let";
} }
std::string FnKeyword::getText() const { std::string ForeignKeyword::getText() const {
return "fn"; return "foreign";
} }
std::string MutKeyword::getText() const { std::string MutKeyword::getText() const {

View file

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

View file

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

View file

@ -919,9 +919,10 @@ finish:
return new IfStatement(Parts); return new IfStatement(Parts);
} }
VariableDeclaration* Parser::parseVariableDeclaration() { LetDeclaration* Parser::parseLetDeclaration() {
PubKeyword* Pub = nullptr; PubKeyword* Pub = nullptr;
ForeignKeyword* Foreign = nullptr;
LetKeyword* Let; LetKeyword* Let;
MutKeyword* Mut = nullptr; MutKeyword* Mut = nullptr;
TypeAssert* TA = nullptr; TypeAssert* TA = nullptr;
@ -932,26 +933,36 @@ VariableDeclaration* Parser::parseVariableDeclaration() {
Pub = static_cast<PubKeyword*>(T0); Pub = static_cast<PubKeyword*>(T0);
T0 = Tokens.get(); T0 = Tokens.get();
} }
if (T0->getKind() == NodeKind::ForeignKeyword) {
Foreign = static_cast<ForeignKeyword*>(T0);
T0 = Tokens.get();
}
if (T0->getKind() != NodeKind::LetKeyword) { if (T0->getKind() != NodeKind::LetKeyword) {
DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LetKeyword }); DE.add<UnexpectedTokenDiagnostic>(File, T0, std::vector { NodeKind::LetKeyword });
if (Pub) { if (Pub) {
Pub->unref(); Pub->unref();
} }
if (Foreign) {
Foreign->unref();
}
skipToLineFoldEnd(); skipToLineFoldEnd();
return nullptr; return nullptr;
} }
Let = static_cast<LetKeyword*>(T0); Let = static_cast<LetKeyword*>(T0);
auto T1 = Tokens.peek(); auto T1 = Tokens.peek();
if (T1->getKind() == NodeKind::MutKeyword) { if (T1->getKind() == NodeKind::MutKeyword) {
Mut = static_cast<MutKeyword*>(T1);
Tokens.get(); Tokens.get();
Mut = static_cast<MutKeyword*>(T1);
} }
auto P = parseWidePattern(); auto Pattern = parseNarrowPattern();
if (!P) { if (!Pattern) {
if (Pub) { if (Pub) {
Pub->unref(); Pub->unref();
} }
if (Foreign) {
Foreign->unref();
}
Let->unref(); Let->unref();
if (Mut) { if (Mut) {
Mut->unref(); Mut->unref();
@ -960,103 +971,6 @@ VariableDeclaration* Parser::parseVariableDeclaration() {
return nullptr; 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; std::vector<Parameter*> Params;
Token* T2; Token* T2;
for (;;) { for (;;) {
@ -1138,10 +1052,12 @@ after_params:
finish: finish:
return new FunctionDeclaration( return new LetDeclaration(
Pub, Pub,
Fn, Foreign,
Name, Let,
Mut,
Pattern,
Params, Params,
TA, TA,
Body Body
@ -1152,9 +1068,7 @@ finish:
auto T0 = peekFirstTokenAfterModifiers(); auto T0 = peekFirstTokenAfterModifiers();
switch (T0->getKind()) { switch (T0->getKind()) {
case NodeKind::LetKeyword: case NodeKind::LetKeyword:
return parseVariableDeclaration(); return parseLetDeclaration();
case NodeKind::FnKeyword:
return parseFunctionDeclaration();
case NodeKind::ReturnKeyword: case NodeKind::ReturnKeyword:
return parseReturnStatement(); return parseReturnStatement();
case NodeKind::IfKeyword: case NodeKind::IfKeyword:
@ -1558,12 +1472,12 @@ next_member:
Node* Parser::parseClassElement() { Node* Parser::parseClassElement() {
auto T0 = Tokens.peek(); auto T0 = Tokens.peek();
switch (T0->getKind()) { switch (T0->getKind()) {
case NodeKind::FnKeyword: case NodeKind::LetKeyword:
return parseFunctionDeclaration(); return parseLetDeclaration();
case NodeKind::TypeKeyword: case NodeKind::TypeKeyword:
// TODO // TODO
default: 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(); skipToLineFoldEnd();
return nullptr; return nullptr;
} }
@ -1573,9 +1487,7 @@ next_member:
auto T0 = peekFirstTokenAfterModifiers(); auto T0 = peekFirstTokenAfterModifiers();
switch (T0->getKind()) { switch (T0->getKind()) {
case NodeKind::LetKeyword: case NodeKind::LetKeyword:
return parseVariableDeclaration(); return parseLetDeclaration();
case NodeKind::FnKeyword:
return parseFunctionDeclaration();
case NodeKind::IfKeyword: case NodeKind::IfKeyword:
return parseIfStatement(); return parseIfStatement();
case NodeKind::ClassKeyword: case NodeKind::ClassKeyword:

View file

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