From c7d8f8fe3ca45fbbaa224cf42ad5c3f79f2bee6f Mon Sep 17 00:00:00 2001
From: Peter Matta <mattapet@fit.cvut.cz>
Date: Mon, 7 May 2018 09:30:45 +0200
Subject: [PATCH] Adding standart func decls

---
 include/dusk/AST/Decl.h                   |  1 +
 include/dusk/CMakeLists.txt               |  1 +
 include/dusk/Runtime/CMakeLists.txt       |  6 ++
 include/dusk/Runtime/RuntimeFuncWrapper.h | 27 +++++++++
 include/dusk/Runtime/RuntimeFuncs.h       | 68 +++++++++++++++++++++++
 lib/AST/Decl.cpp                          |  3 +
 lib/Frontend/CompilerInstance.cpp         |  7 +--
 lib/IRGen/GenExpr.cpp                     |  3 +-
 lib/IRGen/IRGenModule.cpp                 | 17 +++++-
 lib/Parser/ParseExpr.cpp                  |  7 ++-
 lib/Parser/ParseStmt.cpp                  |  1 +
 lib/Parser/Parser.cpp                     |  6 --
 lib/Sema/Sema.cpp                         | 18 +++---
 lib/Sema/TypeCheckPattern.cpp             |  2 +
 14 files changed, 141 insertions(+), 26 deletions(-)
 create mode 100644 include/dusk/Runtime/CMakeLists.txt
 create mode 100644 include/dusk/Runtime/RuntimeFuncWrapper.h
 create mode 100644 include/dusk/Runtime/RuntimeFuncs.h

diff --git a/include/dusk/AST/Decl.h b/include/dusk/AST/Decl.h
index f4541af..8fb3506 100644
--- a/include/dusk/AST/Decl.h
+++ b/include/dusk/AST/Decl.h
@@ -168,6 +168,7 @@ public:
   ModuleDecl(StringRef N, std::vector<ASTNode *> &&C);
 
   ArrayRef<ASTNode *> getContents() const { return Contents; }
+  std::vector<ASTNode *> &getContents() { return Contents; }
   virtual SMRange getSourceRange() const override;
 };
 
diff --git a/include/dusk/CMakeLists.txt b/include/dusk/CMakeLists.txt
index 9b4b9d6..f731b2d 100644
--- a/include/dusk/CMakeLists.txt
+++ b/include/dusk/CMakeLists.txt
@@ -3,6 +3,7 @@ add_subdirectory(Basic)
 add_subdirectory(Frontend)
 add_subdirectory(IRGen)
 add_subdirectory(Parse)
