diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-04-08 16:04:25 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-04-08 16:04:25 +0200 |
commit | 7912e245ab2af57eddc3152b12c07c2e287b5b21 (patch) | |
tree | 94b8d9cf081ddf7242e39499fed408f4f651d07f /prototypes | |
parent | c7474d2ffee418c024d3f74bccff4e75178ca1d6 (diff) |
begin to implement hnf
Diffstat (limited to 'prototypes')
-rw-r--r-- | prototypes/ShiftReducer.hs | 116 |
1 files changed, 77 insertions, 39 deletions
diff --git a/prototypes/ShiftReducer.hs b/prototypes/ShiftReducer.hs index f40c7656..47261d65 100644 --- a/prototypes/ShiftReducer.hs +++ b/prototypes/ShiftReducer.hs | |||
@@ -41,7 +41,10 @@ data Shift a = Shift DBUsed a | |||
41 | deriving (Eq, Functor) | 41 | deriving (Eq, Functor) |
42 | 42 | ||
43 | instance Show a => Show (Shift a) where | 43 | instance Show a => Show (Shift a) where |
44 | show (Shift s a) = foldStream (:) (:":") ((\b -> if b then 'x' else '_') <$> s) ++ show a | 44 | showsPrec p (Shift s a) rest = parens (p > 0) (foldStream (:) (:":") ((\b -> if b then 'x' else '_') <$> s) ++ show a) ++ rest |
45 | |||
46 | parens True s = "(" ++ s ++ ")" | ||
47 | parens False s = s | ||
45 | 48 | ||
46 | strip (Shift _ x) = x | 49 | strip (Shift _ x) = x |
47 | 50 | ||
@@ -150,6 +153,17 @@ filterSubsts u m = streamSubsts $ filterStream (Repeat Nothing) u $ substsStream | |||
150 | 153 | ||
151 | ------------------------------------------------------------ let expressions (substitutions + expression) | 154 | ------------------------------------------------------------ let expressions (substitutions + expression) |
152 | 155 | ||
156 | {- | ||
157 | In let expressions, de bruijn indices of variables can be arbitrary, because | ||
158 | they cannot be seen from outside: | ||
159 | |||
160 | let V 3 = 'c' in (V 4) (V 3) === let V 4 = 'c' in (V 3) (V 4) === let (V 0) = 'c' in (V 4) (V 0) | ||
161 | |||
162 | So all let de bruinj indices could be numbered 0, 1, ..., n. | ||
163 | |||
164 | Question: is it a good idea to store lets in this normal form? | ||
165 | -} | ||
166 | |||
153 | data Let e a = Let (Substs e) a | 167 | data Let e a = Let (Substs e) a |
154 | deriving (Eq, Show, Functor) | 168 | deriving (Eq, Show, Functor) |
155 | 169 | ||
@@ -261,9 +275,10 @@ instance Show Lit where | |||
261 | data Exp e | 275 | data Exp e |
262 | = ELit Lit | 276 | = ELit Lit |
263 | | EVar | 277 | | EVar |
264 | | ELamD (Exp e) -- lambda with unused argument | ||
265 | | ELam (WithLet (Exp e)) -- lambda with used argument | 278 | | ELam (WithLet (Exp e)) -- lambda with used argument |
279 | -- | ELamD (Exp e) -- lambda with unused argument (optimization?) | ||
266 | | EApp (Shift (Exp e)) (Shift (Exp e)) -- application | 280 | | EApp (Shift (Exp e)) (Shift (Exp e)) -- application |
281 | | Delta String | ||
267 | | RHS e -- marks the beginning of right hand side (parts right to the equal sign) in fuction definitions | 282 | | RHS e -- marks the beginning of right hand side (parts right to the equal sign) in fuction definitions |
268 | -- e is either RHSExp or Void; Void means that this constructor cannot be used | 283 | -- e is either RHSExp or Void; Void means that this constructor cannot be used |
269 | deriving (Eq, Show) | 284 | deriving (Eq, Show) |
@@ -273,16 +288,19 @@ type RHSExp = Exp Void | |||
273 | -- left-hand-side expression (allows RHS constructor) | 288 | -- left-hand-side expression (allows RHS constructor) |
274 | type LHSExp = Exp RHSExp | 289 | type LHSExp = Exp RHSExp |
275 | 290 | ||
276 | -- TODO: make this constant time operation | 291 | rhs :: LHSExp -> RHSExp |
292 | rhs (RHS x) = x | ||
293 | |||
277 | lhs :: RHSExp -> LHSExp | 294 | lhs :: RHSExp -> LHSExp |
278 | lhs = \case | 295 | lhs = RHS |
296 | {-\case | ||
279 | ELit l -> ELit l | 297 | ELit l -> ELit l |
280 | EVar -> EVar | 298 | EVar -> EVar |
281 | ELamD e -> ELamD $ lhs e | 299 | -- ELamD e -> ELamD $ lhs e |
282 | ELam l -> ELam $ lhs <$> l | 300 | ELam l -> ELam $ lhs <$> l |
283 | EApp a b -> EApp (lhs <$> a) (lhs <$> b) | 301 | EApp a b -> EApp (lhs <$> a) (lhs <$> b) |
284 | RHS _ -> error "lhs: impossible" | 302 | RHS _ -> error "lhs: impossible" |
285 | 303 | -} | |
286 | type WithLet a = MaybeLet (Shift LHSExp) a | 304 | type WithLet a = MaybeLet (Shift LHSExp) a |
287 | 305 | ||
288 | -------------------------------------------------------- | 306 | -------------------------------------------------------- |
@@ -291,13 +309,18 @@ type SExp = Shift RHSExp | |||
291 | type LExp = WithLet RHSExp | 309 | type LExp = WithLet RHSExp |
292 | type SLExp = Shift (WithLet RHSExp) -- SLExp is *the* expression type in the user API | 310 | type SLExp = Shift (WithLet RHSExp) -- SLExp is *the* expression type in the user API |
293 | 311 | ||
312 | -- TODO | ||
313 | instance Arbitrary LExp where | ||
314 | arbitrary = NoLet <$> arbitrary | ||
315 | |||
294 | instance GetDBUsed RHSExp where | 316 | instance GetDBUsed RHSExp where |
295 | getDBUsed = \case | 317 | getDBUsed = \case |
296 | EApp (Shift ua a) (Shift ub b) -> ua <> ub | 318 | EApp (Shift ua a) (Shift ub b) -> ua <> ub |
297 | ELit{} -> mempty | 319 | ELit{} -> mempty |
298 | EVar{} -> cons True mempty | 320 | EVar{} -> cons True mempty |
299 | ELamD e -> sTail $ getDBUsed e | 321 | -- ELamD e -> sTail $ getDBUsed e |
300 | ELam e -> sTail $ getDBUsed e | 322 | ELam e -> sTail $ getDBUsed e |
323 | Delta{} -> mempty | ||
301 | 324 | ||
302 | instance Arbitrary RHSExp where | 325 | instance Arbitrary RHSExp where |
303 | arbitrary = (\(Shift _ (NoLet e)) -> e) . getSimpleExp <$> arbitrary | 326 | arbitrary = (\(Shift _ (NoLet e)) -> e) . getSimpleExp <$> arbitrary |
@@ -340,41 +363,44 @@ prop_upVar (getNonNegative -> k) (getNonNegative -> n) (getNonNegative -> i) = u | |||
340 | prop_downVar (getNonNegative -> k) (getNonNegative -> i) = down_ k (Var i) == case compare k i of LT -> Just (Var $ i-1); EQ -> Nothing; GT -> Just (Var i) | 363 | prop_downVar (getNonNegative -> k) (getNonNegative -> i) = down_ k (Var i) == case compare k i of LT -> Just (Var $ i-1); EQ -> Nothing; GT -> Just (Var i) |
341 | 364 | ||
342 | lam :: SLExp -> SLExp | 365 | lam :: SLExp -> SLExp |
343 | lam (Shift u e) = Shift (sTail u) $ if sHead u then eLam e else eLamD e | 366 | lam (Shift u e) = Shift (sTail u) $ eLam e -- TODO: if sHead u then eLam e else eLamD e |
344 | where | 367 | where |
345 | eLam (NoLet e) = NoLet $ ELam $ NoLet e | ||
346 | -- TODO: improve this by let-floating | 368 | -- TODO: improve this by let-floating |
369 | eLam = NoLet . ELam | ||
370 | {- | ||
371 | eLam (NoLet e) = NoLet $ ELam $ NoLet e | ||
347 | eLam (HasLet (Let m e)) = NoLet $ ELam (HasLet (Let m{-(filterSubsts (not <$> c) m)-} e)) | 372 | eLam (HasLet (Let m e)) = NoLet $ ELam (HasLet (Let m{-(filterSubsts (not <$> c) m)-} e)) |
348 | where | 373 | where |
349 | c = transitiveClosure (getDBUsed <$> m) $ Cons True $ Repeat False | 374 | c = transitiveClosure (getDBUsed <$> m) $ Cons True $ Repeat False |
375 | -} | ||
350 | 376 | ||
377 | {- | ||
351 | eLamD (NoLet e) = NoLet $ ELamD e | 378 | eLamD (NoLet e) = NoLet $ ELamD e |
352 | -- TODO: review | 379 | -- TODO: review |
353 | eLamD (HasLet (Let m (Shift u e))) = HasLet $ {-gc?-}Let (filterSubsts ul m) $ Shift (filterDBUsed ul u) $ ELamD e | 380 | eLamD (HasLet (Let m (Shift u e))) = HasLet $ {-gc?-}Let (filterSubsts ul m) $ Shift (filterDBUsed ul u) $ ELamD e |
354 | where | 381 | where |
355 | ul = Cons False $ Repeat True | 382 | ul = Cons False $ Repeat True |
356 | 383 | -} | |
357 | lam_test_let = lam $ lets_ m e -- == Shift s (Let m' e') | 384 | -- test without let floating, modify it after let floating is implemented |
385 | lam_test_let = lam (lets_ m e) == Shift s (NoLet $ ELam $ HasLet $ Let m' $ Shift u e') | ||
358 | where | 386 | where |
359 | f (HasLet (Let m a)) = HasLet $ Let m a | ||
360 | |||
361 | e = Var 0 `app` Var 1 `app` Var 10 | 387 | e = Var 0 `app` Var 1 `app` Var 10 |
362 | m = Map.fromList | 388 | m = Map.fromList |
363 | [ (0, Var 13) | 389 | [ (0, Var 13) |
364 | , (2, Var 1) | 390 | , (2, Var 1) |
365 | , (3, Var 1) | 391 | , (3, Var 1) -- garbage |
366 | , (10, Var 0 `app` Var 2) | 392 | , (10, Var 0 `app` Var 2) |
367 | ] | 393 | ] |
368 | {- | 394 | |
369 | s = invTrueIndices [7] | 395 | s = invTrueIndices [6, 9] |
370 | e' = f [0] | 396 | (Shift u (NoLet e')) = Var 0 `app` Var 1 `app` Var 3 |
371 | m' = Map.fromList | 397 | m' = Map.fromList |
372 | [ (0, f [2]) | 398 | [ (0, f $ Var 4) |
373 | , (1, f []) | 399 | , (2, f $ Var 1) |
374 | , (2, f [0, 1]) | 400 | , (3, f $ Var 0 `app` Var 2) |
375 | ] | 401 | ] |
376 | -} | 402 | |
377 | -- f x = Shift (invTrueIndices x) () | 403 | f (Shift u (NoLet e)) = Shift u $ lhs e |
378 | 404 | ||
379 | app :: SLExp -> SLExp -> SLExp | 405 | app :: SLExp -> SLExp -> SLExp |
380 | app (Shift ua (NoLet a)) (Shift ub (NoLet b)) | 406 | app (Shift ua (NoLet a)) (Shift ub (NoLet b)) |
@@ -398,6 +424,9 @@ app x y = f x y | |||
398 | lb'@(Let mb eb) = pushShiftLet $ Shift ulb' lb | 424 | lb'@(Let mb eb) = pushShiftLet $ Shift ulb' lb |
399 | xa = transportIntoLet lb' $ Shift ula' la | 425 | xa = transportIntoLet lb' $ Shift ula' la |
400 | 426 | ||
427 | lets :: Substs (Shift LHSExp) -> SLExp -> SLExp | ||
428 | lets m e = fmap joinLets $ maybeLet $ mkLet m e | ||
429 | |||
401 | -- TODO: handle lets inside | 430 | -- TODO: handle lets inside |
402 | lets_ :: Substs SLExp -> SLExp -> SLExp | 431 | lets_ :: Substs SLExp -> SLExp -> SLExp |
403 | lets_ m e = lets (f <$> m) e | 432 | lets_ m e = lets (f <$> m) e |
@@ -405,13 +434,6 @@ lets_ m e = lets (f <$> m) e | |||
405 | f :: SLExp -> Shift LHSExp | 434 | f :: SLExp -> Shift LHSExp |
406 | f (Shift u (NoLet e)) = Shift u $ lhs e | 435 | f (Shift u (NoLet e)) = Shift u $ lhs e |
407 | 436 | ||
408 | lets :: Substs (Shift LHSExp) -> SLExp -> SLExp | ||
409 | lets m e = fmap joinLets $ maybeLet $ mkLet m e | ||
410 | |||
411 | -- TODO | ||
412 | instance Arbitrary LExp where | ||
413 | arbitrary = NoLet <$> arbitrary | ||
414 | |||
415 | let1 :: Int -> SLExp -> SLExp -> SLExp | 437 | let1 :: Int -> SLExp -> SLExp -> SLExp |
416 | let1 i (Shift u (NoLet x)) = lets $ Map.singleton i $ Shift u $ RHS x | 438 | let1 i (Shift u (NoLet x)) = lets $ Map.singleton i $ Shift u $ RHS x |
417 | let1 i (Shift u (HasLet l)) = lets $ m <> Map.singleton i' (RHS <$> e) | 439 | let1 i (Shift u (HasLet l)) = lets $ m <> Map.singleton i' (RHS <$> e) |
@@ -486,16 +508,32 @@ pushLet' (Shift u l) = case l of | |||
486 | -- Delta_ f -> ExpL $ Delta_ f | 508 | -- Delta_ f -> ExpL $ Delta_ f |
487 | 509 | ||
488 | --------------------------------------------------------- | 510 | --------------------------------------------------------- |
511 | -} | ||
489 | 512 | ||
490 | hnf :: SLExp -> ExpL | 513 | hnf :: SLExp -> SLExp |
514 | hnf exp@(Shift u (NoLet e)) = case e of | ||
515 | EApp (Shift u' (EApp (Shift _ (Delta "add")) y)) x -> case hnf $ NoLet <$> y of | ||
516 | Int a -> case hnf $ NoLet <$> x of | ||
517 | Int b -> Int $ a + b | ||
518 | a -> error "hnf: TODO1" | ||
519 | EApp f x -> up u $ case hnf (NoLet <$> f) of | ||
520 | Shift u' (NoLet (ELam a)) -> hnf $ let1 0 (NoLet <$> x) $ Shift (Cons (sHead $ getDBUsed a) u') a -- beta reduction | ||
521 | ELam{} -> exp | ||
522 | ELit{} -> exp | ||
523 | x -> error $ "hnf: " ++ show x | ||
524 | hnf exp@(Shift u (HasLet (Let m e'@(Shift u' e)))) = case NoLet <$> e' of | ||
525 | Var i -> case Map.lookup i m of | ||
526 | Just x -> hnf $ up u $ maybeLet $ mkLet m $ rhs <$> x | ||
527 | x -> error $ "hnf2: " ++ show x | ||
528 | {- | ||
491 | hnf e = case pushLet' e of | 529 | hnf e = case pushLet' e of |
492 | (ExpL (LHS_ "add" [_, _])) -> error "ok" | 530 | (ExpL (LHS_ "add" [_, _])) -> error "ok" |
493 | x@(ExpL (EApp a b)) -> case hnf a of | 531 | x@(ExpL (EApp a b)) -> case hnf a of |
494 | ExpL (ELam a) -> hnf $ let1 0 b a | 532 | ExpL (ELam a) -> hnf $ let1 0 b a -- beta reduction |
495 | ExpL (LHS_ n acc) -> hnf $ LHS n (_ b: acc) | 533 | -- ExpL (LHS_ n acc) -> hnf $ LHS n (_ b: acc) |
496 | _ -> x | 534 | _ -> x |
497 | x -> x | 535 | x -> x |
498 | 536 | -} | |
499 | {- pattern synonyms | 537 | {- pattern synonyms |
500 | 538 | ||
501 | - BReduce e : at least one step of beta reduction, e is the result | 539 | - BReduce e : at least one step of beta reduction, e is the result |
@@ -507,17 +545,17 @@ hnf e = case pushLet' e of | |||
507 | -} | 545 | -} |
508 | 546 | ||
509 | ----------------------------------------------------------------------------------- | 547 | ----------------------------------------------------------------------------------- |
510 | -} | 548 | |
511 | idE :: SLExp | 549 | idE :: SLExp |
512 | idE = lam $ Var 0 | 550 | idE = lam $ Var 0 |
513 | {- | 551 | |
514 | add :: SLExp | 552 | add :: SLExp |
515 | add = NoLet <$> mkShift (LHS "add" []) -- $ ELam $ NoLet $ ELam $ NoLet $ Delta f) | 553 | add = hnf $ f `app` Int 10 `app` Int 20 |
516 | where | 554 | where |
517 | f [Int i, Int j] = Int $ i + j | 555 | f = NoLet <$> mkShift (Delta "add") |
518 | |||
519 | example1 = app (idE) (Int 10) | ||
520 | 556 | ||
557 | example1 = hnf $ app idE (Int 10) | ||
558 | {- | ||
521 | example2 = app (app add (Int 10)) (Int 5) | 559 | example2 = app (app add (Int 10)) (Int 5) |
522 | 560 | ||
523 | 561 | ||