From c0e77d22cf83cc205a6553af3b9d244e9cf045ce Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 22 Sep 2023 16:38:17 -0500 Subject: [PATCH 01/10] Print generated llvm --- app/LLVMGen/Expression.hs | 6 +++--- app/Main.hs | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/LLVMGen/Expression.hs b/app/LLVMGen/Expression.hs index 0b2c4d2..e501bd0 100644 --- a/app/LLVMGen/Expression.hs +++ b/app/LLVMGen/Expression.hs @@ -1,4 +1,4 @@ -module LLVMGen.Expression () where +module LLVMGen.Expression (getLLVM) where import qualified Objects.Expression as Expr @@ -47,5 +47,5 @@ toLLVM modul = withContext $ \ctx -> do llvm <- withModuleFromAST ctx modul moduleLLVMAssembly BS.putStrLn llvm -main :: IO () -main = toLLVM module_ \ No newline at end of file +getLLVM :: IO () +getLLVM = toLLVM module_ \ No newline at end of file diff --git a/app/Main.hs b/app/Main.hs index d9407df..b75f999 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -6,6 +6,7 @@ import Eval.Expression import Objects.Expression import Parser.Expression import System.Environment +import LLVMGen.Expression import System.IO import Text.Megaparsec @@ -20,3 +21,4 @@ main = do contents <- readFile fileName let result = getResult contents print result + getLLVM From d42de52f78524942f49bcf231f6114ebf5e63315 Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 22 Sep 2023 23:59:31 -0500 Subject: [PATCH 02/10] Generate LLVM program that returns 0 when run --- README.md | 4 ++-- {app => main}/Eval/Expression.hs | 0 {app => main}/LLVMGen/Expression.hs | 22 ++++++++++++++++++++-- {app => main}/Main.hs | 0 {app => main}/Objects/Expression.hs | 0 {app => main}/Parser/Expression.hs | 0 package.yaml | 2 +- really-bad-compiler-in-haskell.cabal | 2 +- 8 files changed, 24 insertions(+), 6 deletions(-) rename {app => main}/Eval/Expression.hs (100%) rename {app => main}/LLVMGen/Expression.hs (68%) rename {app => main}/Main.hs (100%) rename {app => main}/Objects/Expression.hs (100%) rename {app => main}/Parser/Expression.hs (100%) diff --git a/README.md b/README.md index f26cbc7..ff890c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Really Bad Compiler in Haskell -A compiler written in Haskell which can currently perform basic arithmetic using the megaparsec and llvm-hs libraries (I do not know what language I am going to compile yet). Built for the Introduction to Compiler Design class at The University of Texas at Dallas. +A compiler written in Haskell which can currently perform basic arithmetic. Currently using the megaparsec and llvm-hs libraries, but I plan to reimplement parsing and llvm generation myself. Built for the Introduction to Compiler Design class at The University of Texas at Dallas. Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell @@ -42,5 +42,5 @@ Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell - Dependencies: llvm, clang - IDE: VSCodium - Git platform: Forgejo -- AI: Phind +- AI: Phind (GPT-4), ollama (codellama) - Search: Kagi, Stack Overflow diff --git a/app/Eval/Expression.hs b/main/Eval/Expression.hs similarity index 100% rename from app/Eval/Expression.hs rename to main/Eval/Expression.hs diff --git a/app/LLVMGen/Expression.hs b/main/LLVMGen/Expression.hs similarity index 68% rename from app/LLVMGen/Expression.hs rename to main/LLVMGen/Expression.hs index e501bd0..f3a0d28 100644 --- a/app/LLVMGen/Expression.hs +++ b/main/LLVMGen/Expression.hs @@ -5,6 +5,9 @@ import qualified Objects.Expression as Expr import LLVM.AST import qualified LLVM.AST as AST import LLVM.AST.Global +import LLVM.AST.Constant +import LLVM.AST.Type +import LLVM.AST.Name import LLVM.Context import LLVM.Module @@ -13,6 +16,21 @@ import Data.ByteString.Char8 as BS int :: Type int = IntegerType 32 +defMain :: Definition +defMain = GlobalDefinition functionDefaults + { name = Name "main" + , parameters = + ( [] + , False ) + , returnType = int + , basicBlocks = [body] + } + where + body = BasicBlock + (Name "entry") + [] + (Do $ Ret (Just (ConstantOperand (Int 32 0))) []) + defAdd :: Definition defAdd = GlobalDefinition functionDefaults { name = Name "add" @@ -27,7 +45,7 @@ defAdd = GlobalDefinition functionDefaults body = BasicBlock (Name "entry") [ Name "result" := - Add False -- no signed wrap + AST.Add False -- no signed wrap False -- no unsigned wrap (LocalReference int (Name "a")) (LocalReference int (Name "b")) @@ -38,7 +56,7 @@ defAdd = GlobalDefinition functionDefaults module_ :: AST.Module module_ = defaultModule { moduleName = "basic" - , moduleDefinitions = [defAdd] + , moduleDefinitions = [defMain, defAdd] } diff --git a/app/Main.hs b/main/Main.hs similarity index 100% rename from app/Main.hs rename to main/Main.hs diff --git a/app/Objects/Expression.hs b/main/Objects/Expression.hs similarity index 100% rename from app/Objects/Expression.hs rename to main/Objects/Expression.hs diff --git a/app/Parser/Expression.hs b/main/Parser/Expression.hs similarity index 100% rename from app/Parser/Expression.hs rename to main/Parser/Expression.hs diff --git a/package.yaml b/package.yaml index af19751..edb5381 100644 --- a/package.yaml +++ b/package.yaml @@ -19,7 +19,7 @@ ghc-options: -threaded -Wall -j8 +RTS -A64M -RTS -fllvm # source-dirs: src executable: - source-dirs: app + source-dirs: main main: Main.hs # tests: # testall: diff --git a/really-bad-compiler-in-haskell.cabal b/really-bad-compiler-in-haskell.cabal index 25ecb34..fc851e2 100644 --- a/really-bad-compiler-in-haskell.cabal +++ b/really-bad-compiler-in-haskell.cabal @@ -22,7 +22,7 @@ executable really-bad-compiler-in-haskell Parser.Expression Paths_really_bad_compiler_in_haskell hs-source-dirs: - app + main default-extensions: OverloadedStrings, LambdaCase ghc-options: -threaded -Wall -j8 +RTS -A64M -RTS -fllvm From 9f9642347bd62dcb4c562e96894be2d71bb227be Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Sat, 23 Sep 2023 23:15:11 -0500 Subject: [PATCH 03/10] Start new LLVM generator using IRBuilder --- README.md | 17 +++--- main/Eval/{Expression.hs => Expr.hs} | 4 +- main/LLVMGen/Expr.hs | 57 +++++++++++++++++++++ main/LLVMGen/{Expression.hs => Expr.hs.old} | 13 +++-- main/Main.hs | 21 ++++---- main/Objects/Expression.hs | 19 ------- main/Parser/{Expression.hs => Expr.hs} | 9 +++- main/Types/Expr.hs | 9 ++++ package.yaml | 4 +- really-bad-compiler-in-haskell.cabal | 10 ++-- stack.yaml | 6 +-- stack.yaml.lock | 24 ++++----- 12 files changed, 126 insertions(+), 67 deletions(-) rename main/Eval/{Expression.hs => Expr.hs} (71%) create mode 100644 main/LLVMGen/Expr.hs rename main/LLVMGen/{Expression.hs => Expr.hs.old} (76%) delete mode 100644 main/Objects/Expression.hs rename main/Parser/{Expression.hs => Expr.hs} (72%) create mode 100644 main/Types/Expr.hs diff --git a/README.md b/README.md index ff890c3..eb406d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Really Bad Compiler in Haskell -A compiler written in Haskell which can currently perform basic arithmetic. Currently using the megaparsec and llvm-hs libraries, but I plan to reimplement parsing and llvm generation myself. Built for the Introduction to Compiler Design class at The University of Texas at Dallas. +A compiler written in Haskell which can currently perform basic arithmetic. Currently using the megaparsec and llvm-hs-\* libraries, but I plan to reimplement parsing and llvm generation myself. Built for the Introduction to Compiler Design class at The University of Texas at Dallas. Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell @@ -27,19 +27,22 @@ Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell ### Learning Resources Used - Introduction to Compiler Design class at The University of Texas at Dallas, taught by Charles Averill -- learnyouahaskell.com (for learning Haskell basics) +- https://learnyouahaskell.com (for learning Haskell basics) - https://akashagrawal.me/2017/01/19/beginners-guide-to-megaparsec.html -- https://markkarpov.com/tutorial/megaparsec.html (for help writing a Haskell equation parser) +- https://markkarpov.com/tutorial/megaparsec.html (for help writing a Haskell equation parser using megaparsec) - https://www.forth.com/starting-forth/1-forth-stacks-dictionary/ (for learning Forth) - https://blog.josephmorag.com/posts/mcc0/ (Haskell compiler tutorial with megaparsec, llvm-hs, and nix) -- https://gh.sudoer.ch/llvm-hs/llvm-hs-examples (for help writing an llvm code generator) +- https://gh.sudoer.ch/llvm-hs/llvm-hs-examples (for help writing an llvm code generator using llvm-hs) +- https://danieljharvey.github.io/posts/2023-02-08-llvm-compiler-part-1.html (for help using llvm-hs-pure) +- https://gh.sudoer.ch/danieljharvey/mimsa/blob/trunk/llvm-calc/src/Calc/Compile/ToLLVM.hs (source code for above resource) +- https://9to5tutorial.com/homebrew-compiler-made-with-haskell-llvm-configuration (for help using llvm-hs-pure) ### Tools - Language: Haskell -- Haskell tools: GHCup, Stack, Cabal -- Libraries: megaparsec, parser-combinators, text, llvm-hs-pure -- Dependencies: llvm, clang +- Haskell tools: GHCup, Stack, Cabal, GHC 9.2 +- Libraries: megaparsec, parser-combinators, text, llvm-hs-pure 15, llvm-hs-pretty-15 +- Dependencies: llvm 15, clang 15 - IDE: VSCodium - Git platform: Forgejo - AI: Phind (GPT-4), ollama (codellama) diff --git a/main/Eval/Expression.hs b/main/Eval/Expr.hs similarity index 71% rename from main/Eval/Expression.hs rename to main/Eval/Expr.hs index 325afdf..c8016fe 100644 --- a/main/Eval/Expression.hs +++ b/main/Eval/Expr.hs @@ -1,6 +1,6 @@ -module Eval.Expression (evalExpr) where +module Eval.Expr (evalExpr) where -import Objects.Expression +import Types.Expr eval :: Expr -> Int eval (Lit x) = x diff --git a/main/LLVMGen/Expr.hs b/main/LLVMGen/Expr.hs new file mode 100644 index 0000000..78d89b8 --- /dev/null +++ b/main/LLVMGen/Expr.hs @@ -0,0 +1,57 @@ +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} + +-- see https://gh.sudoer.ch/danieljharvey/mimsa/blob/trunk/llvm-calc/src/Calc/Compile/ToLLVM.hs + +module LLVMGen.Expr (getLLVMStr) where + +import Data.Text.Lazy +import LLVM.AST hiding (function) +import LLVM.AST.Type +import LLVM.IRBuilder.Constant +import LLVM.IRBuilder.Instruction +import LLVM.IRBuilder.Module +import LLVM.IRBuilder.Monad +import LLVM.Pretty +import Types.Expr as Expr + +-- charStar :: LLVM.Type +-- charStar = LLVM.ptr LLVM.i8 + +getLLVM :: Expr -> Module +getLLVM expr = + buildModule "program" $ do + -- TODO: better naming + printf <- externVarArgs "printf" [ptr] i32 -- or LLVM.ptr LLVM.i8 + let numFormatStr = globalStringPtr "%d\n" (mkName "str") + function "main" [] i32 $ \_ -> do + ourExpression <- exprToLLVM expr + nfs <- numFormatStr + _ <- call i32 printf [(ConstantOperand nfs, []), (ourExpression, [])] + ret (int32 0) + +exprToLLVM :: + ( MonadIRBuilder m, + MonadModuleBuilder m + ) => + Expr -> + m Operand +exprToLLVM (Lit prim) = pure $ primToLLVM prim +exprToLLVM (Expr.Add a b) = do + lhs <- exprToLLVM a + rhs <- exprToLLVM b + add lhs rhs +exprToLLVM (Expr.Sub a b) = do + lhs <- exprToLLVM a + rhs <- exprToLLVM b + sub lhs rhs +exprToLLVM (Expr.Mul a b) = do + lhs <- exprToLLVM a + rhs <- exprToLLVM b + mul lhs rhs + +primToLLVM :: Int -> Operand +primToLLVM i = int32 (fromIntegral i) + +getLLVMStr :: Expr -> Text +getLLVMStr expr = ppllvm (getLLVM expr) \ No newline at end of file diff --git a/main/LLVMGen/Expression.hs b/main/LLVMGen/Expr.hs.old similarity index 76% rename from main/LLVMGen/Expression.hs rename to main/LLVMGen/Expr.hs.old index f3a0d28..fac2110 100644 --- a/main/LLVMGen/Expression.hs +++ b/main/LLVMGen/Expr.hs.old @@ -1,6 +1,6 @@ -module LLVMGen.Expression (getLLVM) where +module LLVMGen.Expr (getLLVM) where -import qualified Objects.Expression as Expr +import qualified Objects.Expr as Expr import LLVM.AST import qualified LLVM.AST as AST @@ -28,7 +28,13 @@ defMain = GlobalDefinition functionDefaults where body = BasicBlock (Name "entry") - [] + [ Name "calltmp" := + Call + { tailCallKind = Nothing + , function = Right (ConstantOperand (GlobalReference (PointerType (FunctionType int [int, int] False) defaultAddrSpace) (Name "add"))) + , arguments = [ (ConstantOperand (Int 32 10), []), (ConstantOperand (Int 32 20), []) ] + } + ] (Do $ Ret (Just (ConstantOperand (Int 32 0))) []) defAdd :: Definition @@ -52,7 +58,6 @@ defAdd = GlobalDefinition functionDefaults []] (Do $ Ret (Just (LocalReference int (Name "result"))) []) - module_ :: AST.Module module_ = defaultModule { moduleName = "basic" diff --git a/main/Main.hs b/main/Main.hs index b75f999..642cc99 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -1,24 +1,25 @@ +{-# LANGUAGE ImportQualifiedPost #-} +{-# LANGUAGE OverloadedStrings #-} + module Main (main) where -import Control.Monad -import Data.Either -import Eval.Expression -import Objects.Expression -import Parser.Expression +import Data.Text.Lazy.IO qualified as T +import Eval.Expr +import LLVMGen.Expr +import Parser.Expr import System.Environment -import LLVMGen.Expression -import System.IO -import Text.Megaparsec +import Types.Expr getRight :: ParseResult -> Expr getRight (Right r) = r getResult :: String -> Int -getResult str = evalExpr (getRight (parseExpr str)) +getResult str = evalExpr (getRight (parseExpr str)) -- TODO: add error messages +main :: IO () main = do fileName <- fmap head getArgs contents <- readFile fileName let result = getResult contents print result - getLLVM + T.putStrLn (getLLVMStr (getRight (parseExpr contents))) diff --git a/main/Objects/Expression.hs b/main/Objects/Expression.hs deleted file mode 100644 index 932df82..0000000 --- a/main/Objects/Expression.hs +++ /dev/null @@ -1,19 +0,0 @@ -module Objects.Expression - ( Expr - ( Lit, - Add, - Sub, - Mul, - Div - ), - -- solve, - ) -where - -data Expr - = Lit Int - | Add Expr Expr - | Sub Expr Expr - | Mul Expr Expr - | Div Expr Expr - deriving (Show) \ No newline at end of file diff --git a/main/Parser/Expression.hs b/main/Parser/Expr.hs similarity index 72% rename from main/Parser/Expression.hs rename to main/Parser/Expr.hs index 0d323ff..a2f3f4c 100644 --- a/main/Parser/Expression.hs +++ b/main/Parser/Expr.hs @@ -1,11 +1,15 @@ -module Parser.Expression (parseExpr, ParseResult) where +-- see https://markkarpov.com/tutorial/megaparsec.html +{-# LANGUAGE ImportQualifiedPost #-} + +module Parser.Expr (parseExpr, ParseResult) where import Control.Monad.Combinators.Expr +import Data.Functor.Identity qualified import Data.Void (Void) -import Objects.Expression import Text.Megaparsec as MP import Text.Megaparsec.Char as C import Text.Megaparsec.Char.Lexer as L +import Types.Expr type Parser = Parsec Void String @@ -31,6 +35,7 @@ table = ] ] +binaryOp :: String -> (a -> a -> a) -> Operator (ParsecT Void String Data.Functor.Identity.Identity) a binaryOp name f = InfixL (f <$ symbolParser name) expr :: Parser Expr diff --git a/main/Types/Expr.hs b/main/Types/Expr.hs new file mode 100644 index 0000000..f6c3dee --- /dev/null +++ b/main/Types/Expr.hs @@ -0,0 +1,9 @@ +module Types.Expr (Expr (..)) where + +data Expr + = Lit Int + | Add Expr Expr + | Sub Expr Expr + | Mul Expr Expr + | Div Expr Expr + deriving (Show) \ No newline at end of file diff --git a/package.yaml b/package.yaml index edb5381..ff881a5 100644 --- a/package.yaml +++ b/package.yaml @@ -6,9 +6,9 @@ dependencies: - megaparsec >= 9.0.1 && < 10 - parser-combinators - text - - llvm-hs >= 15 && < 16 + # - llvm-hs >= 15 && < 16 - llvm-hs-pure >= 15 && < 16 - # - llvm-hs-pretty >= 15 && < 16 + - llvm-hs-pretty >= 15 && < 16 - bytestring tested-with: GHC == 9.2.8 category: Compilers/Interpreters diff --git a/really-bad-compiler-in-haskell.cabal b/really-bad-compiler-in-haskell.cabal index fc851e2..8d3b947 100644 --- a/really-bad-compiler-in-haskell.cabal +++ b/really-bad-compiler-in-haskell.cabal @@ -16,10 +16,10 @@ tested-with: executable really-bad-compiler-in-haskell main-is: Main.hs other-modules: - Eval.Expression - LLVMGen.Expression - Objects.Expression - Parser.Expression + Eval.Expr + LLVMGen.Expr + Parser.Expr + Types.Expr Paths_really_bad_compiler_in_haskell hs-source-dirs: main @@ -29,7 +29,7 @@ executable really-bad-compiler-in-haskell build-depends: base >=4.14.3 && <5 , bytestring - , llvm-hs ==15.* + , llvm-hs-pretty ==15.* , llvm-hs-pure ==15.* , megaparsec >=9.0.1 && <10 , parser-combinators diff --git a/stack.yaml b/stack.yaml index f5a1103..7070a4e 100644 --- a/stack.yaml +++ b/stack.yaml @@ -3,13 +3,13 @@ resolver: lts-20.26 packages: - . extra-deps: - # - github: hyunsooda/llvm-hs-pretty-15 - # commit: 79283942d1667168ecd65237667aff7fed730303 + - github: hyunsooda/llvm-hs-pretty-15 + commit: 79283942d1667168ecd65237667aff7fed730303 - github: llvm-hs/llvm-hs commit: 5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76 subdirs: - llvm-hs-pure - - llvm-hs + # - llvm-hs nix: enable: true packages: [llvm_15, clang_15, libxml2] diff --git a/stack.yaml.lock b/stack.yaml.lock index 0055e8d..f76a1f2 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -4,6 +4,17 @@ # https://docs.haskellstack.org/en/stable/lock_files packages: +- completed: + name: llvm-hs-pretty + pantry-tree: + sha256: 22ac4a47e1833dece52af7a6f8589958021d67292f6cc3de015ecb7c699db62d + size: 5197 + sha256: 8348b72a61807414ad15e0b7e82a7753e4473701e7ab98520c2e9d9a51c5ed7f + size: 43787 + url: https://github.com/hyunsooda/llvm-hs-pretty-15/archive/79283942d1667168ecd65237667aff7fed730303.tar.gz + version: 15.0.0 + original: + url: https://github.com/hyunsooda/llvm-hs-pretty-15/archive/79283942d1667168ecd65237667aff7fed730303.tar.gz - completed: name: llvm-hs-pure pantry-tree: @@ -17,19 +28,6 @@ packages: original: subdir: llvm-hs-pure url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz -- completed: - name: llvm-hs - pantry-tree: - sha256: 21f74a6f51fae6c0a0fcf3e6620a59f341289ac743998b41ed3276fd1b7d8862 - size: 12716 - sha256: 526b67e2da9ce25b3856c221b6772e699a7593dbb5ba38e7ee2436349de70966 - size: 9802209 - subdir: llvm-hs - url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz - version: 15.0.0 - original: - subdir: llvm-hs - url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz snapshots: - completed: sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2 From 30df05afa9ef835015b86cdb3d51af565e78196b Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Thu, 28 Sep 2023 23:42:59 -0500 Subject: [PATCH 04/10] Generate LLVM code and print to console --- .vscode/extensions.json | 7 ++++++ .vscode/launch.json | 46 +++++++++++++++++++++++++++++++++++++ .vscode/tasks.json | 50 +++++++++++++++++++++++++++++++++++++++++ README.md | 4 ++++ main/Eval/Expr.hs | 3 ++- main/LLVMGen/Expr.hs | 26 ++++++++++++--------- main/Main.hs | 3 ++- main/Parser/Expr.hs | 4 ++-- main/Types/Expr.hs | 4 ++-- 9 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..2201e47 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "gattytto.phoityne-vscode", + "haskell.haskell", + "justusadam.language-haskell" + ] +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ad9207c --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,46 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "ghc", + "request": "launch", + "name": "haskell(stack)", + "internalConsoleOptions": "openOnSessionStart", + "workspace": "${workspaceFolder}", + "startup": "${workspaceFolder}/test/Spec.hs", + "startupFunc": "", + "startupArgs": "", + "stopOnEntry": false, + "mainArgs": "", + "ghciPrompt": "H>>= ", + "ghciInitialPrompt": "Prelude>", + "ghciCmd": "stack ghci --test --no-load --no-build --main-is TARGET", + "ghciEnv": {}, + "logFile": "${workspaceFolder}/.vscode/phoityne.log", + "logLevel": "WARNING", + "forceInspect": false + }, + { + "type": "ghc", + "request": "launch", + "name": "haskell(cabal)", + "internalConsoleOptions": "openOnSessionStart", + "workspace": "${workspaceFolder}", + "startup": "${workspaceFolder}/Main.hs", + "startupFunc": "", + "startupArgs": "", + "stopOnEntry": false, + "mainArgs": "", + "ghciPrompt": "H>>= ", + "ghciInitialPrompt": "Prelude>", + "ghciCmd": "cabal exec -- ghci-dap --interactive -i -i${workspaceFolder}", + "ghciEnv": {}, + "logFile": "${workspaceFolder}/.vscode/phoityne.log", + "logLevel": "WARNING", + "forceInspect": false + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..c7efda6 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,50 @@ + +{ + // Automatically created by phoityne-vscode extension. + + "version": "2.0.0", + "presentation": { + "reveal": "always", + "panel": "new" + }, + "tasks": [ + { + // F7 + "group": { + "kind": "build", + "isDefault": true + }, + "label": "haskell build", + "type": "shell", + //"command": "cabal configure && cabal build" + "command": "stack build" + }, + { + // F6 + "group": "build", + "type": "shell", + "label": "haskell clean & build", + //"command": "cabal clean && cabal configure && cabal build" + "command": "stack clean && stack build" + //"command": "stack clean ; stack build" // for powershell + }, + { + // F8 + "group": { + "kind": "test", + "isDefault": true + }, + "type": "shell", + "label": "haskell test", + //"command": "cabal test" + "command": "stack test" + }, + { + // F6 + "isBackground": true, + "type": "shell", + "label": "haskell watch", + "command": "stack build --test --no-run-tests --file-watch" + } + ] +} diff --git a/README.md b/README.md index eb406d7..a561b0c 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell - Use `ghcup` to install `stack 2.9.3`, `HLS 2.2.0.0`, `GHC 9.2.8`, and `cabal 3.6.2.0`. - Use `stack run ` to run the program (for example, `stack run example/1`). +## To edit + +I recommend using VSCodium, which is preconfigured to have syntax highlighting and (currently broken) debugging features and will automatically suggest the Haskell extensions to install. + ## Known bugs ### Building diff --git a/main/Eval/Expr.hs b/main/Eval/Expr.hs index c8016fe..e4fc440 100644 --- a/main/Eval/Expr.hs +++ b/main/Eval/Expr.hs @@ -7,7 +7,8 @@ eval (Lit x) = x eval (Add x y) = eval x + eval y eval (Sub x y) = eval x - eval y eval (Mul x y) = eval x * eval y -eval (Div x y) = eval x `div` eval y + +-- eval (Div x y) = eval x `div` eval y evalExpr :: Expr -> Int evalExpr = eval \ No newline at end of file diff --git a/main/LLVMGen/Expr.hs b/main/LLVMGen/Expr.hs index 78d89b8..35736e4 100644 --- a/main/LLVMGen/Expr.hs +++ b/main/LLVMGen/Expr.hs @@ -1,11 +1,14 @@ {-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecursiveDo #-} -- see https://gh.sudoer.ch/danieljharvey/mimsa/blob/trunk/llvm-calc/src/Calc/Compile/ToLLVM.hs module LLVMGen.Expr (getLLVMStr) where +import Control.Monad.IO.Class import Data.Text.Lazy +import Debug.Trace import LLVM.AST hiding (function) import LLVM.AST.Type import LLVM.IRBuilder.Constant @@ -15,19 +18,20 @@ import LLVM.IRBuilder.Monad import LLVM.Pretty import Types.Expr as Expr --- charStar :: LLVM.Type --- charStar = LLVM.ptr LLVM.i8 - getLLVM :: Expr -> Module getLLVM expr = - buildModule "program" $ do - -- TODO: better naming - printf <- externVarArgs "printf" [ptr] i32 -- or LLVM.ptr LLVM.i8 + buildModule "program" $ mdo + -- TODO: better module name + printf <- externVarArgs "printf" [ptr] i32 + -- let printf = extern "printf" [(ptr)] i32 let numFormatStr = globalStringPtr "%d\n" (mkName "str") - function "main" [] i32 $ \_ -> do + function "main" [] i32 $ \_ -> mdo ourExpression <- exprToLLVM expr nfs <- numFormatStr - _ <- call i32 printf [(ConstantOperand nfs, []), (ourExpression, [])] + traceShow ourExpression $ pure () + -- llvmCode <- moduleLLVMAssembly + -- liftIO $ putStrLn llvmCode + _ <- call (FunctionType i32 [i32] False) printf [(ConstantOperand nfs, []), (ourExpression, [])] ret (int32 0) exprToLLVM :: @@ -37,15 +41,15 @@ exprToLLVM :: Expr -> m Operand exprToLLVM (Lit prim) = pure $ primToLLVM prim -exprToLLVM (Expr.Add a b) = do +exprToLLVM (Expr.Add a b) = mdo lhs <- exprToLLVM a rhs <- exprToLLVM b add lhs rhs -exprToLLVM (Expr.Sub a b) = do +exprToLLVM (Expr.Sub a b) = mdo lhs <- exprToLLVM a rhs <- exprToLLVM b sub lhs rhs -exprToLLVM (Expr.Mul a b) = do +exprToLLVM (Expr.Mul a b) = mdo lhs <- exprToLLVM a rhs <- exprToLLVM b mul lhs rhs diff --git a/main/Main.hs b/main/Main.hs index 642cc99..3805b0b 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -22,4 +22,5 @@ main = do contents <- readFile fileName let result = getResult contents print result - T.putStrLn (getLLVMStr (getRight (parseExpr contents))) + let parsed = getRight (parseExpr contents) + T.putStrLn (getLLVMStr parsed) diff --git a/main/Parser/Expr.hs b/main/Parser/Expr.hs index a2f3f4c..0e5a720 100644 --- a/main/Parser/Expr.hs +++ b/main/Parser/Expr.hs @@ -27,8 +27,8 @@ term = Lit <$> intParser table :: [[Operator Parser Expr]] table = - [ [ binaryOp "*" Mul, - binaryOp "/" Div + [ [ binaryOp "*" Mul + -- binaryOp "/" Div ], [ binaryOp "+" Add, binaryOp "-" Sub diff --git a/main/Types/Expr.hs b/main/Types/Expr.hs index f6c3dee..1736090 100644 --- a/main/Types/Expr.hs +++ b/main/Types/Expr.hs @@ -5,5 +5,5 @@ data Expr | Add Expr Expr | Sub Expr Expr | Mul Expr Expr - | Div Expr Expr - deriving (Show) \ No newline at end of file + deriving (-- | Div Expr Expr + Show) \ No newline at end of file From 5fc26a7acd400cd499b611a33be727d10b59979b Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 02:02:34 -0500 Subject: [PATCH 05/10] Reorganize program, removing unnecessary code --- main/Compiler/ExeGen.hs | 1 + main/{LLVMGen/Expr.hs => Compiler/LLVMGen.hs} | 17 ++--- main/Eval/Expr.hs | 14 ---- main/LLVMGen/Expr.hs.old | 74 ------------------- main/Main.hs | 11 +-- really-bad-compiler-in-haskell.cabal | 4 +- 6 files changed, 11 insertions(+), 110 deletions(-) create mode 100644 main/Compiler/ExeGen.hs rename main/{LLVMGen/Expr.hs => Compiler/LLVMGen.hs} (73%) delete mode 100644 main/Eval/Expr.hs delete mode 100644 main/LLVMGen/Expr.hs.old diff --git a/main/Compiler/ExeGen.hs b/main/Compiler/ExeGen.hs new file mode 100644 index 0000000..d35f82e --- /dev/null +++ b/main/Compiler/ExeGen.hs @@ -0,0 +1 @@ +module Compiler.ExeGen () where diff --git a/main/LLVMGen/Expr.hs b/main/Compiler/LLVMGen.hs similarity index 73% rename from main/LLVMGen/Expr.hs rename to main/Compiler/LLVMGen.hs index 35736e4..14d0431 100644 --- a/main/LLVMGen/Expr.hs +++ b/main/Compiler/LLVMGen.hs @@ -4,11 +4,9 @@ -- see https://gh.sudoer.ch/danieljharvey/mimsa/blob/trunk/llvm-calc/src/Calc/Compile/ToLLVM.hs -module LLVMGen.Expr (getLLVMStr) where +module Compiler.LLVMGen (llvmGen) where -import Control.Monad.IO.Class import Data.Text.Lazy -import Debug.Trace import LLVM.AST hiding (function) import LLVM.AST.Type import LLVM.IRBuilder.Constant @@ -23,15 +21,10 @@ getLLVM expr = buildModule "program" $ mdo -- TODO: better module name printf <- externVarArgs "printf" [ptr] i32 - -- let printf = extern "printf" [(ptr)] i32 - let numFormatStr = globalStringPtr "%d\n" (mkName "str") function "main" [] i32 $ \_ -> mdo + numFormatStr <- globalStringPtr "%d\n" (mkName "str") ourExpression <- exprToLLVM expr - nfs <- numFormatStr - traceShow ourExpression $ pure () - -- llvmCode <- moduleLLVMAssembly - -- liftIO $ putStrLn llvmCode - _ <- call (FunctionType i32 [i32] False) printf [(ConstantOperand nfs, []), (ourExpression, [])] + _ <- call (FunctionType i32 [i32] False) printf [(ConstantOperand numFormatStr, []), (ourExpression, [])] ret (int32 0) exprToLLVM :: @@ -57,5 +50,5 @@ exprToLLVM (Expr.Mul a b) = mdo primToLLVM :: Int -> Operand primToLLVM i = int32 (fromIntegral i) -getLLVMStr :: Expr -> Text -getLLVMStr expr = ppllvm (getLLVM expr) \ No newline at end of file +llvmGen :: Expr -> Text +llvmGen expr = ppllvm (getLLVM expr) \ No newline at end of file diff --git a/main/Eval/Expr.hs b/main/Eval/Expr.hs deleted file mode 100644 index e4fc440..0000000 --- a/main/Eval/Expr.hs +++ /dev/null @@ -1,14 +0,0 @@ -module Eval.Expr (evalExpr) where - -import Types.Expr - -eval :: Expr -> Int -eval (Lit x) = x -eval (Add x y) = eval x + eval y -eval (Sub x y) = eval x - eval y -eval (Mul x y) = eval x * eval y - --- eval (Div x y) = eval x `div` eval y - -evalExpr :: Expr -> Int -evalExpr = eval \ No newline at end of file diff --git a/main/LLVMGen/Expr.hs.old b/main/LLVMGen/Expr.hs.old deleted file mode 100644 index fac2110..0000000 --- a/main/LLVMGen/Expr.hs.old +++ /dev/null @@ -1,74 +0,0 @@ -module LLVMGen.Expr (getLLVM) where - -import qualified Objects.Expr as Expr - -import LLVM.AST -import qualified LLVM.AST as AST -import LLVM.AST.Global -import LLVM.AST.Constant -import LLVM.AST.Type -import LLVM.AST.Name -import LLVM.Context -import LLVM.Module - -import Data.ByteString.Char8 as BS - -int :: Type -int = IntegerType 32 - -defMain :: Definition -defMain = GlobalDefinition functionDefaults - { name = Name "main" - , parameters = - ( [] - , False ) - , returnType = int - , basicBlocks = [body] - } - where - body = BasicBlock - (Name "entry") - [ Name "calltmp" := - Call - { tailCallKind = Nothing - , function = Right (ConstantOperand (GlobalReference (PointerType (FunctionType int [int, int] False) defaultAddrSpace) (Name "add"))) - , arguments = [ (ConstantOperand (Int 32 10), []), (ConstantOperand (Int 32 20), []) ] - } - ] - (Do $ Ret (Just (ConstantOperand (Int 32 0))) []) - -defAdd :: Definition -defAdd = GlobalDefinition functionDefaults - { name = Name "add" - , parameters = - ( [ Parameter int (Name "a") [] - , Parameter int (Name "b") [] ] - , False ) - , returnType = int - , basicBlocks = [body] - } - where - body = BasicBlock - (Name "entry") - [ Name "result" := - AST.Add False -- no signed wrap - False -- no unsigned wrap - (LocalReference int (Name "a")) - (LocalReference int (Name "b")) - []] - (Do $ Ret (Just (LocalReference int (Name "result"))) []) - -module_ :: AST.Module -module_ = defaultModule - { moduleName = "basic" - , moduleDefinitions = [defMain, defAdd] - } - - -toLLVM :: AST.Module -> IO () -toLLVM modul = withContext $ \ctx -> do - llvm <- withModuleFromAST ctx modul moduleLLVMAssembly - BS.putStrLn llvm - -getLLVM :: IO () -getLLVM = toLLVM module_ \ No newline at end of file diff --git a/main/Main.hs b/main/Main.hs index 3805b0b..d2669c1 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -3,9 +3,9 @@ module Main (main) where +-- import Compiler.ExeGen +import Compiler.LLVMGen import Data.Text.Lazy.IO qualified as T -import Eval.Expr -import LLVMGen.Expr import Parser.Expr import System.Environment import Types.Expr @@ -13,14 +13,9 @@ import Types.Expr getRight :: ParseResult -> Expr getRight (Right r) = r -getResult :: String -> Int -getResult str = evalExpr (getRight (parseExpr str)) -- TODO: add error messages - main :: IO () main = do fileName <- fmap head getArgs contents <- readFile fileName - let result = getResult contents - print result let parsed = getRight (parseExpr contents) - T.putStrLn (getLLVMStr parsed) + T.putStrLn (llvmGen parsed) diff --git a/really-bad-compiler-in-haskell.cabal b/really-bad-compiler-in-haskell.cabal index 8d3b947..fe722e3 100644 --- a/really-bad-compiler-in-haskell.cabal +++ b/really-bad-compiler-in-haskell.cabal @@ -16,8 +16,8 @@ tested-with: executable really-bad-compiler-in-haskell main-is: Main.hs other-modules: - Eval.Expr - LLVMGen.Expr + Compiler.ExeGen + Compiler.LLVMGen Parser.Expr Types.Expr Paths_really_bad_compiler_in_haskell From c296d15f8565ec6b8511f2a9d5e77f52c56b4d57 Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 02:26:49 -0500 Subject: [PATCH 06/10] Write llvm to file --- .gitignore | 2 ++ main/Main.hs | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4c9e245..1078bf3 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,5 @@ cabal.project.local cabal.project.local~ .HTF/ .ghc.environment.* +a.out +a.out.ll \ No newline at end of file diff --git a/main/Main.hs b/main/Main.hs index d2669c1..4b954d9 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -5,6 +5,7 @@ module Main (main) where -- import Compiler.ExeGen import Compiler.LLVMGen +import Data.Text.Lazy qualified as L import Data.Text.Lazy.IO qualified as T import Parser.Expr import System.Environment @@ -17,5 +18,9 @@ main :: IO () main = do fileName <- fmap head getArgs contents <- readFile fileName + T.putStrLn "- Parsing file..." let parsed = getRight (parseExpr contents) - T.putStrLn (llvmGen parsed) + T.putStrLn "- Generating LLVM to './a.out.ll'..." + let llvm = llvmGen parsed + writeFile "a.out.ll" (L.unpack llvm) + T.putStrLn "- Done." From a9549210a75f98f40bbbcf50fdb28b09313fee8e Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 05:17:12 -0500 Subject: [PATCH 07/10] Compile to binary executable file --- README.md | 2 +- main/Compiler/ExeGen.hs | 1 - main/Compiler/LLVMGen.hs | 21 ++++++++++++++++----- main/Main.hs | 8 +++++--- main/Types/Expr.hs | 6 ++++-- package.yaml | 5 +++-- really-bad-compiler-in-haskell.cabal | 4 ++-- stack.yaml | 2 +- stack.yaml.lock | 13 +++++++++++++ 9 files changed, 45 insertions(+), 17 deletions(-) delete mode 100644 main/Compiler/ExeGen.hs diff --git a/README.md b/README.md index a561b0c..06e499b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ I recommend using VSCodium, which is preconfigured to have syntax highlighting a - Language: Haskell - Haskell tools: GHCup, Stack, Cabal, GHC 9.2 -- Libraries: megaparsec, parser-combinators, text, llvm-hs-pure 15, llvm-hs-pretty-15 +- Libraries: megaparsec, parser-combinators, text, process, llvm-hs-pure 15, llvm-hs-pretty-15 - Dependencies: llvm 15, clang 15 - IDE: VSCodium - Git platform: Forgejo diff --git a/main/Compiler/ExeGen.hs b/main/Compiler/ExeGen.hs deleted file mode 100644 index d35f82e..0000000 --- a/main/Compiler/ExeGen.hs +++ /dev/null @@ -1 +0,0 @@ -module Compiler.ExeGen () where diff --git a/main/Compiler/LLVMGen.hs b/main/Compiler/LLVMGen.hs index 14d0431..648abee 100644 --- a/main/Compiler/LLVMGen.hs +++ b/main/Compiler/LLVMGen.hs @@ -6,14 +6,18 @@ module Compiler.LLVMGen (llvmGen) where -import Data.Text.Lazy +-- import LLVM.Pretty + +import Data.ByteString (ByteString) +import Debug.Trace +import LLVM (moduleLLVMAssembly, withModuleFromAST, writeLLVMAssemblyToFile) import LLVM.AST hiding (function) import LLVM.AST.Type +import LLVM.Context import LLVM.IRBuilder.Constant import LLVM.IRBuilder.Instruction import LLVM.IRBuilder.Module import LLVM.IRBuilder.Monad -import LLVM.Pretty import Types.Expr as Expr getLLVM :: Expr -> Module @@ -23,8 +27,10 @@ getLLVM expr = printf <- externVarArgs "printf" [ptr] i32 function "main" [] i32 $ \_ -> mdo numFormatStr <- globalStringPtr "%d\n" (mkName "str") + traceShow numFormatStr $ pure () ourExpression <- exprToLLVM expr - _ <- call (FunctionType i32 [i32] False) printf [(ConstantOperand numFormatStr, []), (ourExpression, [])] + -- _ <- call (FunctionType i32 [i32]) + _ <- call (FunctionType i32 [ptr] True) printf [(ConstantOperand numFormatStr, []), (ourExpression, [])] ret (int32 0) exprToLLVM :: @@ -50,5 +56,10 @@ exprToLLVM (Expr.Mul a b) = mdo primToLLVM :: Int -> Operand primToLLVM i = int32 (fromIntegral i) -llvmGen :: Expr -> Text -llvmGen expr = ppllvm (getLLVM expr) \ No newline at end of file +llvmGen :: Expr -> IO ByteString +llvmGen expr = do + let l = getLLVM expr + withContext + ( \c -> + withModuleFromAST c l moduleLLVMAssembly + ) \ No newline at end of file diff --git a/main/Main.hs b/main/Main.hs index 4b954d9..dda57c6 100644 --- a/main/Main.hs +++ b/main/Main.hs @@ -5,10 +5,11 @@ module Main (main) where -- import Compiler.ExeGen import Compiler.LLVMGen -import Data.Text.Lazy qualified as L +import Data.ByteString.Char8 qualified as B import Data.Text.Lazy.IO qualified as T import Parser.Expr import System.Environment +import System.Process import Types.Expr getRight :: ParseResult -> Expr @@ -21,6 +22,7 @@ main = do T.putStrLn "- Parsing file..." let parsed = getRight (parseExpr contents) T.putStrLn "- Generating LLVM to './a.out.ll'..." - let llvm = llvmGen parsed - writeFile "a.out.ll" (L.unpack llvm) + llvmGen parsed >>= B.writeFile "a.out.ll" + T.putStrLn "- Compiling to executable './a.out'..." + callCommand "clang a.out.ll" T.putStrLn "- Done." diff --git a/main/Types/Expr.hs b/main/Types/Expr.hs index 1736090..23e75e9 100644 --- a/main/Types/Expr.hs +++ b/main/Types/Expr.hs @@ -5,5 +5,7 @@ data Expr | Add Expr Expr | Sub Expr Expr | Mul Expr Expr - deriving (-- | Div Expr Expr - Show) \ No newline at end of file + deriving + ( -- | Div Expr Expr + Show + ) \ No newline at end of file diff --git a/package.yaml b/package.yaml index ff881a5..a8b1fbb 100644 --- a/package.yaml +++ b/package.yaml @@ -6,9 +6,10 @@ dependencies: - megaparsec >= 9.0.1 && < 10 - parser-combinators - text - # - llvm-hs >= 15 && < 16 + - process + - llvm-hs >= 15 && < 16 - llvm-hs-pure >= 15 && < 16 - - llvm-hs-pretty >= 15 && < 16 + # - llvm-hs-pretty >= 15 && < 16 - bytestring tested-with: GHC == 9.2.8 category: Compilers/Interpreters diff --git a/really-bad-compiler-in-haskell.cabal b/really-bad-compiler-in-haskell.cabal index fe722e3..d82f626 100644 --- a/really-bad-compiler-in-haskell.cabal +++ b/really-bad-compiler-in-haskell.cabal @@ -16,7 +16,6 @@ tested-with: executable really-bad-compiler-in-haskell main-is: Main.hs other-modules: - Compiler.ExeGen Compiler.LLVMGen Parser.Expr Types.Expr @@ -29,9 +28,10 @@ executable really-bad-compiler-in-haskell build-depends: base >=4.14.3 && <5 , bytestring - , llvm-hs-pretty ==15.* + , llvm-hs ==15.* , llvm-hs-pure ==15.* , megaparsec >=9.0.1 && <10 , parser-combinators + , process , text default-language: Haskell2010 diff --git a/stack.yaml b/stack.yaml index 7070a4e..14ef8ca 100644 --- a/stack.yaml +++ b/stack.yaml @@ -9,7 +9,7 @@ extra-deps: commit: 5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76 subdirs: - llvm-hs-pure - # - llvm-hs + - llvm-hs nix: enable: true packages: [llvm_15, clang_15, libxml2] diff --git a/stack.yaml.lock b/stack.yaml.lock index f76a1f2..62ed61b 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -28,6 +28,19 @@ packages: original: subdir: llvm-hs-pure url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz +- completed: + name: llvm-hs + pantry-tree: + sha256: 21f74a6f51fae6c0a0fcf3e6620a59f341289ac743998b41ed3276fd1b7d8862 + size: 12716 + sha256: 526b67e2da9ce25b3856c221b6772e699a7593dbb5ba38e7ee2436349de70966 + size: 9802209 + subdir: llvm-hs + url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz + version: 15.0.0 + original: + subdir: llvm-hs + url: https://github.com/llvm-hs/llvm-hs/archive/5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76.tar.gz snapshots: - completed: sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2 From 0b915f57880918d9e8b02e42be99ef85a41622f8 Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 05:18:31 -0500 Subject: [PATCH 08/10] Remove llvm-hs-pretty since it was generating broken code --- README.md | 2 +- package.yaml | 1 - stack.yaml | 2 -- stack.yaml.lock | 11 ----------- 4 files changed, 1 insertion(+), 15 deletions(-) diff --git a/README.md b/README.md index 06e499b..e8d45a9 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ I recommend using VSCodium, which is preconfigured to have syntax highlighting a - Language: Haskell - Haskell tools: GHCup, Stack, Cabal, GHC 9.2 -- Libraries: megaparsec, parser-combinators, text, process, llvm-hs-pure 15, llvm-hs-pretty-15 +- Libraries: megaparsec, parser-combinators, text, process, llvm-hs 15, llvm-hs-pure 15, - Dependencies: llvm 15, clang 15 - IDE: VSCodium - Git platform: Forgejo diff --git a/package.yaml b/package.yaml index a8b1fbb..99c82b0 100644 --- a/package.yaml +++ b/package.yaml @@ -9,7 +9,6 @@ dependencies: - process - llvm-hs >= 15 && < 16 - llvm-hs-pure >= 15 && < 16 - # - llvm-hs-pretty >= 15 && < 16 - bytestring tested-with: GHC == 9.2.8 category: Compilers/Interpreters diff --git a/stack.yaml b/stack.yaml index 14ef8ca..45dc800 100644 --- a/stack.yaml +++ b/stack.yaml @@ -3,8 +3,6 @@ resolver: lts-20.26 packages: - . extra-deps: - - github: hyunsooda/llvm-hs-pretty-15 - commit: 79283942d1667168ecd65237667aff7fed730303 - github: llvm-hs/llvm-hs commit: 5bca2c1a2a3aa98ecfb19181e7a5ebbf3e212b76 subdirs: diff --git a/stack.yaml.lock b/stack.yaml.lock index 62ed61b..0055e8d 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -4,17 +4,6 @@ # https://docs.haskellstack.org/en/stable/lock_files packages: -- completed: - name: llvm-hs-pretty - pantry-tree: - sha256: 22ac4a47e1833dece52af7a6f8589958021d67292f6cc3de015ecb7c699db62d - size: 5197 - sha256: 8348b72a61807414ad15e0b7e82a7753e4473701e7ab98520c2e9d9a51c5ed7f - size: 43787 - url: https://github.com/hyunsooda/llvm-hs-pretty-15/archive/79283942d1667168ecd65237667aff7fed730303.tar.gz - version: 15.0.0 - original: - url: https://github.com/hyunsooda/llvm-hs-pretty-15/archive/79283942d1667168ecd65237667aff7fed730303.tar.gz - completed: name: llvm-hs-pure pantry-tree: From 08e684206e39e1bfe0cd296ac4647141644b6d9f Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 05:21:50 -0500 Subject: [PATCH 09/10] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e8d45a9..e6b3a8f 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ # Really Bad Compiler in Haskell -A compiler written in Haskell which can currently perform basic arithmetic. Currently using the megaparsec and llvm-hs-\* libraries, but I plan to reimplement parsing and llvm generation myself. Built for the Introduction to Compiler Design class at The University of Texas at Dallas. +A compiler written in Haskell which can currently perform basic arithmetic. Currently using the megaparsec and llvm-hs-\* libraries, but I may reimplement certain libraries myself. Built for the Introduction to Compiler Design class at The University of Texas at Dallas. Main repo: https://git.sudoer.ch/me/really-bad-compiler-in-haskell -## Build Instructions +## Setup Instructions - Install `ghcup` (for managing Haskell tools) and `nix` (for managing external dependencies). - Clone the repo. - Use `ghcup` to install `stack 2.9.3`, `HLS 2.2.0.0`, `GHC 9.2.8`, and `cabal 3.6.2.0`. + +## Run Instructions + - Use `stack run ` to run the program (for example, `stack run example/1`). +- The LLVM will be generated as `a.out.ll`, and the executable will be generated as `a.out`. ## To edit From b89be8de8c2d9c974ff6c1cf15de1fed7b695108 Mon Sep 17 00:00:00 2001 From: sudoer777 Date: Fri, 29 Sep 2023 05:31:33 -0500 Subject: [PATCH 10/10] Add division --- main/Compiler/LLVMGen.hs | 6 ++++-- main/Parser/Expr.hs | 4 ++-- main/Types/Expr.hs | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/main/Compiler/LLVMGen.hs b/main/Compiler/LLVMGen.hs index 648abee..d36277d 100644 --- a/main/Compiler/LLVMGen.hs +++ b/main/Compiler/LLVMGen.hs @@ -27,9 +27,7 @@ getLLVM expr = printf <- externVarArgs "printf" [ptr] i32 function "main" [] i32 $ \_ -> mdo numFormatStr <- globalStringPtr "%d\n" (mkName "str") - traceShow numFormatStr $ pure () ourExpression <- exprToLLVM expr - -- _ <- call (FunctionType i32 [i32]) _ <- call (FunctionType i32 [ptr] True) printf [(ConstantOperand numFormatStr, []), (ourExpression, [])] ret (int32 0) @@ -52,6 +50,10 @@ exprToLLVM (Expr.Mul a b) = mdo lhs <- exprToLLVM a rhs <- exprToLLVM b mul lhs rhs +exprToLLVM (Expr.Div a b) = mdo + lhs <- exprToLLVM a + rhs <- exprToLLVM b + sdiv lhs rhs primToLLVM :: Int -> Operand primToLLVM i = int32 (fromIntegral i) diff --git a/main/Parser/Expr.hs b/main/Parser/Expr.hs index 0e5a720..a2f3f4c 100644 --- a/main/Parser/Expr.hs +++ b/main/Parser/Expr.hs @@ -27,8 +27,8 @@ term = Lit <$> intParser table :: [[Operator Parser Expr]] table = - [ [ binaryOp "*" Mul - -- binaryOp "/" Div + [ [ binaryOp "*" Mul, + binaryOp "/" Div ], [ binaryOp "+" Add, binaryOp "-" Sub diff --git a/main/Types/Expr.hs b/main/Types/Expr.hs index 23e75e9..51c8925 100644 --- a/main/Types/Expr.hs +++ b/main/Types/Expr.hs @@ -5,7 +5,7 @@ data Expr | Add Expr Expr | Sub Expr Expr | Mul Expr Expr + | Div Expr Expr deriving - ( -- | Div Expr Expr - Show + ( Show ) \ No newline at end of file