Generate code for functions and variables
authorLuke Lau <luke_lau@icloud.com>
Sat, 18 May 2019 23:23:31 +0000 (00:23 +0100)
committerLuke Lau <luke_lau@icloud.com>
Sun, 19 May 2019 13:17:16 +0000 (14:17 +0100)
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

diff --git a/Main.hs b/Main.hs
index ca6629ab447cd64b7c8748eec07ffa7fe6b34e9d..2eae262967be844fff1886ac2d34318912b17e53 100644 (file)
--- 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