diff --git a/include/dusk/Basic/TokenDefinition.h b/include/dusk/Basic/TokenDefinition.h index 3f51916cba00a490e8d2fe5d272d5a9a7b3ef527..939e95333a7c573147cf3ee438895ace03dabe58 100644 --- a/include/dusk/Basic/TokenDefinition.h +++ b/include/dusk/Basic/TokenDefinition.h @@ -28,10 +28,6 @@ enum struct tok { kwIn, kwFunc, kwExtern, - - // Types - kwVoid, - kwInt, // Identifier identifier, // [a-zA-Z_][a-zA-Z0-9_]+ @@ -94,7 +90,7 @@ enum struct tok { } // namespace dusk namespace llvm { -inline raw_ostream &operator<<(raw_ostream &OS, const dusk::tok &T) { +constexpr inline raw_ostream &operator<<(raw_ostream &OS, const dusk::tok &T) { switch (T) { // Keywords case dusk::tok::kwVar: @@ -119,13 +115,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const dusk::tok &T) { return OS << "func"; case dusk::tok::kwExtern: return OS << "extern"; - - // Types - case dusk::tok::kwVoid: - return OS << "Void"; - case dusk::tok::kwInt: - return OS << "Int"; - // Operators case dusk::tok::assign: diff --git a/include/dusk/CMakeLists.txt b/include/dusk/CMakeLists.txt index f731b2dfedc1e26f3614fa043025ae43444bf5a5..1609576a562463a94c09a5ce402ef3584f4a43df 100644 --- a/include/dusk/CMakeLists.txt +++ b/include/dusk/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory(Runtime) add_subdirectory(Sema) set(HEADERS + ${CMAKE_CURRENT_SOURCE_DIR}/Strings.h ${HEADERS} PARENT_SCOPE ) diff --git a/include/dusk/Parse/Token.h b/include/dusk/Parse/Token.h index bcea3580f4c104a64e36207cbf1a232908309c7f..65879ddcbf0b2609a6ef045c9e3708b59374cab8 100644 --- a/include/dusk/Parse/Token.h +++ b/include/dusk/Parse/Token.h @@ -125,8 +125,8 @@ public: case tok::kwFunc: case tok::kwExtern: - case tok::kwVoid: - case tok::kwInt: +// case tok::kwVoid: +// case tok::kwInt: return true; default: diff --git a/include/dusk/Strings.h b/include/dusk/Strings.h new file mode 100644 index 0000000000000000000000000000000000000000..c4bd7cd23f6de3b11081aa5cede8db51a76b07a5 --- /dev/null +++ b/include/dusk/Strings.h @@ -0,0 +1,23 @@ +//===--- Strings.h - Shared string constants --------------------*- C++ -*-===// +// +// dusk-lang +// This source file is part of a dusk-lang project, which is a semestral +// assignement for BI-PJP course at Czech Technical University in Prague. +// The software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND. +// +//===----------------------------------------------------------------------===// + +#ifndef DUSK_STRINGS_H +#define DUSK_STRINGS_H + +namespace dusk { + +/// The name of buildin type for \c Int +constexpr static const char BUILTIN_TYPE_NAME_INT[] = "Int"; + +/// The name for buildin type for \c Void +constexpr static const char BUILTIN_TYPE_NAME_VOID[] = "Void"; + +} // namespace dusk + +#endif /* DUSK_STRINGS_H */ diff --git a/lib/AST/TypeRepr.cpp b/lib/AST/TypeRepr.cpp index e14eda2cc14c3df05f940136c315eb2fc8bbad37..7afa232f8e55fb91b635374406f95306cb3864a8 100644 --- a/lib/AST/TypeRepr.cpp +++ b/lib/AST/TypeRepr.cpp @@ -13,7 +13,7 @@ using namespace dusk; -TypeRepr::TypeRepr(TypeReprKind K) : Kind(K) {} +TypeRepr::TypeRepr(TypeReprKind K) : Kind(K), Ty(nullptr) {} IdentTypeRepr *TypeRepr::getIdentTypeRepr() { assert(Kind == TypeReprKind::Ident && "Invalid TypeRepr convertion"); diff --git a/lib/Parser/Lexer.cpp b/lib/Parser/Lexer.cpp index e620c537e4f671efa7f332195988f61abe291bfa..e255d29555b3b56ba28b587a854f6413f2a30e54 100644 --- a/lib/Parser/Lexer.cpp +++ b/lib/Parser/Lexer.cpp @@ -311,8 +311,6 @@ tok Lexer::kindOfIdentifier(StringRef Str) { .Case("in", tok::kwIn) .Case("func", tok::kwFunc) .Case("extern", tok::kwExtern) - .Case("Void", tok::kwVoid) - .Case("Int", tok::kwInt) .Default(tok::identifier); } diff --git a/lib/Parser/ParseDecl.cpp b/lib/Parser/ParseDecl.cpp index f50dab58039e9104a803ee87ad90eb8e7921dd8c..b74724ca6d04f16d97a91065e633729e8e8d98c2 100644 --- a/lib/Parser/ParseDecl.cpp +++ b/lib/Parser/ParseDecl.cpp @@ -105,7 +105,6 @@ Decl *Parser::parseFuncDecl() { auto Args = static_cast<VarPattern *>(parseVarPattern()); auto RetTy = parseFuncDeclType(); return new (Context) FuncDecl(ID.getText(), ID.getLoc(), FL, Args, RetTy); -// return makeNode<FuncDecl>(ID.getText(), ID.getLoc(), FL, Args, RetTy); } /// Value decl type @@ -134,13 +133,10 @@ TypeRepr *Parser::parseFuncDeclType() { .fixItBefore("->", Tok.getLoc()); return nullptr; } - auto Ty = Tok.getText(); - if (consumeIf(tok::kwVoid)) - return new(Context) IdentTypeRepr(Ty); - if (consumeIf(tok::kwInt)) - return new(Context) IdentTypeRepr(Ty); - + if (Tok.is(tok::identifier)) + return parseTypeRepr(); + diagnose(Tok.getLoc(), diag::DiagID::expected_type_specifier) .fixItBefore("Int", Tok.getLoc()) .fixItBefore("Void", Tok.getLoc()); diff --git a/lib/Parser/ParseType.cpp b/lib/Parser/ParseType.cpp index 852b5273e4542760af072ee02ca8a476dc647ce5..bdbd8891e4b63e9fdc4cfb62edfa00af27854c08 100644 --- a/lib/Parser/ParseType.cpp +++ b/lib/Parser/ParseType.cpp @@ -16,31 +16,20 @@ using namespace dusk; /// IdentTypeRepr /// ArrayTypeRepr TypeRepr *Parser::parseTypeRepr() { - switch (Tok.getKind()) { - case tok::kwInt: - case tok::kwVoid: + if (Tok.is(tok::identifier)) return parseIdentType(); - - default: - // Unexpected token - diagnose(Tok.getLoc()); - return nullptr; - } + // Unexpected token + diagnose(Tok.getLoc()); + return nullptr; } /// IdentType ::= /// ':' identifier TypeRepr *Parser::parseIdentType() { + assert(Tok.is(tok::identifier) && "Invalid parse method"); auto Ty = Tok; - switch (Tok.getKind()) { - case tok::kwInt: - case tok::kwVoid: - consumeToken(); - return parseArrayType(new (Context) IdentTypeRepr(Ty.getText())); - - default: - llvm_unreachable("Invalid parse method"); - } + consumeToken(); + return parseArrayType(new (Context) IdentTypeRepr(Ty.getText())); } /// ArrayType ::= diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index cc7e7f5b7d3bad71b570e424dbfd2523b574f761..27ca952bdc0ab02d39efd9b59cd8bc261c06adf7 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -17,6 +17,9 @@ #include "dusk/AST/TypeRepr.h" #include "dusk/AST/Diagnostics.h" #include "dusk/AST/NameLookup.h" + +#include "dusk/Strings.h" + #include "dusk/Runtime/RuntimeFuncs.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" @@ -58,14 +61,15 @@ public: // Skip all expressions. bool preWalk(Expr *E) override { return false; } - + 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; + default: + return false; } } }; @@ -75,7 +79,6 @@ public: Sema::Sema(ASTContext &C, DiagnosticEngine &D) : Ctx(C), Diag(D) {} void Sema::perform() { - declareFuncs(); typeCheck(); } @@ -90,10 +93,10 @@ void Sema::typeCheck() { } static Type *typeReprResolve(Sema &S, ASTContext &C, IdentTypeRepr *TyRepr) { - if (TyRepr->getIdent() == "Int") - return new(C) IntType(); - else if (TyRepr->getIdent() == "Void") - return new(C) VoidType(); + if (TyRepr->getIdent() == BUILTIN_TYPE_NAME_INT) + return new (C) IntType(); + else if (TyRepr->getIdent() == BUILTIN_TYPE_NAME_VOID) + return new (C) VoidType(); else return nullptr; } @@ -102,7 +105,7 @@ static Type *typeReprResolve(Sema &S, ASTContext &C, ArrayTypeRepr *TyRepr) { auto BaseTy = S.typeReprResolve(TyRepr->getBaseTyRepr()); auto Size = static_cast<SubscriptStmt *>(TyRepr->getSize()); auto SizeVal = static_cast<NumberLiteralExpr *>(Size->getValue())->getValue(); - return new(C) ArrayType(BaseTy, SizeVal); + return new (C) ArrayType(BaseTy, SizeVal); } Type *Sema::typeReprResolve(TypeRepr *TR) { @@ -120,26 +123,26 @@ Type *Sema::typeReprResolve(FuncDecl *FD) { for (auto Arg : FD->getArgs()->getVars()) Args.push_back(typeReprResolve(Arg->getTypeRepr())); - auto ArgsT = new(Ctx) PatternType(std::move(Args)); + auto ArgsT = new (Ctx) PatternType(std::move(Args)); // Resolve return type Type *RetT = nullptr; if (!FD->hasTypeRepr()) { - RetT = new(Ctx) VoidType(); + RetT = new (Ctx) VoidType(); } else { RetT = typeReprResolve(FD->getTypeRepr()); } - return new(Ctx) FunctionType(ArgsT, RetT); + return new (Ctx) FunctionType(ArgsT, RetT); } Type *Sema::typeReprResolve(ArrayLiteralExpr *E) { auto Ty = static_cast<PatternType *>(E->getValues()->getType()); if (Ty->getItems().size() == 0) return nullptr; - + auto RefT = Ty->getItems()[0]; - auto ATy = new(Ctx) ArrayType(RefT, E->getValues()->count()); + auto ATy = new (Ctx) ArrayType(RefT, E->getValues()->count()); for (size_t i = 1; i < Ty->getItems().size(); i++) { if (!RefT->isClassOf(Ty->getItems()[i])) { Diag.diagnose(E->getLocStart(), diag::array_element_mismatch); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 4ded9767fcbe0ba17bd7aacc5da27c1d299ea74f..6da0dfa8f36bc614bddabe4b0187294e3a74534d 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -9,6 +9,7 @@ #include "TypeChecker.h" +#include "dusk/Strings.h" #include "dusk/AST/Diagnostics.h" #include "dusk/AST/Scope.h" #include "dusk/AST/NameLookup.h" @@ -22,48 +23,47 @@ using namespace dusk; using namespace sema; namespace { - + class TypeReprChecker : public TypeReprVisitor<TypeReprChecker> { TypeChecker &TC; - + typedef ASTVisitor super; - + friend super; - + public: TypeReprChecker(TypeChecker &TC) : TC(TC) {} - + private: - void visitIdentTypeRepr(IdentTypeRepr *TR) { auto Ty = llvm::StringSwitch<Type *>(TR->getIdent()) - .Case("Int", TC.Ctx.getIntType()) - .Case("Void", TC.Ctx.getVoidType()) - .Default(nullptr); - + .Case(BUILTIN_TYPE_NAME_INT, TC.Ctx.getIntType()) + .Case(BUILTIN_TYPE_NAME_VOID, TC.Ctx.getVoidType()) + .Default(nullptr); + if (Ty) TR->setType(Ty); else TC.diagnose(TR->getLocStart(), diag::unknown_type); } - + void visitArrayTypeRepr(ArrayTypeRepr *TR) { typeCheckType(TR->getBaseTyRepr()); TC.typeCheckStmt(TR->getSize()); - + auto BaseTy = TR->getBaseTyRepr()->getType(); auto Size = dynamic_cast<NumberLiteralExpr *>( TR->getSize()->getSubscripStmt()->getValue()); - + if (!BaseTy) return; - + // Array must not be of null type if (BaseTy->isVoidType()) { TC.diagnose(TR->getLocStart(), diag::type_missmatch); return; } - + // Array size must be known at compile time if (!Size) { TC.diagnose(TR->getSize()->getLocStart(), diag::variable_array_size); @@ -72,13 +72,11 @@ private: auto Ty = new (TC.Ctx) ArrayType(BaseTy, Size->getValue()); TR->setType(Ty); } - + public: - void typeCheckType(TypeRepr *TR) { - super::visit(TR); - } + void typeCheckType(TypeRepr *TR) { super::visit(TR); } }; - + } // anonymous namespace void TypeChecker::typeCheckType(TypeRepr *TR) {