| 176 | | applyListAssoc = do |
| 177 | | evl <- asks envEval |
| 178 | | evl $ App (Val $ VCode code{ subParams = length args `replicate` head (subParams code)}) Nothing (map Val args) |
| 179 | | if subAssoc code == A_list then applyListAssoc else do |
| 180 | | if arity < 2 then fail "Cannot reduce() using a unary or nullary function." else do |
| 181 | | -- n is the number of *additional* arguments to be passed to the sub. |
| 182 | | -- Ex.: reduce { $^a + $^b }, ... # n = 1 |
| 183 | | -- Ex.: reduce { $^a + $^b + $^c }, ... # n = 2 |
| 184 | | let n = arity - 1 |
| 185 | | -- Break on empty list. |
| 186 | | let doFold xs = do |
| 187 | | evl <- asks envEval |
| 188 | | local (\e -> e{ envContext = cxtItemAny }) $ do |
| 189 | | evl (App (Val sub) Nothing (map Val xs)) |
| 190 | | case subAssoc code of |
| 191 | | A_right -> do |
| 192 | | let args' = reverse args |
| 193 | | reduceMn args' n (doFold . reverse) |
| 194 | | A_chain -> if arity /= 2 -- FIXME: incorrect for scans |
| 195 | | then fail |
| 196 | | "When reducing using a chain-associative sub,\nthe sub must take exactly two arguments." |
| 197 | | else callCC $ \esc -> do |
| 198 | | let doFold' x y = do |
| 199 | | val <- doFold [x, y] |
| 200 | | case val of |
| 201 | | VBool False -> esc val |
| 202 | | _ -> return y |
| 203 | | reduceM doFold' (head args) (tail args) |
| 204 | | return $ VBool True |
| 205 | | A_non -> fail $ "Cannot reduce over non-associativity" |
| 206 | | _ -> reduceMn args n doFold -- "left", "pre" |
| | 176 | if subAssoc code == A_list |
| | 177 | then asks envEval >>= \evl -> evl $ App (Val $ VCode code{ subParams = length args `replicate` head (subParams code)}) Nothing (map Val args) |
| | 178 | else do |
| | 179 | when (arity < 2) $ fail "Cannot reduce() using a unary or nullary function." |
| | 180 | -- n is the number of *additional* arguments to be passed to the sub. |
| | 181 | -- Ex.: reduce { $^a + $^b }, ... # n = 1 |
| | 182 | -- Ex.: reduce { $^a + $^b + $^c }, ... # n = 2 |
| | 183 | let n = arity - 1 |
| | 184 | -- Break on empty list. |
| | 185 | let doFold xs = do |
| | 186 | evl <- asks envEval |
| | 187 | local (\e -> e{ envContext = cxtItemAny }) $ do |
| | 188 | evl (App (Val sub) Nothing (map Val xs)) |
| | 189 | case subAssoc code of |
| | 190 | A_right -> do |
| | 191 | let args' = reverse args |
| | 192 | reduceMn args' n (doFold . reverse) |
| | 193 | A_chain -> if arity /= 2 -- FIXME: incorrect for scans |
| | 194 | then fail |
| | 195 | "When reducing using a chain-associative sub,\nthe sub must take exactly two arguments." |
| | 196 | else callCC $ \esc -> do |
| | 197 | let doFold' x y = do |
| | 198 | val <- doFold [x, y] |
| | 199 | case val of |
| | 200 | VBool False -> esc val |
| | 201 | _ -> return y |
| | 202 | reduceM doFold' (head args) (tail args) |
| | 203 | return $ VBool True |
| | 204 | A_non -> fail $ "Cannot reduce over non-associativity" |
| | 205 | _ -> reduceMn args n doFold -- "left", "pre" |