module Language.Scheme.Compiler
(
compile
, compileApply
, compileBlock
, compileDivertedVars
, compileExpr
, compileLambdaList
, compileLisp
, compileScalar
, compileSpecialForm
, compileSpecialFormBody
, compileSpecialFormEntryPoint
, defineLambdaVars
, defineTopLevelVars
, divertVars
, initializeCompiler
, isPrim
, mcompile
, mfunc
)
where
import Language.Scheme.Compiler.Libraries as LSCL
import Language.Scheme.Compiler.Types
import qualified Language.Scheme.Core as LSC
(apply, evalLisp, findFileOrLib)
import qualified Language.Scheme.Macro
import Language.Scheme.Primitives
import Language.Scheme.Types
import Language.Scheme.Variables
import Control.Monad.Error
import qualified Data.List
import Data.Maybe (fromMaybe)
initializeCompiler :: Env -> IOThrowsError [HaskAST]
initializeCompiler env = do
_ <- defineNamespacedVar env 't' "imports" $ List []
return []
compileLisp
:: Env
-> String
-> String
-> Maybe String
-> IOThrowsError [HaskAST]
compileLisp env filename entryPoint exitPoint = do
filename' <- LSC.findFileOrLib filename
ast <- load filename' >>= compileBlock entryPoint exitPoint env []
case ast of
[] -> compileScalar
" return $ Number 0" $
CompileOptions entryPoint False False exitPoint
_ -> return ast
compileBlock :: String -> Maybe String -> Env -> [HaskAST] -> [LispVal]
-> IOThrowsError [HaskAST]
compileBlock symThisFunc symLastFunc env result lisps = do
_ <- defineTopLevelVars env lisps
_compileBlock symThisFunc symLastFunc env result lisps
_compileBlock :: String -> Maybe String -> Env -> [HaskAST] -> [LispVal]
-> IOThrowsError [HaskAST]
_compileBlock symThisFunc symLastFunc env result [c] = do
let copts = CompileOptions symThisFunc False False symLastFunc
compiled <- mcompile env c copts
case compiled of
[val@(AstValue _)] -> do
comp <- compileScalar' val copts
_compileBlockDo return result comp
[val@(AstRef _)] -> do
comp <- compileScalar' val copts
_compileBlockDo return result comp
_ -> _compileBlockDo return result compiled
_compileBlock symThisFunc symLastFunc env result
(c@(List [Atom "%husk-switch-to-parent-environment"]) : cs) = do
let parEnv = fromMaybe env (parentEnv env)
_ <- defineTopLevelVars parEnv cs
Atom symNextFunc <- _gensym "f"
compiled <- mcompile env c $
CompileOptions symThisFunc False False (Just symNextFunc)
_compileBlockDo
(\ result' ->
_compileBlock
(if isSingleValue compiled
then symThisFunc
else symNextFunc)
symLastFunc
parEnv result' cs)
result
compiled
_compileBlock symThisFunc symLastFunc env result (c:cs) = do
Atom symNextFunc <- _gensym "f"
compiled <- mcompile env c $
CompileOptions symThisFunc False False (Just symNextFunc)
_compileBlockDo
(\ result' ->
_compileBlock
(if isSingleValue compiled
then symThisFunc
else symNextFunc)
symLastFunc
env result' cs)
result
compiled
_compileBlock _ _ _ result [] = return result
_compileBlockDo :: ([HaskAST] -> IOThrowsError [HaskAST]) ->
[HaskAST] -> [HaskAST] -> IOThrowsError [HaskAST]
_compileBlockDo fnc result c =
case c of
[AstValue _] -> fnc result
[AstRef _] -> fnc result
_ -> fnc $ result ++ c
compileScalar :: String -> CompOpts -> IOThrowsError [HaskAST]
compileScalar val copts = do
f <- return $ AstAssignM "x1" $ AstValue val
c <- return $ createAstCont copts "x1" ""
return [createAstFunc copts [f, c]]
compileScalar' :: HaskAST -> CompOpts -> IOThrowsError [HaskAST]
compileScalar' val copts = do
let fCode = case val of
AstValue v -> AstValue $ " let x1 = " ++ v
AstRef r -> AstValue $ " x1 <- " ++ r
_ -> AstValue $ "Unexpected compiler error in compileScalar' "
f <- return $ fCode
c <- return $ createAstCont copts "x1" ""
return [createAstFunc copts [f, c]]
compileLambdaList :: [LispVal] -> IOThrowsError String
compileLambdaList l = do
serialized <- mapM serialize l
return $ "[" ++ Data.List.intercalate "," serialized ++ "]"
where serialize (Atom a) = return $ (show a)
serialize a = throwError $ Default $
"invalid parameter to lambda list: " ++ show a
defineLambdaVars :: Env -> [LispVal] -> IOThrowsError LispVal
defineLambdaVars env (Atom v : vs) = do
_ <- defineVar env v $ Number 0
defineLambdaVars env vs
defineLambdaVars env (_ : vs) = defineLambdaVars env vs
defineLambdaVars _ [] = return $ Nil ""
defineTopLevelVars :: Env -> [LispVal] -> IOThrowsError LispVal
defineTopLevelVars env (List [Atom "define", Atom var, _] : ls) = do
_ <- defineTopLevelVar env var
defineTopLevelVars env ls
defineTopLevelVars env ((List (Atom "define" : List (Atom var : _) : _)) : ls) = do
_ <- defineTopLevelVar env var
defineTopLevelVars env ls
defineTopLevelVars env ((List (Atom "define" : DottedList (Atom var : _) _ : _)) : ls) = do
_ <- defineTopLevelVar env var
defineTopLevelVars env ls
defineTopLevelVars env (_ : ls) = defineTopLevelVars env ls
defineTopLevelVars _ _ = return nullLisp
defineTopLevelVar :: Env -> String -> IOThrowsError LispVal
defineTopLevelVar env var = do
defineVar env var $ Number 0
compile :: Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST]
compile env
(List (Atom "import" : mods))
copts@(CompileOptions {}) = do
LispEnv meta <- getVar env "*meta-env*"
LSCL.importAll env
meta
mods
(CompileLibraryOptions compileBlock compileLisp)
copts
compile _ (Nil n) _ = return [AstValue $ "Nil " ++ (show n)]
compile _ v@(String _) _ = return [AstValue $ ast2Str v]
compile _ v@(Char _) _ = return [AstValue $ ast2Str v]
compile _ v@(Complex _) _ = return [AstValue $ ast2Str v]
compile _ v@(Float _) _ = return [AstValue $ ast2Str v]
compile _ v@(Rational _) _ = return [AstValue $ ast2Str v]
compile _ v@(Number _) _ = return [AstValue $ ast2Str v]
compile _ v@(Bool _) _ = return [AstValue $ ast2Str v]
compile _ v@(Vector _) _ = return [AstValue $ ast2Str v]
compile _ v@(ByteVector _) _ = return [AstValue $ ast2Str v]
compile _ ht@(HashTable _) _ = return [AstValue $ ast2Str ht]
compile env (Atom a) _ = do
isDefined <- liftIO $ isRecBound env a
case isDefined of
True -> do
return [AstRef $ "getRTVar env \"" ++ a ++ "\""]
False -> throwError $ UnboundVar "Variable is not defined" a
compile _ (List [Atom "quote", val]) copts =
compileScalar (" return $ " ++ ast2Str val) copts
compile env ast@(List [Atom "expand", _body]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
val <- Language.Scheme.Macro.expand env False _body LSC.apply
compileScalar (" return $ " ++ ast2Str val) copts)
compile env ast@(List (Atom "let-syntax" : List _bindings : _body))
copts@(CompileOptions thisFnc a b nextFnc) = do
compileSpecialFormBody env ast copts (\ _ -> do
bodyEnv <- liftIO $ extendEnv env []
_ <- Language.Scheme.Macro.loadMacros env bodyEnv Nothing False _bindings
expanded <- Language.Scheme.Macro.expand bodyEnv False (List _body) LSC.apply
Atom loadMacroSym <- _gensym "loadMacroStub"
stub <- compileScalar (" Language.Scheme.Macro.loadMacros env env Nothing False " ++ (asts2Str _bindings)) (CompileOptions thisFnc False False (Just loadMacroSym))
rest <- divertVars bodyEnv expanded (CompileOptions loadMacroSym a b nextFnc) compexp
return $ stub ++ rest)
where
compexp bodyEnv' expanded' copts' = do
case expanded' of
List e -> compile bodyEnv' (List $ Atom "begin" : e) copts'
e -> compile bodyEnv' e copts'
compile env ast@(List (Atom "letrec-syntax" : List _bindings : _body))
copts@(CompileOptions thisFnc a b nextFnc) = do
compileSpecialFormBody env ast copts (\ _ -> do
bodyEnv <- liftIO $ extendEnv env []
_ <- Language.Scheme.Macro.loadMacros bodyEnv bodyEnv Nothing False _bindings
expanded <- Language.Scheme.Macro.expand bodyEnv False (List _body) LSC.apply
Atom loadMacroSym <- _gensym "loadMacroStub"
stub <- compileScalar (" Language.Scheme.Macro.loadMacros env env Nothing False " ++ (asts2Str _bindings)) (CompileOptions thisFnc False False (Just loadMacroSym))
rest <- divertVars bodyEnv expanded (CompileOptions loadMacroSym a b nextFnc) compexp
return $ stub ++ rest)
where
compexp bodyEnv' expanded' copts' = do
case expanded' of
List e -> compile bodyEnv' (List $ Atom "begin" : e) copts'
e -> compile bodyEnv' e copts'
compile env
(List [Atom "define-syntax",
Atom newKeyword,
Atom keyword])
copts = do
bound <- getNamespacedVar' env macroNamespace keyword
case bound of
Just m -> do
_ <- defineNamespacedVar env macroNamespace newKeyword m
compFunc <- return $ [
AstValue $ " bound <- getNamespacedVar' env macroNamespace \"" ++
keyword ++ "\"",
AstValue $ " case bound of ",
AstValue $ " Just m -> ",
AstValue $ " defineNamespacedVar env macroNamespace \"" ++
newKeyword ++ "\" m",
AstValue $ " Nothing -> throwError $ TypeMismatch \"macro\" $ " ++
"Atom \"" ++ keyword ++ "\"",
createAstCont copts "(Nil \"\")" ""]
return $ [createAstFunc copts compFunc]
Nothing -> throwError $ TypeMismatch "macro" $ Atom keyword
compile env ast@(List [Atom "define-syntax", Atom keyword,
(List [Atom "er-macro-transformer",
(List (Atom "lambda" : List fparams : fbody))])])
copts = do
_ <- validateFuncParams fparams (Just 3)
compileSpecialFormBody env ast copts (\ _ -> do
let fparamsStr = asts2Str fparams
fbodyStr = asts2Str fbody
f <- makeNormalFunc env fparams fbody
_ <- defineNamespacedVar env macroNamespace keyword $ SyntaxExplicitRenaming f
compFunc <- return $ [
AstValue $ " f <- makeNormalFunc env " ++ fparamsStr ++ " " ++ fbodyStr,
AstValue $ " defineNamespacedVar env macroNamespace \"" ++ keyword ++
"\" $ SyntaxExplicitRenaming f",
createAstCont copts "(Nil \"\")" ""]
return $ [createAstFunc copts compFunc])
compile env lisp@(List [Atom "define-syntax", Atom keyword,
(List (Atom "syntax-rules" : Atom ellipsis : (List identifiers : rules)))]) copts = do
compileSpecialFormBody env lisp copts (\ _ -> do
let idStr = asts2Str identifiers
ruleStr = asts2Str rules
_ <- defineNamespacedVar env macroNamespace keyword $
Syntax (Just env) Nothing False ellipsis identifiers rules
compileScalar
(" defineNamespacedVar env macroNamespace \"" ++ keyword ++
"\" $ Syntax (Just env) Nothing False \"" ++ ellipsis ++ "\" " ++ idStr ++ " " ++ ruleStr) copts)
compile env lisp@(List [Atom "define-syntax", Atom keyword,
(List (Atom "syntax-rules" : (List identifiers : rules)))]) copts = do
compileSpecialFormBody env lisp copts (\ _ -> do
let idStr = asts2Str identifiers
ruleStr = asts2Str rules
_ <- defineNamespacedVar env macroNamespace keyword $
Syntax (Just env) Nothing False "..." identifiers rules
compileScalar
(" defineNamespacedVar env macroNamespace \"" ++ keyword ++
"\" $ Syntax (Just env) Nothing False \"...\" " ++ idStr ++ " " ++ ruleStr) copts)
compile env ast@(List [Atom "if", predic, conseq]) copts =
compileSpecialFormBody env ast copts (\ _ -> do
compile env (List [Atom "if", predic, conseq, Nil ""]) copts)
compile env ast@(List [Atom "if", predic, conseq, alt]) copts = do
compileSpecialFormBody env ast copts (\ nextFunc -> do
Atom symPredicate <- _gensym "ifPredic"
Atom symCheckPredicate <- _gensym "compiledIfPredicate"
Atom symConsequence <- _gensym "compiledConsequence"
Atom symAlternate <- _gensym "compiledAlternative"
f <- return [AstValue $ " " ++ symPredicate ++
" env (makeCPSWArgs env cont " ++ symCheckPredicate ++ " []) " ++
" (Nil \"\") (Just []) "]
compPredicate <- wrapObject symPredicate Nothing =<<
compileExpr
env predic symPredicate
Nothing
compConsequence <- wrapObject symConsequence nextFunc =<<
compileExpr
env conseq symConsequence
nextFunc
compAlternate <- wrapObject symAlternate nextFunc =<<
compileExpr
env alt symAlternate
nextFunc
compCheckPredicate <- return $ AstFunction symCheckPredicate " env cont result _ " [
AstValue $ " case result of ",
AstValue $ " Bool False -> " ++ symAlternate ++ " env cont (Nil \"\") (Just []) ",
AstValue $ " _ -> " ++ symConsequence ++ " env cont (Nil \"\") (Just []) "]
return $ [createAstFunc copts f] ++ compPredicate ++ [compCheckPredicate] ++
compConsequence ++ compAlternate)
compile env ast@(List [Atom "set!", Atom var, form]) copts@(CompileOptions {}) = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symDefine <- _gensym "setFunc"
Atom symMakeDefine <- _gensym "setFuncMakeSet"
_ <- setVar env var form
compDefine <- compileExpr env form symDefine $ Just symMakeDefine
case compDefine of
[(AstValue val)] -> do
return [createAstFunc copts [
AstValue $ " result <- setVar env \"" ++ var ++ "\" $ " ++ val,
createAstCont copts "result" ""]]
[(AstRef val)] -> do
return [createAstFunc copts [
AstValue $ " result <- setVar env \"" ++ var ++ "\" =<< " ++ val,
createAstCont copts "result" ""]]
_ -> do
entryPt <- compileSpecialFormEntryPoint "set!" symDefine copts
compMakeDefine <- return $ AstFunction symMakeDefine " env cont result _ " [
AstValue $ " _ <- setVar env \"" ++ var ++ "\" result",
createAstCont copts "result" ""]
return $ [entryPt] ++ compDefine ++ [compMakeDefine])
compile env ast@(List [Atom "set!", nonvar, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set!" ("throwError $ NumArgs 2 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "define", Atom var, form]) copts@(CompileOptions {}) = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symDefine <- _gensym "defineFuncDefine"
Atom symMakeDefine <- _gensym "defineFuncMakeDef"
_ <- defineVar env var form
_ <- case form of
List [Atom "current-environment"] ->
defineVar env var $ LispEnv env
_ -> return $ Nil ""
compDefine <- compileExpr env form symDefine $ Just symMakeDefine
case compDefine of
[(AstValue val)] -> do
return [createAstFunc copts [
AstValue $ " result <- defineVar env \"" ++ var ++ "\" $ " ++ val,
createAstCont copts "result" ""]]
[(AstRef val)] -> do
return [createAstFunc copts [
AstValue $ " result <- defineVar env \"" ++ var ++ "\" =<< " ++ val,
createAstCont copts "result" ""]]
_ -> do
f <- return $ [
AstValue $ " " ++ symDefine ++ " env cont (Nil \"\") (Just [])" ]
compMakeDefine <- return $ AstFunction symMakeDefine " env cont result _ " [
AstValue $ " _ <- defineVar env \"" ++ var ++ "\" result",
createAstCont copts "result" ""]
return $ [createAstFunc copts f] ++ compDefine ++ [compMakeDefine])
compile env ast@(List (Atom "define" : List (Atom var : fparams) : fbody))
copts@(CompileOptions {}) = do
_ <- validateFuncParams fparams Nothing
compileSpecialFormBody env ast copts (\ _ -> do
bodyEnv <- liftIO $ extendEnv env []
_ <- defineLambdaVars bodyEnv (Atom var : fparams)
Atom symCallfunc <- _gensym "defineFuncEntryPt"
compiledParams <- compileLambdaList fparams
compiledBody <- compileBlock symCallfunc Nothing bodyEnv [] fbody
ebody <- mapM (\ lisp -> Language.Scheme.Macro.macroEval env lisp LSC.apply) fbody
_ <- makeNormalFunc env fparams ebody >>= defineVar env var
f <- return $ [
AstValue $ " result <- makeNormalHFunc env (" ++ compiledParams ++
") " ++ symCallfunc,
AstValue $ " _ <- defineVar env \"" ++ var ++ "\" result ",
createAstCont copts "result" ""
]
return $ (createAstFunc copts f) : compiledBody)
compile env
ast@(List (Atom "define" : DottedList (Atom var : fparams) varargs : fbody))
copts@(CompileOptions {}) = do
_ <- validateFuncParams (fparams ++ [varargs]) Nothing
compileSpecialFormBody env ast copts (\ _ -> do
bodyEnv <- liftIO $ extendEnv env []
_ <- defineLambdaVars bodyEnv $ (Atom var : fparams) ++ [varargs]
Atom symCallfunc <- _gensym "defineFuncEntryPt"
compiledParams <- compileLambdaList fparams
compiledBody <- compileBlock symCallfunc Nothing bodyEnv [] fbody
ebody <- mapM (\ lisp -> Language.Scheme.Macro.macroEval env lisp LSC.apply) fbody
_ <- makeVarargs varargs env fparams ebody >>= defineVar env var
f <- return $ [
AstValue $ " result <- makeHVarargs (" ++ ast2Str varargs ++ ") env (" ++
compiledParams ++ ") " ++ symCallfunc,
AstValue $ " _ <- defineVar env \"" ++ var ++ "\" result ",
createAstCont copts "result" "" ]
return $ (createAstFunc copts f) : compiledBody)
compile env ast@(List (Atom "lambda" : List fparams : fbody))
copts@(CompileOptions {}) = do
_ <- validateFuncParams fparams Nothing
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
compiledParams <- compileLambdaList fparams
bodyEnv <- liftIO $ extendEnv env []
_ <- defineLambdaVars bodyEnv fparams
compiledBody <- compileBlock symCallfunc Nothing bodyEnv [] fbody
f <- return $ [
AstValue $ " result <- makeNormalHFunc env (" ++ compiledParams ++
") " ++ symCallfunc,
createAstCont copts "result" ""
]
return $ (createAstFunc copts f) : compiledBody)
compile env ast@(List (Atom "lambda" : DottedList fparams varargs : fbody))
copts@(CompileOptions {}) = do
_ <- validateFuncParams (fparams ++ [varargs]) Nothing
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
compiledParams <- compileLambdaList fparams
bodyEnv <- liftIO $ extendEnv env []
_ <- defineLambdaVars bodyEnv $ fparams ++ [varargs]
compiledBody <- compileBlock symCallfunc Nothing bodyEnv [] fbody
f <- return $ [
AstValue $ " result <- makeHVarargs (" ++ ast2Str varargs ++ ") env (" ++
compiledParams ++ ") " ++ symCallfunc,
createAstCont copts "result" "" ]
return $ (createAstFunc copts f) : compiledBody)
compile env ast@(List (Atom "lambda" : varargs@(Atom _) : fbody))
copts@(CompileOptions {}) = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
bodyEnv <- liftIO $ extendEnv env []
_ <- defineLambdaVars bodyEnv [varargs]
compiledBody <- compileBlock symCallfunc Nothing bodyEnv [] fbody
f <- return $ [
AstValue $ " result <- makeHVarargs (" ++ ast2Str varargs ++ ") env [] " ++ symCallfunc,
createAstCont copts "result" ""
]
return $ (createAstFunc copts f) : compiledBody)
compile env ast@(List [Atom "string-set!", Atom var, i, character]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symDefine <- _gensym "stringSetFunc"
Atom symMakeDefine <- _gensym "stringSetFuncMakeSet"
Atom symChr <- _gensym "stringSetChar"
Atom symCompiledI <- _gensym "stringI"
entryPt <- compileSpecialFormEntryPoint "string-set!" symChr copts
compChr <- wrapObject symChr (Just symDefine) =<<
compileExpr env character symChr (Just symDefine)
compDefine <- return $ AstFunction symDefine " env cont chr _ " [
AstValue $ " " ++ symCompiledI ++ " env (makeCPSWArgs env cont " ++
symMakeDefine ++ " [chr]) (Nil \"\") (Just []) " ]
compI <- wrapObject symCompiledI Nothing =<<
compileExpr env i symCompiledI Nothing
compMakeDefine <- return $ AstFunction symMakeDefine " env cont idx (Just [chr]) " [
AstValue $ " tmp <- getVar env \"" ++ var ++ "\"",
AstValue $ " derefValue <- recDerefPtrs tmp",
AstValue $ " result <- substr (derefValue, chr, idx)",
AstValue $ " _ <- updateObject env \"" ++ var ++ "\" result",
createAstCont copts "result" ""]
return $ [entryPt, compDefine, compMakeDefine] ++ compI ++ compChr)
compile env ast@(List [Atom "string-set!", nonvar, _, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "string-set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "string-set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "string-set!" ("throwError $ NumArgs 3 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "set-car!", Atom var, argObj]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symGetVar <- _gensym "setCarGetVar"
Atom symCompiledObj <- _gensym "setCarCompiledObj"
Atom symObj <- _gensym "setCarObj"
Atom symDoSet <- _gensym "setCarDoSet"
let finalContinuation = case copts of
(CompileOptions _ _ _ (Just nextFunc)) -> "continueEval' e (makeCPSWArgs e c " ++ nextFunc ++ " [])\n"
_ -> "continueEval' e c\n"
entryPt <- compileSpecialFormEntryPoint "set-car!" symGetVar copts
compGetVar <- return $ AstFunction symGetVar " env cont idx _ " [
AstValue $ " result <- getVar env \"" ++ var ++ "\"",
AstValue $ " derefValue <- recDerefPtrs result",
AstValue $ " " ++ symObj ++ " env cont derefValue (Just []) "]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env argObj symCompiledObj Nothing
compObj <- return $ AstValue $ "" ++
symObj ++ " :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal\n" ++
symObj ++ " _ _ obj@(List []) _ = throwError $ TypeMismatch \"pair\" obj\n" ++
symObj ++ " e c obj@(List (_ : _)) _ = " ++ symCompiledObj ++ " e (makeCPSWArgs e c " ++ symDoSet ++ " [obj]) (Nil \"\") Nothing\n" ++
symObj ++ " e c obj@(DottedList _ _) _ = " ++ symCompiledObj ++ " e (makeCPSWArgs e c " ++ symDoSet ++ " [obj]) (Nil \"\") Nothing\n" ++
symObj ++ " _ _ obj _ = throwError $ TypeMismatch \"pair\" obj\n"
compDoSet <- return $ AstValue $ "" ++
symDoSet ++ " :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal\n" ++
symDoSet ++ " e c obj (Just [List (_ : ls)]) = updateObject e \"" ++ var ++ "\" (List (obj : ls)) >>= " ++ finalContinuation ++
symDoSet ++ " e c obj (Just [DottedList (_ : ls) l]) = updateObject e \"" ++ var ++ "\" (DottedList (obj : ls) l) >>= " ++ finalContinuation ++
symDoSet ++ " _ _ _ _ = throwError $ InternalError \"Unexpected argument to " ++ symDoSet ++ "\"\n"
return $ [entryPt, compGetVar, compObj, compDoSet] ++ compiledObj)
compile env ast@(List [Atom "set-car!", nonvar, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set-car!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "set-car!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set-car!" ("throwError $ NumArgs 2 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "set-cdr!", Atom var, argObj]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symGetVar <- _gensym "setCdrGetVar"
Atom symCompiledObj <- _gensym "setCdrCompiledObj"
Atom symObj <- _gensym "setCdrObj"
Atom symDoSet <- _gensym "setCdrDoSet"
let finalContinuation = case copts of
(CompileOptions _ _ _ (Just nextFunc)) -> "continueEval' e (makeCPSWArgs e c " ++ nextFunc ++ " [])\n"
_ -> "continueEval' e c\n"
entryPt <- compileSpecialFormEntryPoint "set-car!" symGetVar copts
compGetVar <- return $ AstFunction symGetVar " env cont idx _ " [
AstValue $ " result <- getVar env \"" ++ var ++ "\"",
AstValue $ " derefValue <- recDerefPtrs result",
AstValue $ " " ++ symObj ++ " env cont derefValue (Just []) "]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env argObj symCompiledObj Nothing
compObj <- return $ AstValue $ "" ++
symObj ++ " :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal\n" ++
symObj ++ " _ _ obj@(List []) _ = throwError $ TypeMismatch \"pair\" obj\n" ++
symObj ++ " e c obj@(List (_ : _)) _ = " ++ symCompiledObj ++ " e (makeCPSWArgs e c " ++ symDoSet ++ " [obj]) (Nil \"\") Nothing\n" ++
symObj ++ " e c obj@(DottedList _ _) _ = " ++ symCompiledObj ++ " e (makeCPSWArgs e c " ++ symDoSet ++ " [obj]) (Nil \"\") Nothing\n" ++
symObj ++ " _ _ obj _ = throwError $ TypeMismatch \"pair\" obj\n"
compDoSet <- return $ AstValue $ "" ++
symDoSet ++ " :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal\n" ++
symDoSet ++ " e c obj (Just [List (l : _)]) = do\n" ++
" l' <- recDerefPtrs l\n" ++
" obj' <- recDerefPtrs obj\n" ++
" (cons [l', obj']) >>= updateObject e \"" ++ var ++ "\" >>= " ++ finalContinuation ++
symDoSet ++ " e c obj (Just [DottedList (l : _) _]) = do\n" ++
" l' <- recDerefPtrs l\n" ++
" obj' <- recDerefPtrs obj\n" ++
" (cons [l', obj']) >>= updateObject e \"" ++ var ++ "\" >>= " ++ finalContinuation ++
symDoSet ++ " _ _ _ _ = throwError $ InternalError \"Unexpected argument to " ++ symDoSet ++ "\"\n"
return $ [entryPt, compGetVar, compObj, compDoSet] ++ compiledObj)
compile env ast@(List [Atom "set-cdr!", nonvar, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set-cdr!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "set-cdr!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "set-cdr!" ("throwError $ NumArgs 2 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "list-set!", Atom var, i, object]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCompiledIdx <- _gensym "listSetIdx"
Atom symCompiledObj <- _gensym "listSetObj"
Atom symUpdateVec <- _gensym "listSetUpdate"
Atom symIdxWrapper <- _gensym "listSetIdxWrapper"
entryPt <- compileSpecialFormEntryPoint "list-set!" symCompiledIdx copts
compiledIdx <- wrapObject symCompiledIdx (Just symIdxWrapper) =<<
compileExpr env i symCompiledIdx (Just symIdxWrapper)
compiledIdxWrapper <- return $ AstFunction symIdxWrapper " env cont idx _ " [
AstValue $ " " ++ symCompiledObj ++ " env (makeCPSWArgs env cont " ++ symUpdateVec ++ " [idx]) (Nil \"\") (Just []) " ]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env object symCompiledObj Nothing
compiledUpdate <- return $ AstFunction symUpdateVec " env cont obj (Just [idx]) " [
AstValue $ " vec <- getVar env \"" ++ var ++ "\"",
AstValue $ " result <- updateList vec idx obj >>= updateObject env \"" ++ var ++ "\"",
createAstCont copts "result" ""]
return $ [entryPt, compiledIdxWrapper, compiledUpdate] ++ compiledIdx ++ compiledObj)
compile env ast@(List [Atom "list-set!", nonvar, _, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "list-set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "list-set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "list-set!" ("throwError $ NumArgs 3 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "vector-set!", Atom var, i, object]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCompiledIdx <- _gensym "vectorSetIdx"
Atom symCompiledObj <- _gensym "vectorSetObj"
Atom symUpdateVec <- _gensym "vectorSetUpdate"
Atom symIdxWrapper <- _gensym "vectorSetIdxWrapper"
entryPt <- compileSpecialFormEntryPoint "vector-set!" symCompiledIdx copts
compiledIdx <- wrapObject symCompiledIdx (Just symIdxWrapper) =<<
compileExpr env i symCompiledIdx (Just symIdxWrapper)
compiledIdxWrapper <- return $ AstFunction symIdxWrapper " env cont idx _ " [
AstValue $ " " ++ symCompiledObj ++ " env (makeCPSWArgs env cont " ++ symUpdateVec ++ " [idx]) (Nil \"\") (Just []) " ]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env object symCompiledObj Nothing
compiledUpdate <- return $ AstFunction symUpdateVec " env cont obj (Just [idx]) " [
AstValue $ " vec <- getVar env \"" ++ var ++ "\"",
AstValue $ " result <- updateVector vec idx obj >>= updateObject env \"" ++ var ++ "\"",
createAstCont copts "result" ""]
return $ [entryPt, compiledIdxWrapper, compiledUpdate] ++ compiledIdx ++ compiledObj)
compile env ast@(List [Atom "vector-set!", nonvar, _, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "vector-set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "vector-set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "vector-set!" ("throwError $ NumArgs 3 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "bytevector-u8-set!", Atom var, i, object]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCompiledIdx <- _gensym "bytevectorSetIdx"
Atom symCompiledObj <- _gensym "bytevectorSetObj"
Atom symUpdateVec <- _gensym "bytevectorSetUpdate"
Atom symIdxWrapper <- _gensym "bytevectorSetIdxWrapper"
entryPt <- compileSpecialFormEntryPoint "bytevector-u8-set!" symCompiledIdx copts
compiledIdx <- wrapObject symCompiledIdx (Just symIdxWrapper) =<<
compileExpr env i symCompiledIdx (Just symIdxWrapper)
compiledIdxWrapper <- return $ AstFunction symIdxWrapper " env cont idx _ " [
AstValue $ " " ++ symCompiledObj ++ " env (makeCPSWArgs env cont " ++ symUpdateVec ++ " [idx]) (Nil \"\") (Just []) " ]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env object symCompiledObj Nothing
compiledUpdate <- return $ AstFunction symUpdateVec " env cont obj (Just [idx]) " [
AstValue $ " vec <- getVar env \"" ++ var ++ "\"",
AstValue $ " result <- updateByteVector vec idx obj >>= updateObject env \"" ++ var ++ "\"",
createAstCont copts "result" ""]
return $ [entryPt, compiledIdxWrapper, compiledUpdate] ++ compiledIdx ++ compiledObj)
compile env ast@(List [Atom "bytevector-u8-set!", nonvar, _, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "bytevector-u8-set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "bytevector-u8-set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "bytevector-u8-set!" ("throwError $ NumArgs 3 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "hash-table-set!", Atom var, rkey, rvalue]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCompiledIdx <- _gensym "hashTableSetIdx"
Atom symCompiledObj <- _gensym "hashTableSetObj"
Atom symUpdateVec <- _gensym "hashTableSetUpdate"
Atom symIdxWrapper <- _gensym "hashTableSetIdxWrapper"
entryPt <- compileSpecialFormEntryPoint "hash-table-set!" symCompiledIdx copts
compiledIdx <- wrapObject symCompiledIdx (Just symIdxWrapper) =<<
compileExpr env rkey symCompiledIdx (Just symIdxWrapper)
compiledIdxWrapper <- return $ AstFunction symIdxWrapper " env cont idx _ " [
AstValue $ " " ++ symCompiledObj ++ " env (makeCPSWArgs env cont " ++ symUpdateVec ++ " [idx]) (Nil \"\") (Just []) " ]
compiledObj <- wrapObject symCompiledObj Nothing =<<
compileExpr env rvalue symCompiledObj Nothing
compiledUpdate <- return $ AstFunction symUpdateVec " env cont obj (Just [rkey]) " [
AstValue $ " HashTable ht <- getVar env \"" ++ var ++ "\"",
AstValue $ " HashTable ht' <- recDerefPtrs $ HashTable ht",
AstValue $ " result <- updateObject env \"" ++ var ++ "\" (HashTable $ Data.Map.insert rkey obj ht') ",
createAstCont copts "result" ""]
return $ [entryPt, compiledIdxWrapper, compiledUpdate] ++ compiledIdx ++ compiledObj)
compile env ast@(List [Atom "hash-table-set!", nonvar, _, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "hash-table-set!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "hash-table-set!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "hash-table-set!" ("throwError $ NumArgs 3 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List [Atom "hash-table-delete!", Atom var, rkey]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
Atom symCompiledIdx <- _gensym "hashTableDeleteIdx"
Atom symDoDelete <- _gensym "hashTableDelete"
entryPt <- compileSpecialFormEntryPoint "hash-table-delete!" symCompiledIdx copts
compiledIdx <- wrapObject symCompiledIdx (Just symDoDelete) =<<
compileExpr env rkey symCompiledIdx (Just symDoDelete)
compiledUpdate <- return $ AstFunction symDoDelete " env cont rkey _ " [
AstValue $ " HashTable ht <- getVar env \"" ++ var ++ "\"",
AstValue $ " HashTable ht' <- recDerefPtrs $ HashTable ht",
AstValue $ " result <- updateObject env \"" ++ var ++ "\" (HashTable $ Data.Map.delete rkey ht') ",
createAstCont copts "result" ""]
return $ [entryPt, compiledUpdate] ++ compiledIdx)
compile env ast@(List [Atom "hash-table-delete!", nonvar, _]) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "hash-table-delete!" ("throwError $ TypeMismatch \"variable\"" ++
" $ String \"" ++ (show nonvar) ++ "\"") copts
return [f])
compile env ast@(List (Atom "hash-table-delete!" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
f <- compileSpecialForm "hash-table-delete!" ("throwError $ NumArgs 2 $ [String \"" ++
(show args) ++ "\"]") copts
return [f])
compile env ast@(List (Atom "%import" : args)) copts = do
compileSpecialFormBody env ast copts (\ _ -> do
throwError $ NotImplemented $ "%import, with args: " ++ show args)
compile env (List [a@(Atom "husk-interpreter?")]) copts = do
mfunc env (List [a, Bool True]) compile copts
compile env args@(List [Atom "load", filename, envSpec]) copts = do
fname <- LSC.evalLisp env filename
case fname of
String fn -> compileFile fn
_ -> mfunc env args compileApply copts
where
compileFile filename' = do
Atom symEnv <- _gensym "loadEnv"
Atom symLoad <- _gensym "load"
compEnv <- wrapObject symEnv Nothing =<<
compileExpr env envSpec symEnv
Nothing
env' <- case envSpec of
Atom a -> do
v <- getVar env a
case v of
LispEnv e -> return e
_ -> return env
_ -> return env
compLoad <- compileLisp env' filename' symLoad Nothing
f <- return $ [
AstValue $ " LispEnv e <- " ++ symEnv ++ " env (makeNullContinuation env) (Nil \"\") (Just []) ",
AstValue $ " result <- " ++ symLoad ++ " e (makeNullContinuation e) (Nil \"\") Nothing",
createAstCont copts "result" ""]
return $ [createAstFunc copts f] ++ compEnv ++ compLoad
compile env (List [Atom "load", filename]) copts = do
String filename' <- LSC.evalLisp env filename
Atom symEntryPt <- _gensym "load"
result <- compileLisp env filename' symEntryPt Nothing
return $ result ++
[createAstFunc copts [
AstValue $ " result <- " ++ symEntryPt ++
" env (makeNullContinuation env) (Nil \"\") Nothing",
createAstCont copts "result" ""]]
compile env (List [Atom "load-ffi",
String moduleName,
String externalFuncName,
String internalFuncName]) copts = do
List l <- getNamespacedVar env 't' "imports"
_ <- if String moduleName `notElem` l
then setNamespacedVar env 't' "imports" $
List $ l ++ [String moduleName]
else return $ String ""
return [createAstFunc copts [
AstValue $ " result <- defineVar env \"" ++
internalFuncName ++ "\" $ IOFunc " ++
moduleName ++ "." ++ externalFuncName,
createAstCont copts "result" ""]]
compile env args@(List (_ : _)) copts = mfunc env args compileApply copts
compile _ badForm _ = throwError $ BadSpecialForm "Unrecognized special form" badForm
mcompile :: Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST]
mcompile env lisp = mfunc env lisp compile
mfunc :: Env
-> LispVal
-> (Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST])
-> CompOpts
-> IOThrowsError [HaskAST]
mfunc env lisp func copts = do
expanded <- Language.Scheme.Macro.macroEval env lisp LSC.apply
divertVars env expanded copts func
divertVars
:: Env
-> LispVal
-> CompOpts
-> (Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST])
-> IOThrowsError [HaskAST]
divertVars env expanded copts@(CompileOptions _ uvar uargs nfnc) func = do
vars <- Language.Scheme.Macro.getDivertedVars env
case vars of
[] -> func env expanded copts
_ -> do
Atom symNext <- _gensym "afterDivert"
diverted <- compileDivertedVars symNext env vars copts
rest <- wrapObject symNext nfnc =<<
func env expanded (CompileOptions symNext uvar uargs nfnc)
return $ diverted : rest
compileDivertedVars :: String -> Env -> [LispVal] -> CompOpts -> IOThrowsError HaskAST
compileDivertedVars
formNext _ vars
copts@(CompileOptions _ useVal useArgs _) = do
let val = case useVal of
True -> "value"
_ -> "Nil \"\""
args = case useArgs of
True -> "(Just args)"
_ -> "(Just [])"
comp (List [Atom renamed, Atom orig]) = do
[AstValue $ " v <- getVar env \"" ++ orig ++ "\"",
AstValue $ " _ <- defineVar env \"" ++ renamed ++ "\" v"]
comp _ = []
cvars = map comp vars
f = (concat cvars) ++
[AstValue $ " " ++ formNext ++ " env cont (" ++ val ++ ") " ++ args]
return $ createAstFunc copts f
compileSpecialFormEntryPoint :: String -> String -> CompOpts -> IOThrowsError HaskAST
compileSpecialFormEntryPoint formName formSym copts = do
compileSpecialForm formName ("" ++ formSym ++ " env cont (Nil \"\") (Just [])") copts
compileSpecialForm :: String -> String -> CompOpts -> IOThrowsError HaskAST
compileSpecialForm _ formCode copts = do
f <- return $ [
AstValue $ " " ++ formCode]
return $ createAstFunc copts f
compileSpecialFormBody :: Env
-> LispVal
-> CompOpts
-> (Maybe String -> ErrorT LispError IO [HaskAST])
-> ErrorT LispError IO [HaskAST]
compileSpecialFormBody env
ast@(List (Atom fnc : _))
copts@(CompileOptions _ _ _ nextFunc)
spForm = do
isDefined <- liftIO $ isRecBound env fnc
case isDefined of
True -> mfunc env ast compileApply copts
False -> spForm nextFunc
compileSpecialFormBody _ _ _ _ = throwError $ InternalError "compileSpecialFormBody"
compileExpr :: Env -> LispVal -> String -> Maybe String -> IOThrowsError [HaskAST]
compileExpr env expr symThisFunc fForNextExpr = do
mcompile env expr (CompileOptions symThisFunc False False fForNextExpr)
compileApply :: Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST]
compileApply env (List (func : fparams)) copts@(CompileOptions coptsThis _ _ coptsNext) = do
_ <- case func of
List _ -> return $ Nil ""
Atom _ -> return $ Nil ""
_ -> throwError $ BadSpecialForm "Unable to evaluate form" $ List (func : fparams)
primitive <- isPrim env func
let literals = collectLiterals fparams
nonFunctionCalls = collectLiteralsAndVars fparams
case (primitive, literals, nonFunctionCalls) of
(Just primFunc, Just ls, _) -> do
result <- LSC.apply
(makeNullContinuation env)
primFunc
ls
return $ [createAstFunc copts [
AstValue $ " let result = " ++ (ast2Str result),
createAstCont copts "result" ""]]
(_, _, Just ls) -> compileFuncLitArgs ls
_ -> compileAllArgs func
where
compileFuncLitArgs args = do
let pack (Atom p : ps) strs vars i = do
let varName = 'v' : show i
pack ps
(strs ++ [varName])
(vars ++ [(p, varName)])
(i + 1)
pack (p : ps) strs vars i =
pack ps
(strs ++ [ast2Str p])
vars
i
pack [] strs vars _ = (strs, vars)
let (paramStrs, vars) = pack args [] [] (0::Int)
_compileFuncLitArgs func vars $ "[" ++ joinL paramStrs "," ++ "]"
_compileFuncLitArgs fnc vars args = do
Atom stubFunc <- _gensym "applyStubF"
Atom nextFunc <- _gensym "applyNextF"
let varLines =
map (\ (rt, cp) ->
AstValue $ " " ++ cp ++ " <- getRTVar env \"" ++ rt ++ "\"")
vars
rest <- case coptsNext of
Nothing -> return $ [
AstFunction nextFunc
" env cont value _ " $ varLines ++
[AstValue $ " apply cont value " ++ args]]
Just fnextExpr -> return $ [
AstFunction nextFunc
" env cont value _ " $ varLines ++
[AstValue $ " apply (makeCPSWArgs env cont " ++
fnextExpr ++ " []) value " ++ args]]
_comp <- mcompile env fnc $ CompileOptions stubFunc False False Nothing
case _comp of
[(AstValue val)] -> do
return $ [createAstFunc
(CompileOptions coptsThis False False Nothing) [
AstValue $ " let var = " ++ val,
AstValue $ " " ++ nextFunc ++ " env cont var Nothing"]] ++ rest
[(AstRef val)] -> do
return $ [createAstFunc
(CompileOptions coptsThis False False Nothing) [
AstValue $ " var <- " ++ val,
AstValue $ " " ++ nextFunc ++ " env cont var Nothing"]] ++ rest
_ -> do
c <- return $
AstFunction coptsThis " env cont _ _ " [
AstValue $ " " ++ stubFunc ++ " env (makeCPSWArgs env cont " ++
nextFunc ++ " []) (Nil \"\") (Just [])"]
return $ [c] ++ _comp ++ rest
compileAllArgs (Atom fncName) = do
rest <- case fparams of
[] -> do
throwError $ Default $ " unreachable code in compileAllArgs for " ++ fncName
_ -> compileArgs coptsThis True (Just fncName) fparams
return $ rest
compileAllArgs func' = do
Atom stubFunc <- _gensym "applyStubF"
Atom wrapperFunc <- _gensym "applyWrapper"
Atom nextFunc <- _gensym "applyNextF"
wrapper <- return $
AstFunction wrapperFunc " env cont value _ " [
AstValue $ " " ++ nextFunc ++ " env cont " ++
" (Nil \"\") (Just [value]) "]
rest <- case fparams of
[] -> do
return [AstFunction
nextFunc
" env cont (Nil _) (Just (a:as)) "
[AstValue $ " apply " ++ applyCont ++ " a as "],
AstFunction
nextFunc
" env cont value (Just (a:as)) "
[AstValue $ " apply " ++ applyCont ++ " a $ as ++ [value] "]]
_ -> compileArgs nextFunc False Nothing fparams
_comp <- mcompile env func' $ CompileOptions stubFunc False False Nothing
case _comp of
[(AstValue val)] -> do
return $ [createAstFunc
(CompileOptions coptsThis False False Nothing) [
AstValue $ " let var = " ++ val,
AstValue $ " " ++ wrapperFunc ++ " env cont var Nothing"]] ++ rest
[(AstRef val)] -> do
return $ [createAstFunc
(CompileOptions coptsThis False False Nothing) [
AstValue $ " var <- " ++ val,
AstValue $ " " ++ wrapperFunc ++ " env cont var Nothing"]] ++ rest
_ -> do
c <- return $
AstFunction coptsThis " env cont _ _ " [
AstValue $ " " ++ stubFunc ++ " env (makeCPSWArgs env cont " ++
wrapperFunc ++ " []) (Nil \"\") (Just [])"]
return $ [c, wrapper ] ++ _comp ++ rest
applyCont :: String
applyCont = case coptsNext of
Nothing -> "cont"
Just fnextExpr -> "(makeCPSWArgs env cont " ++ fnextExpr ++ " [])"
compileArgs :: String -> Bool -> (Maybe String) -> [LispVal] -> IOThrowsError [HaskAST]
compileArgs thisFunc thisFuncUseValue maybeFnc args = do
case args of
(a:as) -> do
let (asRest, asLiterals) = (as, [])
let lastArg = null asRest
Atom stubFunc <- _gensym "applyFirstArg"
Atom nextFunc <- do
case lastArg of
True -> return $ Atom "applyWrapper"
_ -> _gensym "applyNextArg"
fnc <- case maybeFnc of
Just fncName -> do
var <- compileInlineVar env fncName "value"
return [var]
_ -> return []
let fargs = if thisFuncUseValue
then " env cont value (Just args) "
else " env cont _ (Just args) "
rest <- case lastArg of
True -> return []
_ -> compileArgs nextFunc True Nothing asRest
let nextCont' = case (lastArg, coptsNext) of
(True, Just fnextExpr) -> "(makeCPSWArgs env cont " ++ fnextExpr ++ " [])"
_ -> "cont"
let literalArgs = asts2Str asLiterals
let argsCode = case thisFuncUseValue of
True -> " $ args ++ [value] ++ " ++ literalArgs ++ ") "
False -> " $ args ++ " ++ literalArgs ++ ") "
_comp <- mcompile env a $ CompileOptions stubFunc thisFuncUseValue False Nothing
case _comp of
[(AstValue val)] -> do
c <- do
return [AstValue $ " let var = " ++ val,
AstValue $ " " ++ nextFunc ++ " env " ++ nextCont' ++ " var (Just " ++ argsCode]
return $ [AstFunction thisFunc fargs (fnc ++ c)] ++ rest
[(AstRef val)] -> do
c <- do
return [AstValue $ " var <- " ++ val,
AstValue $ " " ++ nextFunc ++ " env " ++ nextCont' ++ " var (Just " ++ argsCode]
return $ [AstFunction thisFunc fargs (fnc ++ c)] ++ rest
_ -> do
let c = AstValue $
" continueEval' env (makeCPSWArgs env (makeCPSWArgs env " ++
nextCont' ++ " " ++ nextFunc ++ argsCode ++ stubFunc ++
" []) $ Nil\"\""
return $ [AstFunction thisFunc fargs (fnc ++ [c])] ++ _comp ++ rest
_ -> throwError $ TypeMismatch "nonempty list" $ List args
compileApply _ err _ = do
throwError $ Default $ "compileApply - Unexpected argument: " ++ show err
isPrim :: Env -> LispVal -> IOThrowsError (Maybe LispVal)
isPrim env (Atom func) = do
val <- getVar env func >>= recDerefPtrs
case val of
p@(PrimitiveFunc _) -> return $ Just p
_ -> return Nothing
isPrim _ p@(PrimitiveFunc _) = return $ Just p
isPrim _ _ = return Nothing
_collectLiterals :: [LispVal] -> [LispVal] -> Bool -> (Maybe [LispVal])
_collectLiterals (List _ : _) _ _ = Nothing
_collectLiterals (Atom _ : _) _ False = Nothing
_collectLiterals (a : as) nfs varFlag = _collectLiterals as (a : nfs) varFlag
_collectLiterals [] nfs _ = Just $ reverse nfs
collectLiterals, collectLiteralsAndVars :: [LispVal] -> (Maybe [LispVal])
collectLiteralsAndVars args = _collectLiterals args [] True
collectLiterals args = _collectLiterals args [] False
compileInlineVar :: Env -> String -> String -> IOThrowsError HaskAST
compileInlineVar env a hsName = do
isDefined <- liftIO $ isRecBound env a
case isDefined of
True -> return $ AstValue $ " " ++ hsName ++ " <- getRTVar env \"" ++ a ++ "\""
False -> throwError $ UnboundVar "Variable is not defined" a
isSingleValue :: [HaskAST] -> Bool
isSingleValue [(AstValue _)] = True
isSingleValue [(AstRef _)] = True
isSingleValue _ = False
wrapObject :: String
-> Maybe String -> [HaskAST] -> IOThrowsError [HaskAST]
wrapObject thisF nextF es = do
case es of
[val@(AstValue _)] -> compileScalar' val $ CompileOptions thisF False False nextF
[val@(AstRef _)] -> compileScalar' val $ CompileOptions thisF False False nextF
_ -> return es