From 8cd4f6315dc3efd76822337e935b7d465a134a5e Mon Sep 17 00:00:00 2001 From: Luke Lau Date: Sun, 19 May 2019 00:23:31 +0100 Subject: [PATCH] Generate code for functions and variables Now that we're generating functions, variables can now be bound. This means we will have to somehow keep track of what variables are available in scope (i.e. passed to us in 'funciton'), so we've wrapped our IRBuilderT in a ReaderT (Map String Operand). For now if the variable doesn't exist in scope, we just crash the program. But later on we will introduce a mechanism for errors, and tidy up the transformer stack. --- Main.hs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Main.hs b/Main.hs index ca6629a..2eae262 100644 --- a/Main.hs +++ b/Main.hs @@ -2,7 +2,10 @@ import AST as K -- K for Kaleidoscope import Utils +import Control.Monad.Trans.Reader import Control.Monad.IO.Class +import Data.String +import qualified Data.Map as Map import qualified Data.Text.Lazy.IO as Text import LLVM.AST.Constant import LLVM.AST.Float @@ -28,12 +31,27 @@ repl = do repl where +type Binds = Map.Map String Operand + buildAST :: AST -> ModuleBuilder Operand +buildAST (Function (Prototype nameStr paramStrs) body) = do + let n = fromString nameStr + function n params Type.double $ \ops -> do + let binds = Map.fromList (zip paramStrs ops) + flip runReaderT binds $ buildExpr body >>= ret + where params = zip (repeat Type.double) (map fromString paramStrs) + buildAST (TopLevelExpr x) = function "__anon_expr" [] Type.double $ - const $ buildExpr x >>= ret + const $ flip runReaderT mempty $ buildExpr x >>= ret -buildExpr :: Expr -> IRBuilderT ModuleBuilder Operand +buildExpr :: Expr -> ReaderT Binds (IRBuilderT ModuleBuilder) Operand buildExpr (Num x) = pure $ ConstantOperand (Float (Double x)) +buildExpr (Var n) = do + binds <- ask + case binds Map.!? n of + Just x -> pure x + Nothing -> error $ "'" <> n <> "' doesn't exist in scope" + buildExpr (BinOp op a b) = do opA <- buildExpr a opB <- buildExpr b -- 2.30.2