-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathArgs.hs
More file actions
158 lines (132 loc) · 6.1 KB
/
Copy pathArgs.hs
File metadata and controls
158 lines (132 loc) · 6.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
{-# LANGUAGE ImplicitParams #-} -- for tracking isSimple option
module Args(argn, getArgByName, newLambdaArg, addLambda, newLetArg, popArg, debugContext, argImplicit, deBruijnArgReps, getAllArgs) where
import Expr
import Types
import Header
import Hs
import Parse (parseError,onlyCheckMatchIdentifier)
import Data.List
import Data.Maybe
import Control.Monad.State -- needs cabal install --lib mtl
import qualified Data.Set as Set -- needs cabal install --lib containers
argStr n tn = "arg" ++ show n ++ "t" ++ show tn
letStr n tn = "larg" ++ show n ++ "t" ++ show tn
newLambdaArg :: [VT] -> Maybe [String] -> ArgUsedness -> String -> ParseState Args
newLambdaArg argT names argUsedness from = do
context <- gets pdContext
let depth = 1 + length context
let impls = zipWith3 (\t name tn -> Impl {
implType = t,
implCode = hsAtom $ argStr depth tn,
implDeps = Set.singleton depth,
implName = name,
implUsed = argUsedness
} ) argT (transposeMaybe names) [1..]
let newArg = Args impls LambdaArg from
modify $ \s -> s { pdContext=newArg:context }
return newArg
transposeMaybe :: Maybe [String] -> [Maybe String]
transposeMaybe names = maybe (repeat Nothing) (map Just) names
newLetArg :: Maybe [String] -> ArgUsedness -> Impl -> [VT] -> String -> ParseState Args
newLetArg names argUsedness (Impl _ defHs defDepth _ usedness) defTypes from = do
context <- gets pdContext
nextLetId <- gets pdNextUniqLetId
modify $ \s -> s { pdNextUniqLetId=nextLetId+1 }
let impls = zipWith3 (\t name tn -> Impl t (hsAtom $ letStr nextLetId tn) defDepth name argUsedness) defTypes (transposeMaybe names) [1..]
let newArg = Args impls (LetArg defHs) from
modify $ \s -> s { pdContext=newArg:context }
return newArg
argn :: Int -> ParseState Impl
argn deBruijnIndex = do
context <- gets pdContext
flattenedArgs <- getAllArgs
case at flattenedArgs (deBruijnIndex-1) of
Nothing -> parseError $ "Attempt to access " ++ (snd $ indexToOp (deBruijnIndex-1)) ++ debugContext context
Just impl -> setUsed impl
getArgByName :: ParseState (Maybe Impl)
getArgByName = do
allArgs <- getAllArgs
getArgByNameH 0 allArgs
where
getArgByNameH :: Int -> [Impl] -> ParseState (Maybe Impl)
getArgByNameH _ [] = return Nothing
getArgByNameH n (impl:rest) =
case implName impl of
Just argName -> do
code <- gets pdCode
case onlyCheckMatchIdentifier code of
Just (name, nextCode) | name == argName -> do
modify $ \s -> s { pdCode = nextCode }
appendRep $ indexToOp n
argn (n+1) >>= return.Just
otherwise -> getArgByNameH (n+1) rest
otherwise -> getArgByNameH (n+1) rest
setUsed :: Impl -> ParseState Impl
setUsed impl = do
context <- gets pdContext
let newContext = map (\arg -> arg { argsImpls=setUsedImpl (argsImpls arg) } ) context
modify $ \s -> s { pdContext=newContext }
return impl where
setUsedImpl :: [Impl] -> [Impl]
setUsedImpl = map (\argImpl ->
if implCode argImpl == implCode impl then
argImpl { implUsed=UsedArg }
else argImpl)
argImplicit :: (?isSimple::Bool) => ParseState Impl
argImplicit = do
if ?isSimple
then parseError "Expecting more expressions at EOF"
else do
allArgs <- getAllArgs
modify $ \s -> s { pdImplicitArgUsed = True }
argn $ 1 + (fromMaybe 0 $ findIndex ((==UnusedArg).implUsed) allArgs)
flattenArg (Args impls (LambdaArg) _) = impls
flattenArg (Args impls (LetArg _) _) = tail impls
getAllArgs :: ParseState [Impl]
getAllArgs = do
context <- gets pdContext
return $ concatMap flattenArg context
addLambda :: Args -> Impl -> Impl
addLambda arg (Impl t body d _ _) = Impl {
implType = t,
implCode = hsFn (map implCode $ argsImpls arg) body,
implDeps = Set.difference d (getArgDeps arg),
implName = Nothing,
implUsed = UsednessDoesntMatter }
-- Remove arg # and all its dependent let args (adding let statements for them).
popArg :: Int -> Impl -> ParseState Impl
popArg depth impl = do
context <- gets pdContext
let (finalImpl, finalContext) = mapAccumL maybePopIt impl context
modify $ \s -> s { pdContext=concat finalContext }
return finalImpl where
maybePopIt :: Impl -> Args -> (Impl, [Args])
maybePopIt impl eachArg
| Set.member depth (getArgDeps eachArg) = (popIt eachArg impl, [])
| otherwise = (impl, [eachArg])
popIt :: Args -> Impl -> Impl
popIt (Args _ LambdaArg _) impl = impl
popIt (Args varImpls (LetArg refHs) _) (Impl retT bodyHs dep _ _) =
Impl retT (hsLet (map implCode varImpls) refHs bodyHs) dep Nothing UsednessDoesntMatter
getArgDeps (Args (impl : _) _ _) = implDeps impl -- They should all be the same
getArgDeps (Args [] _ _) = implDeps noArgsUsed
--------- for debugging // errors -----------
debugContext :: [Args] -> String
debugContext context = "\nContext:\n" ++ (unlines $ snd $ mapAccumL (\count arg ->
let args = flattenArg arg in
(count+length args, unlines $ showArgType arg : zipWith (\n a->(" "++showArg n a)) [count..] args)
) 0 $ filter (not.null.flattenArg) context)
showArgType (Args _ LambdaArg from) = "LambdaArg " ++ from
showArgType (Args _ (LetArg _) from) = "LetArg " ++ from
showArg n impl = snd (indexToOp n) ++ " " ++ fromMaybe "" (implName impl) ++ " :: " ++ (toHsReadType $ implType impl) ++ " " ++ explainUsedness (implUsed impl)
-- only really useful for debugging code that checks where let statements go
-- ++ " deps: " ++ show (Set.toList $ implDeps impl)
explainUsedness OptionalArg = "" -- "(optionally used, equivalent to used in priority)"
explainUsedness UnusedArg = "(unused so far, prioritized for implicit args)"
explainUsedness UsedArg = "" -- ""
explainUsedness UsednessDoesntMatter = "usedness doesn't matter, should be impossible"
indexToOp :: Int -> ([Int], String)
indexToOp = fromMaybe (error "deBruijn index too high") . (at deBruijnArgReps) where
deBruijnArgReps :: [([Int], String)]
deBruijnArgReps = [(replicate unary 6 ++ [nib], replicate unary ';' ++ sym)
| unary <- [0..11], (sym,nib) <- [("$",3),("@",4),("_",5)]]