diff --git a/examples/funcDecl.dusk b/examples/funcDecl.dusk index 9c558bc77b71d4716ad9b0f3ba9ca051239b4041..b67f82850ebb23101c7c132d9664b1cd24522154 100644 --- a/examples/funcDecl.dusk +++ b/examples/funcDecl.dusk @@ -1,10 +1,15 @@ extern func test(); +extern func println(output: Int) -> Void; func main(arg1: Int) -> Int { - if arg1 % 2 != 0 { - return inc(arg1); + for i in 0..arg1 { + println(i); + if i > 5 { + break; + } + break; } - return arg1; + return 0; } func inc(i: Int) -> Int { diff --git a/include/dusk/AST/Stmt.h b/include/dusk/AST/Stmt.h index ac10dca241be6565efd8190d6dee28ce00b7c31b..ade30dc290f34b19a16ddeb4c3d9705717aa3c74 100644 --- a/include/dusk/AST/Stmt.h +++ b/include/dusk/AST/Stmt.h @@ -176,7 +176,7 @@ class ForStmt : public Stmt { SMLoc ForLoc; /// Iterabling variable - Expr *Var; + Decl *Iter; /// For-in range statement Stmt *Range; @@ -185,9 +185,9 @@ class ForStmt : public Stmt { Stmt *Body; public: - ForStmt(SMLoc FL, Expr *V, Stmt *R, Stmt *C); + ForStmt(SMLoc FL, Decl *V, Stmt *R, Stmt *C); - Expr *getVar() const { return Var; } + Decl *getIter() const { return Iter; } Stmt *getRange() const { return Range; } Stmt *getBody() const { return Body; } diff --git a/include/dusk/Parse/Token.h b/include/dusk/Parse/Token.h index 158308547e04dc24d2b092df411a8840cfc20a3c..bcea3580f4c104a64e36207cbf1a232908309c7f 100644 --- a/include/dusk/Parse/Token.h +++ b/include/dusk/Parse/Token.h @@ -84,8 +84,6 @@ public: bool isBinaryOperator() const { switch (Kind) { case tok::assign: - case tok::elipsis_excl: - case tok::elipsis_incl: case tok::land: case tok::lor: case tok::equals: @@ -150,10 +148,6 @@ public: case tok::assign: return 5; - case tok::elipsis_excl: - case tok::elipsis_incl: - return 10; - case tok::land: case tok::lor: return 20; diff --git a/include/dusk/Sema/Context.h b/include/dusk/Sema/Context.h index df3e54ebf43877ed549ae4eb959ef7ee5a00d416..3c3a08c415cb06b8dd24742d3ed87f4b7e66588a 100644 --- a/include/dusk/Sema/Context.h +++ b/include/dusk/Sema/Context.h @@ -46,9 +46,6 @@ public: /// Returns variable for given name, if found, \c nullptr otherwise. Decl *getVar(StringRef Str) const; - /// Returns variable for given name, if found, \c nullptr otherwise. - Decl *getVar(StringRef Str); - /// Returns variable for given name, if found, \c nullptr otherwise. Decl *get(StringRef Str) const; diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 53a9644e36199a723919de182a43d7db67f5ded8..5f68351d549cbcdf872cf1072547955c1832004b 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -228,7 +228,7 @@ public: Printer.printStmtPre(S); Printer << tok::kwFor << " "; - super::visit(S->getVar()); + super::visit(S->getIter()); Printer << " " << tok::kwIn << " "; super::visit(S->getRange()); Printer << " "; diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index f449fed52a99957682157f7dc34aaf3a9f5202cc..36527857cc3b11d6e32b2accca4a5101f3c3cba8 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -76,8 +76,8 @@ SMRange FuncStmt::getSourceRange() const { // MARK: Fot-in statement -ForStmt::ForStmt(SMLoc FL, Expr *V, Stmt *R, Stmt *B) - : Stmt(StmtKind::For), ForLoc(FL), Var(V), Range(R), Body(B) {} +ForStmt::ForStmt(SMLoc FL, Decl *V, Stmt *R, Stmt *B) + : Stmt(StmtKind::For), ForLoc(FL), Iter(V), Range(R), Body(B) {} SMRange ForStmt::getSourceRange() const { return {ForLoc, Body->getLocEnd()}; } diff --git a/lib/Parser/ParseStmt.cpp b/lib/Parser/ParseStmt.cpp index ec0e39f637bab47219460a6d4b1836fd2e0fc1eb..1529d9d092bf57a3d0d0e06db3b3be3e14b1c4b8 100644 --- a/lib/Parser/ParseStmt.cpp +++ b/lib/Parser/ParseStmt.cpp @@ -199,16 +199,19 @@ Stmt *Parser::parseFuncStmt() { return nullptr; } +/// ForStmt ::= +/// 'for' identifier 'in' Expr ('..' | '...') Expr Block Stmt *Parser::parseForStmt() { // Validate `for` keyword. assert(Tok.is(tok::kwFor) && "Invalid parse method"); auto FLoc = consumeToken(); - if (!Tok.is(tok::identifier)) { - diagnose(Tok.getLoc(), diag::DiagID::expected_identifier); + auto Ident = Tok; + if (!consumeIf(tok::identifier)) { + diagnose(Tok.getLoc(), diag::expected_identifier); return nullptr; } - auto Var = parseIdentifierExpr(); + auto Var = makeNode<ParamDecl>(Ident.getText(), Ident.getLoc()); if (!consumeIf(tok::kwIn)) { diagnose(Tok.getLoc(), diag::DiagID::expected_in_kw) .fixItBefore("in", Tok.getLoc()); diff --git a/lib/Sema/Context.cpp b/lib/Sema/Context.cpp index 6fde8fc8a91ec1d463eb3c81e0a95dbdafcf9d56..f979db6012c23e5968691284032037835e187d2d 100644 --- a/lib/Sema/Context.cpp +++ b/lib/Sema/Context.cpp @@ -39,16 +39,6 @@ Decl *ContextImpl::getVar(StringRef Str) const { return nullptr; } -Decl *ContextImpl::getVar(StringRef Str) { - auto Var = Vars.find(Str); - if (Var != Vars.end()) - return Var->second; - - if (Parent != nullptr) - return Parent->getVar(Str); - return nullptr; -} - Decl *ContextImpl::get(StringRef Str) const { if (auto Var = getVar(Str)) return Var; diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 42639f52f044000bae980d2fafa76a9dff645310..7b93672ab6d824538dd570936cc2816c35f6dcf3 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1,4 +1,3 @@ - //===--- Sema.cpp ---------------------------------------------------------===// // // dusk-lang @@ -22,17 +21,16 @@ #include "TypeChecker.h" - using namespace dusk; using namespace sema; namespace { - -class FwdDeclarator: public ASTWalker { + +class FwdDeclarator : public ASTWalker { Sema &S; Context &Ctx; DiagnosticEngine &Diag; - + public: FwdDeclarator(Sema &S, Context &C, DiagnosticEngine &D) : S(S), Ctx(C), Diag(D) {} @@ -44,7 +42,7 @@ public: return true; return false; } - + virtual bool postWalk(Decl *D) override { if (auto FD = dynamic_cast<FuncDecl *>(D)) { if (!Ctx.declareFunc(D)) { @@ -56,24 +54,23 @@ public: } return true; } - + // Skip all expressions. virtual bool preWalk(Expr *E) override { return false; } virtual bool preWalk(Stmt *S) override { switch (S->getKind()) { - case StmtKind::Func: - case StmtKind::Extern: - return true; - - // Skip all non-func related statements. - default: - return false; + case StmtKind::Func: + case StmtKind::Extern: + return true; + + // Skip all non-func related statements. + default: + return false; } } }; - -} // anonymous namespace +} // anonymous namespace Sema::Sema(ASTContext &C, DiagnosticEngine &D) : Ctx(C), Diag(D) {} @@ -117,10 +114,10 @@ Type *Sema::typeReprResolve(FuncDecl *FD) { llvm::SmallVector<Type *, 128> Args; for (auto Arg : FD->getArgs()->getVars()) Args.push_back(typeReprResolve(Arg->getTypeRepr())); - + auto ArgsT = std::make_unique<PatternType>(std::move(Args)); auto ArgsTT = Ctx.pushType(std::move(ArgsT)); - + Type *RetT = nullptr; if (!FD->hasTypeRepr()) { auto F = std::make_unique<VoidType>(); @@ -128,9 +125,8 @@ Type *Sema::typeReprResolve(FuncDecl *FD) { } else { RetT = typeReprResolve(FD->getTypeRepr()); } - + auto Ty = std::make_unique<FunctionType>(ArgsTT, RetT); return Ctx.pushType(std::move(Ty)); } - diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 09791168a2f4c287868f6e239d2a1fc62dbabdbc..8c1492d75a99b34accc94d290d0a466f42fac3e7 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -41,7 +41,8 @@ bool TypeChecker::preWalkVarDecl(VarDecl *D) { } bool TypeChecker::preWalkParamDecl(ParamDecl *D) { - D->setType(S.typeReprResolve(D->getTypeRepr())); + if (D->hasTypeRepr()) + D->setType(S.typeReprResolve(D->getTypeRepr())); return false; } @@ -99,12 +100,7 @@ bool TypeChecker::postWalkVarDecl(VarDecl *D) { } bool TypeChecker::postWalkParamDecl(ParamDecl *D) { - // Check if has resolved type - if (!D->getType()) - return false; - - // No default value, therefore don't have a reference to match against. - return DeclCtx.declareLet(D); + return D->getType() != nullptr; } bool TypeChecker::postWalkFuncDecl(FuncDecl *D) { diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index 348ef69f7b8e842741f116bbe4779e54e2b3280a..8276b782ac71835e325fb13d56670b40e67f0434 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -39,7 +39,19 @@ bool TypeChecker::preWalkBlockStmt(BlockStmt *S) { auto Proto = static_cast<FuncDecl *>(Fn->getPrototype()); auto Args = static_cast<VarPattern *>(Proto->getArgs()); for (auto Arg : Args->getVars()) - DeclCtx.declareLet(Arg); + if (!DeclCtx.declareLet(Arg)) { + Diag.diagnose(Args->getLocStart(), diag::redefinition_of_identifier); + return false; + } + } + + if (auto For = dynamic_cast<ForStmt *>(Scp.top().getStmt())) { + if (!For->getRange()->walk(*this)) + return false; + auto Rng = static_cast<RangeStmt *>(For->getRange()); + auto Iter = static_cast<ParamDecl *>(For->getIter()); + Iter->setType(Rng->getStart()->getType()); + DeclCtx.declareLet(Iter); } Scp.push(Scope(&Scp.top(), Scope::BlockScope, S)); return true; @@ -52,7 +64,7 @@ bool TypeChecker::preWalkExternStmt(ExternStmt *S) { } bool TypeChecker::preWalkForStmt(ForStmt *S) { - Scp.push(Scope(&Scp.top(), Scope::ControlScope, S)); + Scp.push(Scope(&Scp.top(), Scope::ControlScope | Scope::BreakScope, S)); return true; } @@ -62,13 +74,13 @@ bool TypeChecker::preWalkFuncStmt(FuncStmt *S) { } bool TypeChecker::preWalkIfStmt(IfStmt *S) { - Scp.push(Scope(&Scp.top(), 0, S)); + Scp.push(Scope(&Scp.top(), Scope::ControlScope, S)); return true; } bool TypeChecker::preWalkWhileStmt(WhileStmt *S) { - Scp.push(Scope(&Scp.top(), Scope::ControlScope, S)); - return false; + Scp.push(Scope(&Scp.top(), Scope::ControlScope | Scope::BreakScope, S)); + return true; }