+add_subdirectory(Runtime)
 add_subdirectory(Sema)
 
 set(HEADERS
diff --git a/include/dusk/Runtime/CMakeLists.txt b/include/dusk/Runtime/CMakeLists.txt
new file mode 100644
index 0000000..4060374
--- /dev/null
+++ b/include/dusk/Runtime/CMakeLists.txt
@@ -0,0 +1,6 @@
+SET(HEADERS
+    ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeFuncs.h
+    ${CMAKE_CURRENT_SOURCE_DIR}/RuntimeFuncWrapper.h
+    ${HEADERS}
+    PARENT_SCOPE
+)
diff --git a/include/dusk/Runtime/RuntimeFuncWrapper.h b/include/dusk/Runtime/RuntimeFuncWrapper.h
new file mode 100644
index 0000000..ac13337
--- /dev/null
+++ b/include/dusk/Runtime/RuntimeFuncWrapper.h
@@ -0,0 +1,27 @@
+//===--- RuntimeFuncWrapper.h - Runtime function generation -----*- 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_RUNTIME_FUNC_WRAPPER_H
+#define DUSK_RUNTIME_FUNC_WRAPPER_H
+
+#include "dusk/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+
+namespace dusk {
+  llvm::Value *getRuntimeFunc(llvm::Module *M,
+                              StringRef N,
+                              ArrayRef<llvm::Type *> ArgsT,
+                              llvm::Type *RetT);
+}
+
+#endif /* DUSK_RUNTIME_FUNC_WRAPPER_H */
diff --git a/include/dusk/Runtime/RuntimeFuncs.h b/include/dusk/Runtime/RuntimeFuncs.h
new file mode 100644
index 0000000..4285c9e
--- /dev/null
+++ b/include/dusk/Runtime/RuntimeFuncs.h
@@ -0,0 +1,68 @@
+//===--- RuntimeFuncs.h - Runtime function declarations ---------*- 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_RUNTIME_FUNCS_H
+#define DUSK_RUNTIME_FUNCS_H
+
+#include "dusk/Basic/LLVM.h"
+#include "dusk/AST/Decl.h"
+#include "dusk/AST/Expr.h"
+#include "dusk/AST/Stmt.h"
+#include "dusk/AST/Pattern.h"
+#include "dusk/AST/Type.h"
+#include "dusk/AST/NameLookup.h"
+#include "dusk/AST/ASTContext.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/SourceMgr.h"
+#include <memory>
+#include <vector>
+
+namespace dusk {
+
+static ASTNode *getPrintln(ASTContext &Context) {
+  auto TyRepr = std::make_unique<FuncRetTypeRepr>(SMLoc{}, "Int");
+  auto P = std::make_unique<ParamDecl>("val", SMLoc{},
+                                       Context.pushTypeRepr(std::move(TyRepr)));
+  llvm::SmallVector<Decl *, 128> Prms;
+  Prms.push_back(Context.pushNode(std::move(P)));
+  auto Pttrn = std::make_unique<VarPattern>(std::move(Prms), SMLoc{}, SMLoc{});
+  auto Fn = std::make_unique<FuncDecl>("println", SMLoc{}, SMLoc{},
+                                       Context.pushPattern(std::move(Pttrn)));
+  auto Extrn =
+      std::make_unique<ExternStmt>(SMLoc{}, Context.pushNode(std::move(Fn)));
+  auto C = Context.getRootModule()->getContents();
+  return Context.pushNode(std::move(Extrn));
+}
+
+static ASTNode *getReadln(ASTContext &Context) {
+  NameLookup NL;
+  llvm::SmallVector<Decl *, 128> Prms;
+  auto Pttrn = std::make_unique<VarPattern>(std::move(Prms), SMLoc{}, SMLoc{});
+  auto TyRepr = std::make_unique<FuncRetTypeRepr>(SMLoc{}, "Int");
+  auto Fn = std::make_unique<FuncDecl>("readln", SMLoc{}, SMLoc{},
+                                       Context.pushPattern(std::move(Pttrn)),
+                                       Context.pushTypeRepr(std::move(TyRepr)));
+  auto Extrn =
+      std::make_unique<ExternStmt>(SMLoc{}, Context.pushNode(std::move(Fn)));
+  auto C = Context.getRootModule()->getContents();
+  return Context.pushNode(std::move(Extrn));
+}
+
+static void getFuncs(ASTContext &Context) {
+  std::vector<ASTNode *> NF;
+  NF.push_back(getPrintln(Context));
+  NF.push_back(getReadln(Context));
+  auto &C = Context.getRootModule()->getContents();
+  NF.insert(NF.end(), C.begin(), C.end());
+  C = NF;
+}
+
+} // namespace dusk
+
+#endif /* DUSK_RUNTIME_FUNCS_H */
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e62c4a5..f948dde 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -88,6 +88,9 @@ ParamDecl::ParamDecl(StringRef N, SMLoc NL, TypeRepr *TR)
 
 // MARK: - FuncDecl class
 
+FuncDecl::FuncDecl(StringRef N, SMLoc NL, SMLoc FuncL, VarPattern *A)
+: Decl(DeclKind::Func, N, NL), FuncLoc(FuncL), Params(A) {}
+
 FuncDecl::FuncDecl(StringRef N, SMLoc NL, SMLoc FuncL, VarPattern *A,
                    TypeRepr *TR)
     : Decl(DeclKind::Func, N, NL, TR), FuncLoc(FuncL), Params(A) {}
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 5b5fecb..5644193 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -11,6 +11,7 @@
 
 #include "dusk/AST/Diagnostics.h"
 #include "dusk/Parse/Parser.h"
+#include "dusk/Runtime/RuntimeFuncs.h"
 #include "dusk/Sema/Sema.h"
 #include "dusk/IRGen/IRGenerator.h"
 #include "llvm/IR/Module.h"
@@ -58,6 +59,7 @@ void CompilerInstance::performSema() {
   performParseOnly();
   if (Context->isError())
     return;
+  getFuncs(*Context);
   sema::Sema S(*Context, Diag);
   S.perform();
 }
@@ -104,7 +106,7 @@ void CompilerInstance::emitObjectFile(llvm::Module *M) {
   auto RM = Optional<llvm::Reloc::Model>();
   auto TargetMachine = Target->createTargetMachine(Invocation.getTargetTriple(),
                                                    CPU, Features, Opt, RM);
-
+  
   M->setDataLayout(TargetMachine->createDataLayout());
   M->setTargetTriple(Invocation.getTargetTriple());
   
@@ -131,6 +133,3 @@ void CompilerInstance::emitObjectFile(llvm::Module *M) {
   dest.flush();
 }
 
-
-
-
diff --git a/lib/IRGen/GenExpr.cpp b/lib/IRGen/GenExpr.cpp
index 19ede3a..67f41ed 100644
--- a/lib/IRGen/GenExpr.cpp
+++ b/lib/IRGen/GenExpr.cpp
@@ -110,7 +110,8 @@ llvm::Value *irgen::codegenExpr(IRGenModule &IRGM, AssignExpr *E) {
   if (!VarAddr || !Val)
     llvm_unreachable("Invalid val or addr");
 
-  return IRGM.Builder.CreateStore(Val, VarAddr, "assign");
+  IRGM.Builder.CreateStore(Val, VarAddr, "assign");
+  return Val;
 }
 
 llvm::Value *irgen::codegenExpr(IRGenModule &IRGM, CallExpr *E) {
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 32d10d1..1ec5a16 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -12,6 +12,8 @@
 #include "dusk/AST/Decl.h"
 #include "dusk/AST/Type.h"
 #include "dusk/AST/ASTContext.h"
+#include "dusk/Runtime/RuntimeFuncWrapper.h"
+#include "dusk/Runtime/RuntimeFuncs.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Module.h"
@@ -36,11 +38,11 @@ Address IRGenModule::declareVal(Decl *D) {
     
     auto Ty = llvm::Type::getInt64Ty(LLVMContext);
 
-    auto gvar = new llvm::GlobalVariable(*Module, Ty, false,
+    auto GV = new llvm::GlobalVariable(*Module, Ty, false,
                                          llvm::GlobalValue::InternalLinkage,
                                          nullptr, D->getName());
-    gvar->setInitializer(llvm::ConstantInt::get(Ty, 0));
-    return gvar;
+    GV->setInitializer(llvm::ConstantInt::get(Ty, 0));
+    return GV;
   } else {
     if (!Lookup.declareVar(D))
       llvm_unreachable("Redefinition of a variable");
@@ -86,3 +88,12 @@ Address IRGenModule::getVal(StringRef N) {
 llvm::Function *IRGenModule::getFunc(StringRef N) {
   return Module->getFunction(N);
 }
+
+llvm::Value *dusk::getRuntimeFunc(llvm::Module *M, StringRef N,
+                                  ArrayRef<llvm::Type *> ArgsT,
+                                  llvm::Type *RetT) {
+  auto Proto = llvm::FunctionType::get(RetT, ArgsT, false);
+  auto Fn = llvm::Function::Create(Proto, llvm::GlobalValue::ExternalLinkage);
+  return Fn;
+}
+
diff --git a/lib/Parser/ParseExpr.cpp b/lib/Parser/ParseExpr.cpp
index b8f9627..0316a92 100644
--- a/lib/Parser/ParseExpr.cpp
+++ b/lib/Parser/ParseExpr.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "dusk/Parse/Parser.h"
+#include <cctype>
 
 using namespace dusk;
 
@@ -156,15 +157,15 @@ Expr *Parser::parseNumberLiteralExpr() {
     llvm::StringRef B = Str.slice(2, Str.size());
 
     // Parse hexadecimal literal
-    if (Str[0] == '0' && Str[1] == 'x')
+    if (Str[0] == '0' && std::tolower(Str[1]) == 'x')
       B.getAsInteger(16, Value);
 
     // Parse octal litera
-    else if (Str[0] == '0' && Str[1] == 'o')
+    else if (Str[0] == '0' && std::tolower(Str[1]) == 'o')
       B.getAsInteger(8, Value);
 
     // Parse binary literal
-    else if (Str[0] == '0' && Str[1] == 'b')
+    else if (Str[0] == '0' && std::tolower(Str[1]) == 'b')
       B.getAsInteger(2, Value);
     else
       // Parse decimal literal
diff --git a/lib/Parser/ParseStmt.cpp b/lib/Parser/ParseStmt.cpp
index 1529d9d..a9af3a8 100644
--- a/lib/Parser/ParseStmt.cpp
+++ b/lib/Parser/ParseStmt.cpp
@@ -67,6 +67,7 @@ Stmt *Parser::parseReturnStmt() {
   case tok::number_literal:
   case tok::l_paren:
   case tok::minus:
+  case tok::lnot:
     E = parseExpr();
     break;
   case tok::semicolon:
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index da8fb7d..70bd811 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -72,12 +72,6 @@ ASTNode *Parser::parseGlobal() {
     return parseExterStmt();
   case tok::kwFunc:
     return parseFuncStmt();
-  case tok::kwFor:
-    return parseForStmt();
-  case tok::kwWhile:
-    return parseWhileStmt();
-  case tok::kwIf:
-    return parseIfStmt();
 
   case tok::identifier:
   case tok::number_literal:
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 46b62e6..495ca1e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -36,7 +36,7 @@ public:
   FwdDeclarator(Sema &S, NameLookup &C, DiagnosticEngine &D)
       : S(S), Ctx(C), Diag(D) {}
 
-  virtual bool preWalk(Decl *D) override {
+  bool preWalk(Decl *D) override {
     if (D->getKind() == DeclKind::Func)
       return true;
     if (D->getKind() == DeclKind::Module)
@@ -44,29 +44,27 @@ public:
     return false;
   }
 
-  virtual bool postWalk(Decl *D) override {
+  bool postWalk(Decl *D) override {
     if (auto FD = dynamic_cast<FuncDecl *>(D)) {
       if (!Ctx.declareFunc(D)) {
         Diag.diagnose(D->getLocStart(), diag::redefinition_of_identifier);
         return false;
       }
       D->setType(S.typeReprResolve(FD));
-      return true;
     }
     return true;
   }
 
   // Skip all expressions.
-  virtual bool preWalk(Expr *E) override { return false; }
-  virtual bool preWalk(Stmt *S) override {
+  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;
     }
   }
 };
@@ -76,6 +74,7 @@ public:
 Sema::Sema(ASTContext &C, DiagnosticEngine &D) : Ctx(C), Diag(D) {}
 
 void Sema::perform() {
+  
   declareFuncs();
   typeCheck();
 }
@@ -112,6 +111,7 @@ Type *Sema::typeReprResolve(TypeRepr *TR) {
 }
 
 Type *Sema::typeReprResolve(FuncDecl *FD) {
+  // Aggregate args types
   llvm::SmallVector<Type *, 128> Args;
   for (auto Arg : FD->getArgs()->getVars())
     Args.push_back(typeReprResolve(Arg->getTypeRepr()));
@@ -119,6 +119,7 @@ Type *Sema::typeReprResolve(FuncDecl *FD) {
   auto ArgsT = std::make_unique<PatternType>(std::move(Args));
   auto ArgsTT = Ctx.pushType(std::move(ArgsT));
 
+  // Resolve return type
   Type *RetT = nullptr;
   if (!FD->hasTypeRepr()) {
     auto F = std::make_unique<VoidType>();
@@ -130,4 +131,3 @@ Type *Sema::typeReprResolve(FuncDecl *FD) {
   auto Ty = std::make_unique<FunctionType>(ArgsTT, RetT);
   return Ctx.pushType(std::move(Ty));
 }
-
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index d0a5a72..47889f7 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -34,6 +34,7 @@ bool TypeChecker::postWalkVarPattern(VarPattern *P) {
       return false;
     Ty.push_back(V->getType());
   }
+  
   auto PTy = std::make_unique<PatternType>(std::move(Ty));
   P->setType(Ctx.pushType(std::move(PTy)));
   return true;
@@ -46,6 +47,7 @@ bool TypeChecker::postWalkExprPattern(ExprPattern *P) {
       return false;
     Ty.push_back(V->getType());
   }
+  
   auto PTy = std::make_unique<PatternType>(std::move(Ty));
   P->setType(Ctx.pushType(std::move(PTy)));
   return true;
-- 
GitLab