parent
73559460ec
commit
f63d892662
10 changed files with 173 additions and 309 deletions
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -126,9 +126,7 @@ namespace bolt {
|
|||
|
||||
Node* parseLetBodyElement();
|
||||
|
||||
FunctionDeclaration* parseFunctionDeclaration();
|
||||
|
||||
VariableDeclaration* parseVariableDeclaration();
|
||||
LetDeclaration* parseLetDeclaration();
|
||||
|
||||
Node* parseClassElement();
|
||||
|
||||
|
|
|
@ -321,7 +321,6 @@ namespace bolt {
|
|||
return Curr;
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const Type* Ty) {
|
||||
return Ty->getKind() == TypeKind::Arrow;
|
||||
}
|
||||
|
|
47
src/CST.cc
47
src/CST.cc
|
@ -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 {
|
||||
|
|
|
@ -274,13 +274,22 @@ namespace bolt {
|
|||
break;
|
||||
}
|
||||
|
||||
case NodeKind::FunctionDeclaration:
|
||||
// These declarations will be handled separately in check()
|
||||
case NodeKind::LetDeclaration:
|
||||
{
|
||||
// Function declarations are handled separately in forwardDeclareLetDeclaration()
|
||||
auto Decl = static_cast<LetDeclaration*>(X);
|
||||
if (!Decl->isVariable()) {
|
||||
break;
|
||||
|
||||
case NodeKind::VariableDeclaration:
|
||||
// All of this node's semantics will be handled in infer()
|
||||
}
|
||||
Type* Ty;
|
||||
if (Decl->TypeAssert) {
|
||||
Ty = inferTypeExpression(Decl->TypeAssert->TypeExpression, false);
|
||||
} else {
|
||||
Ty = createTypeVar();
|
||||
}
|
||||
Decl->setType(Ty);
|
||||
break;
|
||||
}
|
||||
|
||||
case NodeKind::VariantDeclaration:
|
||||
{
|
||||
|
@ -405,12 +414,14 @@ namespace bolt {
|
|||
Contexts.pop();
|
||||
}
|
||||
|
||||
void visitFunctionDeclaration(FunctionDeclaration* Let) {
|
||||
void visitLetDeclaration(LetDeclaration* Let) {
|
||||
if (Let->isFunction()) {
|
||||
Let->Ctx = createDerivedContext();
|
||||
Contexts.push(Let->Ctx);
|
||||
visitEachChild(Let);
|
||||
Contexts.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// void visitVariableDeclaration(VariableDeclaration* Var) {
|
||||
// Var->Ctx = Contexts.top();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
auto Ty3 = inferPattern(Decl->Pattern);
|
||||
if (Ty) {
|
||||
makeEqual(Ty, Ty3, Decl);
|
||||
} else {
|
||||
Ty = Ty3;
|
||||
}
|
||||
Decl->setType(Ty);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
138
src/Parser.cc
138
src/Parser.cc
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue