Created
February 19, 2025 04:48
-
-
Save VictorTaelin/209664d2b8dd4f8db19c4b3c81a0194c to your computer and use it in GitHub Desktop.
AI Prompt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You're a code completion assistant. | |
### | |
-- | |
module HVML.Type where | |
import Data.Map.Strict as MS | |
import Data.Word | |
import Foreign.Ptr | |
-- Core Types | |
-- ---------- | |
--show-- | |
data Core | |
= Var String -- x | |
| Ref String Word64 [Core] -- @fn | |
| Era -- * | |
| Lam String Core -- λx(F) | |
| App Core Core -- (f x) | |
| Sup Word64 Core Core -- &L{a b} | |
| Dup Word64 String String Core Core -- ! &L{a b} = v body | |
| Ctr String [Core] -- #Ctr{a b ...} | |
| Mat Core [(String,Core)] [(String,[String],Core)] -- ~ v { #A{a b ...}: ... #B{a b ...}: ... ... } | |
| U32 Word32 -- 123 | |
| Chr Char -- 'a' | |
| Op2 Oper Core Core -- (+ a b) | |
| Let Mode String Core Core -- ! x = v body | |
deriving (Show, Eq) | |
--show-- | |
data Mode | |
= LAZY | |
| STRI | |
| PARA | |
deriving (Show, Eq, Enum) | |
--show-- | |
data MatchType | |
= Switch | |
| Match | |
| IfLet | |
deriving (Show, Eq, Enum) | |
--show-- | |
data Oper | |
= OP_ADD | OP_SUB | OP_MUL | OP_DIV | |
| OP_MOD | OP_EQ | OP_NE | OP_LT | |
| OP_GT | OP_LTE | OP_GTE | OP_AND | |
| OP_OR | OP_XOR | OP_LSH | OP_RSH | |
deriving (Show, Eq, Enum) | |
--show-- | |
-- A top-level function, including: | |
-- - copy: true when ref-copy mode is enabled | |
-- - args: a list of (isArgStrict, argName) pairs | |
-- - core: the function's body | |
-- Note: ref-copy improves C speed, but increases interaction count | |
type Func = ((Bool, [(Bool,String)]), Core) | |
data Book = Book | |
{ fidToFun :: MS.Map Word64 Func -- function id to Function object | |
, fidToLab :: MS.Map Word64 (MS.Map Word64 ()) -- function id to dup labels used in its body | |
, fidToNam :: MS.Map Word64 String -- function id to name | |
, namToFid :: MS.Map String Word64 -- function name to id | |
, cidToAri :: MS.Map Word64 Word64 -- constructor id to field count (arity) | |
, cidToLen :: MS.Map Word64 Word64 -- constructor id to cases length (ADT constructor count) | |
, cidToCtr :: MS.Map Word64 String -- constructor id to name | |
, ctrToCid :: MS.Map String Word64 -- constructor name to id | |
, cidToADT :: MS.Map Word64 Word64 -- constructor id to ADT id (first cid of its datatype) | |
} deriving (Show, Eq) | |
-- Runtime Types | |
-- ------------- | |
--show-- | |
type Tag = Word64 | |
type Lab = Word64 | |
type Loc = Word64 | |
type Term = Word64 | |
--show-- | |
data TAG | |
= DP0 | |
| DP1 | |
| VAR | |
| ERA | |
| APP | |
| LAM | |
| SUP | |
| SUB | |
| REF | |
| LET | |
| CTR | |
| MAT | |
| IFL | |
| SWI | |
| W32 | |
| CHR | |
| OPX | |
| OPY | |
deriving (Eq, Show) | |
--show-- | |
type HVM = IO | |
--show-- | |
type ReduceAt = Book -> Loc -> HVM Term | |
-- C Functions | |
-- ----------- | |
foreign import ccall unsafe "Runtime.c hvm_init" | |
hvmInit :: IO () | |
foreign import ccall unsafe "Runtime.c hvm_free" | |
hvmFree :: IO () | |
foreign import ccall unsafe "Runtime.c alloc_node" | |
allocNode :: Word64 -> IO Word64 | |
foreign import ccall unsafe "Runtime.c set" | |
set :: Word64 -> Term -> IO () | |
foreign import ccall unsafe "Runtime.c got" | |
got :: Word64 -> IO Term | |
foreign import ccall unsafe "Runtime.c take" | |
take :: Word64 -> IO Term | |
foreign import ccall unsafe "Runtime.c swap" | |
swap :: Word64 -> IO Term | |
foreign import ccall unsafe "Runtime.c term_new" | |
termNew :: Tag -> Lab -> Loc -> Term | |
foreign import ccall unsafe "Runtime.c term_tag" | |
termTag :: Term -> Tag | |
foreign import ccall unsafe "Runtime.c term_get_bit" | |
termGetBit :: Term -> Tag | |
foreign import ccall unsafe "Runtime.c term_lab" | |
termLab :: Term -> Lab | |
foreign import ccall unsafe "Runtime.c term_loc" | |
termLoc :: Term -> Loc | |
foreign import ccall unsafe "Runtime.c term_set_bit" | |
termSetBit :: Term -> Tag | |
foreign import ccall unsafe "Runtime.c term_rem_bit" | |
termRemBit :: Term -> Tag | |
foreign import ccall unsafe "Runtime.c get_len" | |
getLen :: IO Word64 | |
foreign import ccall unsafe "Runtime.c get_itr" | |
getItr :: IO Word64 | |
foreign import ccall unsafe "Runtime.c inc_itr" | |
incItr :: IO Word64 | |
foreign import ccall unsafe "Runtime.c fresh" | |
fresh :: IO Word64 | |
foreign import ccall unsafe "Runtime.c reduce" | |
reduceC :: Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_let" | |
reduceLet :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_app_era" | |
reduceAppEra :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_app_lam" | |
reduceAppLam :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_app_sup" | |
reduceAppSup :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_app_ctr" | |
reduceAppCtr :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_app_w32" | |
reduceAppW32 :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_era" | |
reduceDupEra :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_lam" | |
reduceDupLam :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_sup" | |
reduceDupSup :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_ctr" | |
reduceDupCtr :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_w32" | |
reduceDupW32 :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_dup_ref" | |
reduceDupRef :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_mat_era" | |
reduceMatEra :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_mat_lam" | |
reduceMatLam :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_mat_sup" | |
reduceMatSup :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_mat_ctr" | |
reduceMatCtr :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_mat_w32" | |
reduceMatW32 :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opx_era" | |
reduceOpxEra :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opx_lam" | |
reduceOpxLam :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opx_sup" | |
reduceOpxSup :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opx_ctr" | |
reduceOpxCtr :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opx_w32" | |
reduceOpxW32 :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opy_era" | |
reduceOpyEra :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opy_lam" | |
reduceOpyLam :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opy_sup" | |
reduceOpySup :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opy_ctr" | |
reduceOpyCtr :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_opy_w32" | |
reduceOpyW32 :: Term -> Term -> IO Term | |
foreign import ccall unsafe "Runtime.c reduce_ref_sup" | |
reduceRefSup :: Term -> Word64 -> IO Term | |
foreign import ccall unsafe "Runtime.c hvm_define" | |
hvmDefine :: Word64 -> FunPtr (IO Term) -> IO () | |
foreign import ccall unsafe "Runtime.c hvm_get_state" | |
hvmGetState :: IO (Ptr ()) | |
foreign import ccall unsafe "Runtime.c hvm_set_state" | |
hvmSetState :: Ptr () -> IO () | |
foreign import ccall unsafe "Runtime.c u12v2_new" | |
u12v2New :: Word64 -> Word64 -> Word64 | |
foreign import ccall unsafe "Runtime.c u12v2_x" | |
u12v2X :: Word64 -> Word64 | |
foreign import ccall unsafe "Runtime.c u12v2_y" | |
u12v2Y :: Word64 -> Word64 | |
foreign import ccall unsafe "Runtime.c hvm_set_cari" | |
hvmSetCari :: Word64 -> Word16 -> IO () | |
foreign import ccall unsafe "Runtime.c hvm_set_clen" | |
hvmSetClen :: Word64 -> Word16 -> IO () | |
foreign import ccall unsafe "Runtime.c hvm_set_cadt" | |
hvmSetCadt :: Word64 -> Word16 -> IO () | |
foreign import ccall unsafe "Runtime.c hvm_set_fari" | |
hvmSetFari :: Word64 -> Word16 -> IO () | |
-- Constants | |
-- --------- | |
--show-- | |
tagT :: Tag -> TAG | |
tagT 0x00 = DP0 | |
tagT 0x01 = DP1 | |
tagT 0x02 = VAR | |
tagT 0x03 = SUB | |
tagT 0x04 = REF | |
tagT 0x05 = LET | |
tagT 0x06 = APP | |
tagT 0x08 = MAT | |
tagT 0x09 = IFL | |
tagT 0x0A = SWI | |
tagT 0x0B = OPX | |
tagT 0x0C = OPY | |
tagT 0x0D = ERA | |
tagT 0x0E = LAM | |
tagT 0x0F = SUP | |
tagT 0x10 = CTR | |
tagT 0x11 = W32 | |
tagT 0x12 = CHR | |
tagT tag = error $ "unknown tag: " ++ show tag | |
_DP0_ :: Tag | |
_DP0_ = 0x00 | |
_DP1_ :: Tag | |
_DP1_ = 0x01 | |
_VAR_ :: Tag | |
_VAR_ = 0x02 | |
_SUB_ :: Tag | |
_SUB_ = 0x03 | |
_REF_ :: Tag | |
_REF_ = 0x04 | |
_LET_ :: Tag | |
_LET_ = 0x05 | |
_APP_ :: Tag | |
_APP_ = 0x06 | |
_MAT_ :: Tag | |
_MAT_ = 0x08 | |
_IFL_ :: Tag | |
_IFL_ = 0x09 | |
_SWI_ :: Tag | |
_SWI_ = 0x0A | |
_OPX_ :: Tag | |
_OPX_ = 0x0B | |
_OPY_ :: Tag | |
_OPY_ = 0x0C | |
_ERA_ :: Tag | |
_ERA_ = 0x0D | |
_LAM_ :: Tag | |
_LAM_ = 0x0E | |
_SUP_ :: Tag | |
_SUP_ = 0x0F | |
_CTR_ :: Tag | |
_CTR_ = 0x10 | |
_W32_ :: Tag | |
_W32_ = 0x11 | |
_CHR_ :: Tag | |
_CHR_ = 0x12 | |
--show-- | |
modeT :: Lab -> Mode | |
modeT 0x00 = LAZY | |
modeT 0x01 = STRI | |
modeT 0x02 = PARA | |
modeT mode = error $ "unknown mode: " ++ show mode | |
-- Primitive Functions | |
_DUP_F_ :: Lab | |
_DUP_F_ = 0xFFF | |
_SUP_F_ :: Lab | |
_SUP_F_ = 0xFFE | |
_LOG_F_ :: Lab | |
_LOG_F_ = 0xFFD | |
primitives :: [(String, Lab)] | |
primitives = | |
[ ("SUP", _SUP_F_) | |
, ("DUP", _DUP_F_) | |
, ("LOG", _LOG_F_) | |
] | |
-- Utils | |
-- ----- | |
-- Getter function for maps | |
mget :: (Ord k, Show k) => MS.Map k a -> k -> a | |
mget map key = | |
case MS.lookup key map of | |
Just val -> val | |
Nothing -> error $ "key not found: " ++ show key | |
-- Returns the first constructor ID in a pattern-match | |
matFirstCid :: Book -> Core -> Word64 | |
matFirstCid book (Mat _ _ ((ctr,_,_):_)) = | |
case MS.lookup ctr (ctrToCid book) of | |
Just cid -> cid | |
Nothing -> 0 | |
matFirstCid _ _ = 0 | |
matType :: Book -> Core -> MatchType | |
matType book (Mat _ _ css) = | |
case css of | |
((ctr,_,_):_) | ctr == "0" -> Switch | |
[(ctr,_,_),("_",_,_)] -> IfLet | |
cs | all (\(c,_,_) -> c /= "_") cs -> Match | |
_ -> error "invalid match" | |
matType _ _ = error "not a match" | |
funArity :: Book -> Word64 -> Word64 | |
funArity book fid | |
| fid == _SUP_F_ = 3 | |
| fid == _DUP_F_ = 3 | |
| fid == _LOG_F_ = 1 | |
| otherwise = case MS.lookup fid (fidToFun book) of | |
Just ((_, args), _) -> fromIntegral (length args) | |
Nothing -> error $ "Function ID not found: " ++ show fid | |
-- | |
-- //./Type.hs// | |
module HVML.Inject where | |
import Control.Monad (foldM, when, forM_) | |
import Control.Monad.State | |
import Data.Bits (shiftL, (.|.)) | |
import Data.Char (ord) | |
import Data.List (foldr, take) | |
import Data.Word | |
import Debug.Trace | |
import HVML.Show | |
import HVML.Type | |
import qualified Data.Map.Strict as MS | |
type InjectM a = StateT InjectState HVM a | |
data InjectState = InjectState | |
{ args :: MS.Map String Term -- maps var names to binder locations | |
, vars :: [(String, Loc)] -- list of (var name, usage location) pairs | |
} | |
emptyState :: InjectState | |
emptyState = InjectState MS.empty [] | |
injectCore :: Book -> Core -> Loc -> InjectM () | |
injectCore _ Era loc = do | |
lift $ set loc (termNew _ERA_ 0 0) | |
injectCore _ (Var nam) loc = do | |
argsMap <- gets args | |
case MS.lookup nam argsMap of | |
Just term -> do | |
lift $ set loc term | |
when (head nam /= '&') $ do | |
modify $ \s -> s { args = MS.delete nam (args s) } | |
Nothing -> do | |
modify $ \s -> s { vars = (nam, loc) : vars s } | |
injectCore book (Let mod nam val bod) loc = do | |
let_node <- lift $ allocNode 2 | |
modify $ \s -> s { args = MS.insert nam (termNew _VAR_ 0 (let_node + 0)) (args s) } | |
injectCore book val (let_node + 0) | |
injectCore book bod (let_node + 1) | |
lift $ set loc (termNew _LET_ (fromIntegral $ fromEnum mod) let_node) | |
injectCore book (Lam vr0 bod) loc = do | |
lam <- lift $ allocNode 1 | |
-- lift $ set (lam + 0) (termNew _SUB_ 0 0) | |
modify $ \s -> s { args = MS.insert vr0 (termNew _VAR_ 0 (lam + 0)) (args s) } | |
injectCore book bod (lam + 0) | |
lift $ set loc (termNew _LAM_ 0 lam) | |
injectCore book (App fun arg) loc = do | |
app <- lift $ allocNode 2 | |
injectCore book fun (app + 0) | |
injectCore book arg (app + 1) | |
lift $ set loc (termNew _APP_ 0 app) | |
injectCore book (Sup lab tm0 tm1) loc = do | |
sup <- lift $ allocNode 2 | |
injectCore book tm0 (sup + 0) | |
injectCore book tm1 (sup + 1) | |
lift $ set loc (termNew _SUP_ lab sup) | |
injectCore book (Dup lab dp0 dp1 val bod) loc = do | |
dup <- lift $ allocNode 2 | |
-- lift $ set (dup + 0) (termNew _SUB_ 0 0) | |
lift $ set (dup + 1) (termNew _SUB_ 0 0) | |
modify $ \s -> s | |
{ args = MS.insert dp0 (termNew _DP0_ lab dup) | |
$ MS.insert dp1 (termNew _DP1_ lab dup) (args s) | |
} | |
injectCore book val (dup + 0) | |
injectCore book bod loc | |
injectCore book (Ref nam fid arg) loc = do | |
let ari = funArity book fid | |
ref <- lift $ allocNode (fromIntegral ari) | |
sequence_ [injectCore book x (ref + i) | (i,x) <- zip [0..] arg] | |
lift $ set loc (termNew _REF_ fid ref) | |
injectCore book (Ctr nam fds) loc = do | |
let ari = length fds | |
let cid = mget (ctrToCid book) nam | |
ctr <- lift $ allocNode (fromIntegral ari) | |
sequence_ [injectCore book fd (ctr + ix) | (ix,fd) <- zip [0..] fds] | |
lift $ set loc (termNew _CTR_ cid ctr) | |
injectCore book tm@(Mat val mov css) loc = do | |
typ <- return $ matType book tm | |
mat <- lift $ allocNode (1 + fromIntegral (length css)) | |
injectCore book val (mat + 0) | |
forM_ (zip [0..] css) $ \ (idx, (ctr, fds, bod)) -> do | |
injectCore book (foldr Lam (foldr Lam bod (map fst mov)) fds) (mat + 1 + fromIntegral idx) | |
let tag = case typ of { Switch -> _SWI_ ; Match -> _MAT_ ; IfLet -> _IFL_ } | |
let lab = case typ of { Switch -> fromIntegral $ length css ; _ -> matFirstCid book tm } | |
trm <- return $ termNew tag lab mat | |
ret <- foldM (\mat (_, val) -> do | |
app <- lift $ allocNode 2 | |
lift $ set (app + 0) mat | |
injectCore book val (app + 1) | |
return $ termNew _APP_ 0 app) | |
trm | |
mov | |
lift $ set loc ret | |
injectCore book (U32 val) loc = do | |
lift $ set loc (termNew _W32_ 0 (fromIntegral val)) | |
injectCore book (Chr val) loc = do | |
lift $ set loc (termNew _CHR_ 0 (fromIntegral $ ord val)) | |
injectCore book (Op2 opr nm0 nm1) loc = do | |
opx <- lift $ allocNode 2 | |
injectCore book nm0 (opx + 0) | |
injectCore book nm1 (opx + 1) | |
lift $ set loc (termNew _OPX_ (fromIntegral $ fromEnum opr) opx) | |
doInjectCoreAt :: Book -> Core -> Loc -> [(String,Term)] -> HVM Term | |
doInjectCoreAt book core host argList = do | |
(_, state) <- runStateT (injectCore book core host) (emptyState { args = MS.fromList argList }) | |
foldM (\m (name, loc) -> do | |
case MS.lookup name (args state) of | |
Just term -> do | |
set loc term | |
if (head name /= '&') then do | |
return $ MS.delete name m | |
else do | |
return $ m | |
Nothing -> do | |
error $ "Unbound variable: \n\x1b[2m" ++ name ++ "\n\x1b[0mIn term:\n\x1b[2m" ++ Data.List.take 256 (coreToString core) ++ "...\x1b[0m") | |
(args state) | |
(vars state) | |
got host | |
module HVML.Compile where | |
import Control.Monad (forM_, forM, foldM, when) | |
import Control.Monad.State | |
import Data.Bits (shiftL, (.|.)) | |
import Data.List | |
import Data.Word | |
import Debug.Trace | |
import HVML.Show | |
import HVML.Type hiding (fresh) | |
import qualified Data.Map.Strict as MS | |
-- Compilation | |
-- ----------- | |
data CompileState = CompileState | |
{ next :: Word64 | |
, tabs :: Int | |
, bins :: MS.Map String String -- var_name => binder_host | |
, vars :: [(String, String)] -- [(var_name, var_host)] | |
, code :: [String] | |
} | |
type Compile = State CompileState | |
compileHeaders :: Book -> String | |
compileHeaders book = | |
let funcs = MS.toList (fidToNam book) | |
decls_f = map (\(_, name) -> "Term " ++ name ++ "_f(Term);") funcs | |
decls_t = map (\(_, name) -> "Term " ++ name ++ "_t(Term);") funcs | |
in unlines $ decls_f ++ decls_t | |
compile :: Book -> Word64 -> String | |
compile book fid = | |
let full = compileWith compileFull book fid in | |
let fast = compileWith compileFast book fid in | |
let slow = compileWith compileSlow book fid in | |
if "<ERR>" `isInfixOf` fast | |
then unlines [ full , slow ] | |
else unlines [ full , fast ] | |
-- Compiles a function using either Fast-Mode or Full-Mode | |
compileWith :: (Book -> Word64 -> Core -> Bool -> [(Bool,String)] -> Compile ()) -> Book -> Word64 -> String | |
compileWith cmp book fid = | |
let copy = fst (fst (mget (fidToFun book) fid)) in | |
let args = snd (fst (mget (fidToFun book) fid)) in | |
let core = snd (mget (fidToFun book) fid) in | |
let state = CompileState 0 0 MS.empty [] [] in | |
let result = runState (cmp book fid core copy args) state in | |
unlines $ reverse $ code (snd result) | |
emit :: String -> Compile () | |
emit line = modify $ \st -> st { code = (replicate (tabs st * 2) ' ' ++ line) : code st } | |
tabInc :: Compile () | |
tabInc = modify $ \st -> st { tabs = tabs st + 1 } | |
tabDec :: Compile () | |
tabDec = modify $ \st -> st { tabs = tabs st - 1 } | |
bind :: String -> String -> Compile () | |
bind var host = modify $ \st -> st { bins = MS.insert var host (bins st) } | |
fresh :: String -> Compile String | |
fresh name = do | |
uid <- gets next | |
modify $ \s -> s { next = uid + 1 } | |
return $ name ++ show uid | |
-- Full Compiler | |
-- ------------- | |
compileFull :: Book -> Word64 -> Core -> Bool -> [(Bool,String)] -> Compile () | |
compileFull book fid core copy args = do | |
emit $ "Term " ++ mget (fidToNam book) fid ++ "_t(Term ref) {" | |
tabInc | |
forM_ (zip [0..] args) $ \(i, arg) -> do | |
let argName = snd arg | |
let argTerm = if fst arg | |
then "reduce_at(term_loc(ref) + " ++ show i ++ ")" | |
else "got(term_loc(ref) + " ++ show i ++ ")" | |
bind argName argTerm | |
result <- compileFullCore book fid core "root" | |
st <- get | |
forM_ (vars st) $ \ (var,host) -> do | |
let varTerm = MS.findWithDefault "" var (bins st) | |
emit $ "set(" ++ host ++ ", " ++ varTerm ++ ");" | |
emit $ "return " ++ result ++ ";" | |
tabDec | |
emit "}" | |
compileFullVar :: String -> String -> Compile String | |
compileFullVar var host = do | |
bins <- gets bins | |
case MS.lookup var bins of | |
Just entry -> do | |
return entry | |
Nothing -> do | |
modify $ \s -> s { vars = (var, host) : vars s } | |
return "0" | |
compileFullCore :: Book -> Word64 -> Core -> String -> Compile String | |
compileFullCore book fid Era _ = do | |
return $ "term_new(ERA, 0, 0)" | |
compileFullCore book fid (Var name) host = do | |
compileFullVar name host | |
compileFullCore book fid (Let mode var val bod) host = do | |
letNam <- fresh "let" | |
emit $ "Loc " ++ letNam ++ " = alloc_node(2);" | |
-- emit $ "set(" ++ letNam ++ " + 0, term_new(SUB, 0, 0));" | |
valT <- compileFullCore book fid val (letNam ++ " + 0") | |
emit $ "set(" ++ letNam ++ " + 0, " ++ valT ++ ");" | |
bind var $ "term_new(VAR, 0, " ++ letNam ++ " + 0)" | |
bodT <- compileFullCore book fid bod (letNam ++ " + 1") | |
emit $ "set(" ++ letNam ++ " + 1, " ++ bodT ++ ");" | |
return $ "term_new(LET, " ++ show (fromEnum mode) ++ ", " ++ letNam ++ ")" | |
compileFullCore book fid (Lam var bod) host = do | |
lamNam <- fresh "lam" | |
emit $ "Loc " ++ lamNam ++ " = alloc_node(1);" | |
-- emit $ "set(" ++ lamNam ++ " + 0, term_new(SUB, 0, 0));" | |
bind var $ "term_new(VAR, 0, " ++ lamNam ++ " + 0)" | |
bodT <- compileFullCore book fid bod (lamNam ++ " + 0") | |
emit $ "set(" ++ lamNam ++ " + 0, " ++ bodT ++ ");" | |
return $ "term_new(LAM, 0, " ++ lamNam ++ ")" | |
compileFullCore book fid (App fun arg) host = do | |
appNam <- fresh "app" | |
emit $ "Loc " ++ appNam ++ " = alloc_node(2);" | |
funT <- compileFullCore book fid fun (appNam ++ " + 0") | |
argT <- compileFullCore book fid arg (appNam ++ " + 1") | |
emit $ "set(" ++ appNam ++ " + 0, " ++ funT ++ ");" | |
emit $ "set(" ++ appNam ++ " + 1, " ++ argT ++ ");" | |
return $ "term_new(APP, 0, " ++ appNam ++ ")" | |
compileFullCore book fid (Sup lab tm0 tm1) host = do | |
supNam <- fresh "sup" | |
emit $ "Loc " ++ supNam ++ " = alloc_node(2);" | |
tm0T <- compileFullCore book fid tm0 (supNam ++ " + 0") | |
tm1T <- compileFullCore book fid tm1 (supNam ++ " + 1") | |
emit $ "set(" ++ supNam ++ " + 0, " ++ tm0T ++ ");" | |
emit $ "set(" ++ supNam ++ " + 1, " ++ tm1T ++ ");" | |
return $ "term_new(SUP, " ++ show lab ++ ", " ++ supNam ++ ")" | |
compileFullCore book fid (Dup lab dp0 dp1 val bod) host = do | |
dupNam <- fresh "dup" | |
emit $ "Loc " ++ dupNam ++ " = alloc_node(2);" | |
emit $ "set(" ++ dupNam ++ " + 1, term_new(SUB, 0, 0));" | |
bind dp0 $ "term_new(DP0, " ++ show lab ++ ", " ++ dupNam ++ " + 0)" | |
bind dp1 $ "term_new(DP1, " ++ show lab ++ ", " ++ dupNam ++ " + 0)" | |
valT <- compileFullCore book fid val (dupNam ++ " + 0") | |
emit $ "set(" ++ dupNam ++ " + 0, " ++ valT ++ ");" | |
bodT <- compileFullCore book fid bod host | |
return bodT | |
compileFullCore book fid (Ctr nam fds) host = do | |
ctrNam <- fresh "ctr" | |
let arity = length fds | |
let cid = mget (ctrToCid book) nam | |
emit $ "Loc " ++ ctrNam ++ " = alloc_node(" ++ show arity ++ ");" | |
fdsT <- mapM (\ (i,fd) -> compileFullCore book fid fd (ctrNam ++ " + " ++ show i)) (zip [0..] fds) | |
sequence_ [emit $ "set(" ++ ctrNam ++ " + " ++ show i ++ ", " ++ fdT ++ ");" | (i,fdT) <- zip [0..] fdsT] | |
return $ "term_new(CTR, " ++ show cid ++ ", " ++ ctrNam ++ ")" | |
compileFullCore book fid tm@(Mat val mov css) host = do | |
let typ = matType book tm | |
matNam <- fresh "mat" | |
emit $ "Loc " ++ matNam ++ " = alloc_node(" ++ show (1 + length css) ++ ");" | |
valT <- compileFullCore book fid val (matNam ++ " + 0") | |
emit $ "set(" ++ matNam ++ " + 0, " ++ valT ++ ");" | |
forM_ (zip [0..] css) $ \ (i,(ctr,fds,bod)) -> do | |
let bod' = foldr Lam (foldr Lam bod (map fst mov)) fds | |
bodT <- compileFullCore book fid bod' (matNam ++ " + " ++ show (i+1)) | |
emit $ "set(" ++ matNam ++ " + " ++ show (i+1) ++ ", " ++ bodT ++ ");" | |
let tag = case typ of { Switch -> "SWI" ; IfLet -> "IFL" ; Match -> "MAT" } | |
let lab = case typ of { Switch -> fromIntegral (length css) ; _ -> matFirstCid book tm } | |
let mat = "term_new(" ++ tag ++ ", " ++ show lab ++ ", " ++ matNam ++ ")" | |
foldM (\term (key, val) -> do | |
appNam <- fresh "app" | |
emit $ "Loc " ++ appNam ++ " = alloc_node(2);" | |
valT <- compileFullCore book fid val (appNam ++ " + 1") | |
emit $ "set(" ++ appNam ++ " + 0, " ++ term ++ ");" | |
emit $ "set(" ++ appNam ++ " + 1, " ++ valT ++ ");" | |
return $ "term_new(APP, 0, " ++ appNam ++ ")") mat mov | |
compileFullCore book fid tm@(Mat val mov css) host = do | |
typ <- return $ matType book tm | |
matNam <- fresh "mat" | |
emit $ "Loc " ++ matNam ++ " = alloc_node(" ++ show (1 + length css) ++ ");" | |
valT <- compileFullCore book fid val (matNam ++ " + 0)" | |
emit $ "set(" ++ matNam ++ " + 0, " ++ valT ++ ");" | |
forM_ (zip [0..] css) $ \(i, (ctr,fds,bod)) -> do | |
let bod' = foldr Lam (foldr Lam bod (map fst mov)) fds | |
bodT <- compileFullCore book fid bod' (matNam ++ " + " ++ show (i+1)) | |
emit $ "set(" ++ matNam ++ " + " ++ show (i+1) ++ ", " ++ bodT ++ ");" | |
let tag = case typ of { Switch -> "SWI" ; Match -> "MAT" ; IfLet -> "IFL" } | |
let lab = case typ of { Switch -> fromIntegral (length css) ; _ -> matFirstCid book tm } | |
trm <- return $ "term_new(" ++ tag ++ ", " ++ show lab ++ ", " ++ matNam ++ ")" | |
foldM (\mat (_, val) -> do | |
appNam <- fresh "app" | |
emit $ "Loc " ++ appNam ++ " = alloc_node(2);" | |
emit $ "set(" ++ appNam ++ " + 0, " ++ mat ++ ");" | |
valT <- compileFullCore book fid val (appNam ++ " + 1") | |
emit $ "set(" ++ appNam ++ " + 1, " ++ valT ++ ");" | |
return $ "term_new(APP, 0, " ++ appNam ++ ")") | |
trm | |
mov | |
compileFullCore book fid (U32 val) _ = | |
return $ "term_new(W32, 0, " ++ show (fromIntegral val) ++ ")" | |
compileFullCore book fid (Chr val) _ = | |
return $ "term_new(CHR, 0, " ++ show (fromEnum val) ++ ")" | |
compileFullCore book fid (Op2 opr nu0 nu1) host = do | |
opxNam <- fresh "opx" | |
emit $ "Loc " ++ opxNam ++ " = alloc_node(2);" | |
nu0T <- compileFullCore book fid nu0 (opxNam ++ " + 0") | |
nu1T <- compileFullCore book fid nu1 (opxNam ++ " + 1") | |
emit $ "set(" ++ opxNam ++ " + 0, " ++ nu0T ++ ");" | |
emit $ "set(" ++ opxNam ++ " + 1, " ++ nu1T ++ ");" | |
return $ "term_new(OPX, " ++ show (fromEnum opr) ++ ", " ++ opxNam ++ ")" | |
compileFullCore book fid (Ref rNam rFid rArg) host = do | |
refNam <- fresh "ref" | |
let arity = length rArg | |
emit $ "Loc " ++ refNam ++ " = alloc_node(" ++ show arity ++ ");" | |
argsT <- mapM (\ (i,arg) -> compileFullCore book fid arg (refNam ++ " + " ++ show i)) (zip [0..] rArg) | |
sequence_ [emit $ "set(" ++ refNam ++ " + " ++ show i ++ ", " ++ argT ++ ");" | (i,argT) <- zip [0..] argsT] | |
return $ "term_new(REF, " ++ show rFid ++ ", " ++ refNam ++ ")" | |
-- Fast Compiler | |
-- ------------- | |
-- Compiles a function using Fast-Mode | |
compileFast :: Book -> Word64 -> Core -> Bool -> [(Bool,String)] -> Compile () | |
compileFast book fid core copy args = do | |
emit $ "Term " ++ mget (fidToNam book) fid ++ "_f(Term ref) {" | |
tabInc | |
emit "u64 itrs = 0;" | |
args <- forM (zip [0..] args) $ \ (i, (strict, arg)) -> do | |
argNam <- fresh "arg" | |
if strict then do | |
emit $ "Term " ++ argNam ++ " = reduce_at(term_loc(ref) + " ++ show i ++ ");" | |
else do | |
emit $ "Term " ++ argNam ++ " = got(term_loc(ref) + " ++ show i ++ ");" | |
if copy && strict then do | |
-- your goal is to implement the ref-sup optimization. trigger it when the | |
-- arg is a superposition, and its label isn't on this function's fidToLab | |
-- set. note that the fidToLab set is static, while the label is dynamic. | |
-- that is, there is no 'fidToLab' map on the generated C runtime. | |
-- TODO: reason about that, and implement this logic correctly. | |
{:FILL_HERE:} | |
else | |
return () | |
bind arg argNam | |
return argNam | |
compileFastArgs book fid core args MS.empty | |
tabDec | |
emit "}" | |
-- Compiles a fast function's argument list | |
compileFastArgs :: Book -> Word64 -> Core -> [String] -> MS.Map Int [String] -> Compile () | |
compileFastArgs book fid body ctx reuse = do | |
emit $ "while (1) {" | |
tabInc | |
compileFastBody book fid body ctx False 0 reuse | |
tabDec | |
emit $ "}" | |
-- Compiles a fast function body (pattern-matching) | |
compileFastBody :: Book -> Word64 -> Core -> [String] -> Bool -> Int -> MS.Map Int [String] -> Compile () | |
compileFastBody book fid term@(Mat val mov css) ctx stop@False itr reuse = do | |
valT <- compileFastCore book fid val reuse | |
valNam <- fresh "val" | |
numNam <- fresh "num" | |
emit $ "Term " ++ valNam ++ " = (" ++ valT ++ ");" | |
let isNumeric = length css > 0 && (let (ctr,fds,bod) = css !! 0 in ctr == "0") | |
-- Numeric Pattern-Matching | |
if isNumeric then do | |
emit $ "if (term_tag("++valNam++") == W32) {" | |
tabInc | |
emit $ "u32 " ++ numNam ++ " = term_loc(" ++ valNam ++ ");" | |
emit $ "switch (" ++ numNam ++ ") {" | |
tabInc | |
forM_ (zip [0..] css) $ \ (i, (ctr,fds,bod)) -> do | |
if i < length css - 1 then do | |
emit $ "case " ++ show i ++ ": {" | |
tabInc | |
forM_ mov $ \ (key,val) -> do | |
valT <- compileFastCore book fid val reuse | |
bind key valT | |
compileFastBody book fid bod ctx stop (itr + 1 + length mov) reuse | |
emit $ "break;" | |
tabDec | |
emit $ "}" | |
else do | |
emit $ "default: {" | |
tabInc | |
preNam <- fresh "pre" | |
emit $ "Term " ++ preNam ++ " = " ++ "term_new(W32, 0, "++numNam++" - "++show (length css - 1)++");" | |
forM_ fds $ \ fd -> do | |
bind fd preNam | |
forM_ mov $ \ (key,val) -> do | |
valT <- compileFastCore book fid val reuse | |
bind key valT | |
compileFastBody book fid bod ctx stop (itr + 1 + length fds + length mov) reuse | |
emit $ "break;" | |
tabDec | |
emit $ "}" | |
tabDec | |
emit $ "}" | |
tabDec | |
emit $ "}" | |
-- Constructor Pattern-Matching (with IfLet) | |
else do | |
if matType book term == IfLet then do | |
emit $ "if (term_tag(" ++ valNam ++ ") == CTR) {" | |
tabInc | |
emit $ "if (term_lab(" ++ valNam ++ ") == " ++ show (matFirstCid book term) ++ ") {" | |
tabInc | |
let (ctr,fds,bod) = css !! 0 | |
let reuse' = MS.insertWith (++) (length fds) ["term_loc(" ++ valNam ++ ")"] reuse | |
forM_ (zip [0..] fds) $ \ (k,fd) -> do | |
fdNam <- fresh "fd" | |
emit $ "Term " ++ fdNam ++ " = got(term_loc(" ++ valNam ++ ") + " ++ show k ++ ");" | |
bind fd fdNam | |
forM_ mov $ \ (key,val) -> do | |
valT <- compileFastCore book fid val reuse' | |
bind key valT | |
compileFastBody book fid bod ctx stop (itr + 1 + length fds + length mov) reuse' | |
tabDec | |
emit $ "} else {" | |
tabInc | |
let (ctr,fds,bod) = css !! 1 | |
when (length fds /= 1) $ do | |
error "incorrect arity on if-let default case" | |
fdNam <- fresh "fd" | |
emit $ "Term " ++ fdNam ++ " = " ++ valNam ++ ";" | |
bind (head fds) fdNam | |
forM_ mov $ \ (key,val) -> do | |
valT <- compileFastCore book fid val reuse | |
bind key valT | |
compileFastBody book fid bod ctx stop (itr + 1 + 1 + length mov) reuse | |
tabDec | |
emit $ "}" | |
tabDec | |
emit $ "}" | |
-- Constructor Pattern-Matching (without IfLet) | |
else do | |
emit $ "if (term_tag(" ++ valNam ++ ") == CTR) {" | |
tabInc | |
emit $ "switch (term_lab(" ++ valNam ++ ") - " ++ show (matFirstCid book term) ++ ") {" | |
tabInc | |
forM_ (zip [0..] css) $ \ (i, (ctr,fds,bod)) -> do | |
emit $ "case " ++ show i ++ ": {" | |
tabInc | |
let reuse' = MS.insertWith (++) (length fds) ["term_loc(" ++ valNam ++ ")"] reuse | |
forM_ (zip [0..] fds) $ \ (k,fd) -> do | |
fdNam <- fresh "fd" | |
emit $ "Term " ++ fdNam ++ " = got(term_loc(" ++ valNam ++ ") + " ++ show k ++ ");" | |
bind fd fdNam | |
forM_ mov $ \ (key,val) -> do | |
valT <- compileFastCore book fid val reuse' | |
bind key valT | |
compileFastBody book fid bod ctx stop (itr + 1 + length fds + length mov) reuse' | |
emit $ "break;" | |
tabDec | |
emit $ "}" | |
tabDec | |
emit $ "}" | |
tabDec | |
emit $ "}" | |
compileFastUndo book fid term ctx itr reuse | |
compileFastBody book fid term@(Dup lab dp0 dp1 val bod) ctx stop itr reuse = do | |
valT <- compileFastCore book fid val reuse | |
valNam <- fresh "val" | |
dp0Nam <- fresh "dp0" | |
dp1Nam <- fresh "dp1" | |
emit $ "Term " ++ valNam ++ " = (" ++ valT ++ ");" | |
emit $ "Term " ++ dp0Nam ++ ";" | |
emit $ "Term " ++ dp1Nam ++ ";" | |
emit $ "if (term_tag(" ++ valNam ++ ") == W32) {" | |
tabInc | |
emit $ "itrs += 1;" | |
emit $ dp0Nam ++ " = " ++ valNam ++ ";" | |
emit $ dp1Nam ++ " = " ++ valNam ++ ";" | |
tabDec | |
emit $ "} else {" | |
tabInc | |
dupNam <- fresh "dup" | |
dupLoc <- compileFastAlloc 2 reuse | |
emit $ "Loc " ++ dupNam ++ " = " ++ dupLoc ++ ";" | |
emit $ "set(" ++ dupNam ++ " + 0, " ++ valNam ++ ");" | |
emit $ "set(" ++ dupNam ++ " + 1, term_new(SUB, 0, 0));" | |
emit $ dp0Nam ++ " = term_new(DP0, " ++ show lab ++ ", " ++ dupNam ++ " + 0);" | |
emit $ dp1Nam ++ " = term_new(DP1, " ++ show lab ++ ", " ++ dupNam ++ " + 0);" | |
tabDec | |
emit $ "}" | |
bind dp0 dp0Nam | |
bind dp1 dp1Nam | |
compileFastBody book fid bod ctx stop itr reuse | |
compileFastBody book fid term@(Let mode var val bod) ctx stop itr reuse = do | |
valT <- compileFastCore book fid val reuse | |
case mode of | |
LAZY -> do | |
bind var valT | |
STRI -> do | |
case val of | |
Ref _ rFid _ -> do | |
valNam <- fresh "val" | |
emit $ "Term " ++ valNam ++ " = reduce(" ++ mget (fidToNam book) rFid ++ "_f(" ++ valT ++ "));" | |
bind var valNam | |
_ -> do | |
valNam <- fresh "val" | |
emit $ "Term " ++ valNam ++ " = reduce(" ++ valT ++ ");" | |
bind var valNam | |
PARA -> do | |
valNam <- fresh "val" | |
emit $ "Term " ++ valNam ++ " = reduce(" ++ valT ++ ");" | |
bind var valNam | |
compileFastBody book fid bod ctx stop itr reuse | |
compileFastBody book fid term@(Ref fNam fFid fArg) ctx stop itr reuse | fFid == fid = do | |
forM_ (zip fArg ctx) $ \ (arg, ctxVar) -> do | |
argT <- compileFastCore book fid arg reuse | |
emit $ "" ++ ctxVar ++ " = " ++ argT ++ ";" | |
emit $ "itrs += " ++ show (itr + 1) ++ ";" | |
emit $ "continue;" | |
compileFastBody book fid term ctx stop itr reuse = do | |
emit $ "itrs += " ++ show itr ++ ";" | |
body <- compileFastCore book fid term reuse | |
compileFastSave book fid term ctx itr reuse | |
emit $ "return " ++ body ++ ";" | |
-- Falls back from fast mode to full mode | |
compileFastUndo :: Book -> Word64 -> Core -> [String] -> Int -> MS.Map Int [String] -> Compile () | |
compileFastUndo book fid term ctx itr reuse = do | |
forM_ (zip [0..] ctx) $ \ (i, arg) -> do | |
emit $ "set(term_loc(ref) + "++show i++", " ++ arg ++ ");" | |
emit $ "return " ++ mget (fidToNam book) fid ++ "_t(ref);" | |
-- Completes a fast mode call | |
compileFastSave :: Book -> Word64 -> Core -> [String] -> Int -> MS.Map Int [String] -> Compile () | |
compileFastSave book fid term ctx itr reuse = do | |
emit $ "*HVM.itrs += itrs;" | |
-- Helper function to allocate nodes with reuse | |
compileFastAlloc :: Int -> MS.Map Int [String] -> Compile String | |
compileFastAlloc arity reuse = do | |
return $ "alloc_node(" ++ show arity ++ ")" | |
-- FIXME: temporarily disabled, caused bug in: | |
-- data List { | |
-- #Nil | |
-- #Cons{head tail} | |
-- } | |
-- @cat(xs ys) = ~xs !ys { | |
-- #Nil: ys | |
-- #Cons{h t}: #Cons{h @cat(t ys)} | |
-- } | |
-- @main = @cat(#Cons{1 #Nil} #Nil) | |
-- case MS.lookup arity reuse of | |
-- Just (loc:locs) -> return loc | |
-- _ -> return $ "alloc_node(" ++ show arity ++ ")" | |
-- Compiles a core term in fast mode | |
compileFastCore :: Book -> Word64 -> Core -> MS.Map Int [String] -> Compile String | |
compileFastCore book fid Era reuse = | |
return $ "term_new(ERA, 0, 0)" | |
compileFastCore book fid (Let mode var val bod) reuse = do | |
valT <- compileFastCore book fid val reuse | |
case mode of | |
LAZY -> do | |
emit $ "itrs += 1;" | |
bind var valT | |
STRI -> do | |
valNam <- fresh "val" | |
emit $ "itrs += 1;" | |
emit $ "Term " ++ valNam ++ " = reduce(" ++ valT ++ ");" | |
bind var valNam | |
PARA -> do -- TODO: implement parallel evaluation | |
valNam <- fresh "val" | |
emit $ "Term " ++ valNam ++ " = reduce(" ++ valT ++ ");" | |
bind var valNam | |
compileFastCore book fid bod reuse | |
compileFastCore book fid (Var name) reuse = do | |
compileFastVar name | |
compileFastCore book fid (Lam var bod) reuse = do | |
lamNam <- fresh "lam" | |
lamLoc <- compileFastAlloc 1 reuse | |
emit $ "Loc " ++ lamNam ++ " = " ++ lamLoc ++ ";" | |
-- emit $ "set(" ++ lamNam ++ " + 0, term_new(SUB, 0, 0));" | |
bind var $ "term_new(VAR, 0, " ++ lamNam ++ " + 0)" | |
bodT <- compileFastCore book fid bod reuse | |
emit $ "set(" ++ lamNam ++ " + 0, " ++ bodT ++ ");" | |
return $ "term_new(LAM, 0, " ++ lamNam ++ ")" | |
compileFastCore book fid (App fun arg) reuse = do | |
appNam <- fresh "app" | |
appLoc <- compileFastAlloc 2 reuse | |
emit $ "Loc " ++ appNam ++ " = " ++ appLoc ++ ";" | |
funT <- compileFastCore book fid fun reuse | |
argT <- compileFastCore book fid arg reuse | |
emit $ "set(" ++ appNam ++ " + 0, " ++ funT ++ ");" | |
emit $ "set(" ++ appNam ++ " + 1, " ++ argT ++ ");" | |
return $ "term_new(APP, 0, " ++ appNam ++ ")" | |
compileFastCore book fid (Sup lab tm0 tm1) reuse = do | |
supNam <- fresh "sup" | |
supLoc <- compileFastAlloc 2 reuse | |
emit $ "Loc " ++ supNam ++ " = " ++ supLoc ++ ";" | |
tm0T <- compileFastCore book fid tm0 reuse | |
tm1T <- compileFastCore book fid tm1 reuse | |
emit $ "set(" ++ supNam ++ " + 0, " ++ tm0T ++ ");" | |
emit $ "set(" ++ supNam ++ " + 1, " ++ tm1T ++ ");" | |
return $ "term_new(SUP, " ++ show lab ++ ", " ++ supNam ++ ")" | |
compileFastCore book fid (Dup lab dp0 dp1 val bod) reuse = do | |
dupNam <- fresh "dup" | |
dp0Nam <- fresh "dp0" | |
dp1Nam <- fresh "dp1" | |
valNam <- fresh "val" | |
valT <- compileFastCore book fid val reuse | |
emit $ "Term " ++ valNam ++ " = (" ++ valT ++ ");" | |
emit $ "Term " ++ dp0Nam ++ ";" | |
emit $ "Term " ++ dp1Nam ++ ";" | |
emit $ "if (term_tag("++valNam++") == W32 || term_tag("++valNam++") == CHR) {" | |
tabInc | |
emit $ "itrs += 1;" | |
emit $ dp0Nam ++ " = " ++ valNam ++ ";" | |
emit $ dp1Nam ++ " = " ++ valNam ++ ";" | |
tabDec | |
emit $ "} else {" | |
tabInc | |
dupLoc <- compileFastAlloc 2 reuse | |
emit $ "Loc " ++ dupNam ++ " = " ++ dupLoc ++ ";" | |
emit $ "set(" ++ dupNam ++ " + 0, " ++ valNam ++ ");" | |
emit $ "set(" ++ dupNam ++ " + 1, term_new(SUB, 0, 0));" | |
emit $ dp0Nam ++ " = term_new(DP0, " ++ show lab ++ ", " ++ dupNam ++ " + 0);" | |
emit $ dp1Nam ++ " = term_new(DP1, " ++ show lab ++ ", " ++ dupNam ++ " + 0);" | |
tabDec | |
emit $ "}" | |
bind dp0 dp0Nam | |
bind dp1 dp1Nam | |
compileFastCore book fid bod reuse | |
compileFastCore book fid (Ctr nam fds) reuse = do | |
ctrNam <- fresh "ctr" | |
let arity = length fds | |
let cid = mget (ctrToCid book) nam | |
ctrLoc <- compileFastAlloc arity reuse | |
emit $ "Loc " ++ ctrNam ++ " = " ++ ctrLoc ++ ";" | |
fdsT <- mapM (\ (i,fd) -> compileFastCore book fid fd reuse) (zip [0..] fds) | |
sequence_ [emit $ "set(" ++ ctrNam ++ " + " ++ show i ++ ", " ++ fdT ++ ");" | (i,fdT) <- zip [0..] fdsT] | |
return $ "term_new(CTR, " ++ show cid ++ ", " ++ ctrNam ++ ")" | |
compileFastCore book fid tm@(Mat val mov css) reuse = do | |
let typ = matType book tm | |
matNam <- fresh "mat" | |
matLoc <- compileFastAlloc (1 + length css) reuse | |
emit $ "Loc " ++ matNam ++ " = " ++ matLoc ++ ";" | |
valT <- compileFastCore book fid val reuse | |
emit $ "set(" ++ matNam ++ " + 0, " ++ valT ++ ");" | |
forM_ (zip [0..] css) $ \(i,(ctr,fds,bod)) -> do | |
let bod' = foldr Lam (foldr Lam bod (map fst mov)) fds | |
bodT <- compileFastCore book fid bod' reuse | |
emit $ "set(" ++ matNam ++ " + " ++ show (i+1) ++ ", " ++ bodT ++ ");" | |
let tag = case typ of { Switch -> "SWI" ; IfLet -> "IFL" ; Match -> "MAT" } | |
let lab = case typ of { Switch -> fromIntegral (length css) ; _ -> matFirstCid book tm } | |
retNam <- fresh "ret" | |
emit $ "Term " ++ retNam ++ " = term_new(" ++ tag ++ ", " ++ show lab ++ ", " ++ matNam ++ ");" | |
foldM (\acc (_, val) -> do | |
appNam <- fresh "app" | |
appLoc <- compileFastAlloc 2 reuse | |
emit $ "Loc " ++ appNam ++ " = " ++ appLoc ++ ";" | |
emit $ "set(" ++ appNam ++ " + 0, " ++ acc ++ ");" | |
valT <- compileFastCore book fid val reuse | |
emit $ "set(" ++ appNam ++ " + 1, " ++ valT ++ ");" | |
return $ "term_new(APP, 0, " ++ appNam ++ ")") retNam mov | |
compileFastCore book fid (U32 val) reuse = | |
return $ "term_new(W32, 0, " ++ show (fromIntegral val) ++ ")" | |
compileFastCore book fid (Chr val) reuse = | |
return $ "term_new(CHR, 0, " ++ show (fromEnum val) ++ ")" | |
compileFastCore book fid (Op2 opr nu0 nu1) reuse = do | |
opxNam <- fresh "opx" | |
retNam <- fresh "ret" | |
nu0Nam <- fresh "nu0" | |
nu1Nam <- fresh "nu1" | |
nu0T <- compileFastCore book fid nu0 reuse | |
nu1T <- compileFastCore book fid nu1 reuse | |
emit $ "Term " ++ nu0Nam ++ " = (" ++ nu0T ++ ");" | |
emit $ "Term " ++ nu1Nam ++ " = (" ++ nu1T ++ ");" | |
emit $ "Term " ++ retNam ++ ";" | |
emit $ "if (term_tag(" ++ nu0Nam ++ ") == W32 && term_tag(" ++ nu1Nam ++ ") == W32) {" | |
emit $ " itrs += 2;" | |
let oprStr = case opr of | |
OP_ADD -> "+" | |
OP_SUB -> "-" | |
OP_MUL -> "*" | |
OP_DIV -> "/" | |
OP_MOD -> "%" | |
OP_EQ -> "==" | |
OP_NE -> "!=" | |
OP_LT -> "<" | |
OP_GT -> ">" | |
OP_LTE -> "<=" | |
OP_GTE -> ">=" | |
OP_AND -> "&" | |
OP_OR -> "|" | |
OP_XOR -> "^" | |
OP_LSH -> "<<" | |
OP_RSH -> ">>" | |
emit $ " " ++ retNam ++ " = term_new(W32, 0, term_loc(" ++ nu0Nam ++ ") " ++ oprStr ++ " term_loc(" ++ nu1Nam ++ "));" | |
emit $ "} else {" | |
opxLoc <- compileFastAlloc 2 reuse | |
emit $ " Loc " ++ opxNam ++ " = " ++ opxLoc ++ ";" | |
emit $ " set(" ++ opxNam ++ " + 0, " ++ nu0Nam ++ ");" | |
emit $ " set(" ++ opxNam ++ " + 1, " ++ nu1Nam ++ ");" | |
emit $ " " ++ retNam ++ " = term_new(OPX, " ++ show (fromEnum opr) ++ ", " ++ opxNam ++ ");" | |
emit $ "}" | |
return $ retNam | |
compileFastCore book fid (Ref rNam rFid rArg) reuse = do | |
-- Inline Dynamic SUP | |
if rNam == "SUP" then do | |
let [lab, tm0, tm1] = rArg | |
supNam <- fresh "sup" | |
labNam <- fresh "lab" | |
supLoc <- compileFastAlloc 2 reuse | |
labT <- compileFastCore book fid lab reuse | |
emit $ "Term " ++ labNam ++ " = reduce(" ++ labT ++ ");" | |
emit $ "if (term_tag(" ++ labNam ++ ") != W32) {" | |
emit $ " printf(\"ERROR:non-numeric-sup-label\\n\");" | |
emit $ "}" | |
emit $ "itrs += 1;" | |
emit $ "Loc " ++ supNam ++ " = " ++ supLoc ++ ";" | |
tm0T <- compileFastCore book fid tm0 reuse | |
tm1T <- compileFastCore book fid tm1 reuse | |
emit $ "set(" ++ supNam ++ " + 0, " ++ tm0T ++ ");" | |
emit $ "set(" ++ supNam ++ " + 1, " ++ tm1T ++ ");" | |
return $ "term_new(SUP, term_loc(" ++ labNam ++ "), " ++ supNam ++ ")" | |
-- Inline Dynamic DUP | |
else if rNam == "DUP" && (case rArg of [_, _, Lam _ (Lam _ _)] -> True ; _ -> False) then do | |
let [lab, val, Lam x (Lam y body)] = rArg | |
dupNam <- fresh "dup" | |
labNam <- fresh "lab" | |
dupLoc <- compileFastAlloc 2 reuse | |
labT <- compileFastCore book fid lab reuse | |
emit $ "Term " ++ labNam ++ " = reduce(" ++ labT ++ ");" | |
emit $ "if (term_tag(" ++ labNam ++ ") != W32) {" | |
emit $ " printf(\"ERROR:non-numeric-sup-label\\n\");" | |
emit $ "}" | |
emit $ "itrs += 3;" | |
emit $ "Loc " ++ dupNam ++ " = " ++ dupLoc ++ ";" | |
valT <- compileFastCore book fid val reuse | |
emit $ "set(" ++ dupNam ++ " + 0, " ++ valT ++ ");" | |
emit $ "set(" ++ dupNam ++ " + 1, term_new(SUB, 0, 0));" | |
bind x $ "term_new(DP0, term_loc(" ++ labNam ++ "), " ++ dupNam ++ " + 0)" | |
bind y $ "term_new(DP1, term_loc(" ++ labNam ++ "), " ++ dupNam ++ " + 0)" | |
compileFastCore book fid body reuse | |
-- Create REF node | |
else do | |
refNam <- fresh "ref" | |
let arity = length rArg | |
refLoc <- compileFastAlloc arity reuse | |
emit $ "Loc " ++ refNam ++ " = " ++ refLoc ++ ";" | |
argsT <- mapM (\ (i,arg) -> compileFastCore book fid arg reuse) (zip [0..] rArg) | |
sequence_ [emit $ "set(" ++ refNam ++ " + " ++ show i ++ ", " ++ argT ++ ");" | (i,argT) <- zip [0..] argsT] | |
return $ "term_new(REF, " ++ show rFid ++ ", " ++ refNam ++ ")" | |
-- Compiles a variable in fast mode | |
compileFastVar :: String -> Compile String | |
compileFastVar var = do | |
bins <- gets bins | |
case MS.lookup var bins of | |
Just entry -> do | |
return entry | |
Nothing -> do | |
return "<ERR>" | |
-- Compiles a function using Fast-Mode | |
compileSlow :: Book -> Word64 -> Core -> Bool -> [(Bool,String)] -> Compile () | |
compileSlow book fid core copy args = do | |
emit $ "Term " ++ mget (fidToNam book) fid ++ "_f(Term ref) {" | |
emit $ " return " ++ mget (fidToNam book) fid ++ "_t(ref);" | |
emit $ "}" | |
### TASK: complete the {:FILL_HERE:} part of the file above. Write ONLY the needed text to replace {:FILL_HERE:} by the correct completion, including correct spacing and indentation. Include the answer inside a <COMPLETION></COMPLETION> tag. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
the challenge is to realize that, since there is no fidToLab map on C-side, we need to compile that map inline, as a series of checks:
the canonical implementation is:
notice how the 'labs' map is compiled to a series of 'lab != X' expressions on C
side, using a forM_. if the AI has that insight, a point is awarded
a common error is to mix up haskell and C, and answer something like:
which is wrong, since the AI is trying to access the Haskell map from the C code