[<<][meta][>>][..]
Sat Oct 29 18:02:59 EDT 2011

Next

_letrec
Similar problem: collection of references.

Probably can just reuse the Struct mechanism, though this requires to
use Var for function bindings.  Trouble with that is type annotation
for Var.

That's not exactly free..  To some extent a more liberal syntax is
simpler to implement, though type annotation for higher order
functions is extra work.

Why did I change to more liberal syntax?  To be able to
App (Lambda ...) [...]

Yeah, it's messy..

Maybe let it sit for a while.

Maybe I can actually not implement this for now as it's not really
necessary for making the Pd/SM code run; that just needs single
recursion for loops.

The _letrec has the same problem as _lambda earlier: it's not monadic.

Got it working, but it requires some heavy type annotation:

t17def :: Code (Tint -> MCode Tint) -> MCode (Code (Tint -> MCode Tint))
t17def = \f -> _lambda $ (\x -> do
                             x2 <- mul x x
                             _app f x2)
t17exp = \f -> _app f (lit 123)

t17 = term $ _letrec t17def t17exp

> t17
Let (Var i "r2" 0) 
      (Op i "mul" [Ref (Var i "r1" 0),
                   Ref (Var i "r1" 0)])
  (LetRec [(Fun "f\"r0\"",
              Lambda [Var i "r1" 0] 
                (App (FRef (Fun "f\"r0\"")) 
                     [Ref (Var i "r2" 0)]))]
     (App (FRef (Fun "f\"r0\"")) [Lit i "123"]))


All kinds of things wrong with this..  Let's first fix the FRef
printing though.  Then make a proper insert for the LetRec.



insertLetRec ref (SC cDef) (SC cExpr) = SC cTerm where
  cTerm s k = cDef s k' where -- compile definition, then goto k'
    k' s' (Code def) = cExpr s' k'' where -- compile body, then goto k''
      k'' s (Code expr) = k s' $ Code $ LetRec [(ref, def)] expr  -- return wrapped form

instance Loop Term MCode' Code where
  _letrec open body = do
    [fName] <- nameList "fun" 1
    let fRef  = Fun $ fName
        fCode = Code $ FRef fRef -- How to correctly type this?
      in do
      insertLetRec fRef (open fCode) (body fCode)

Doesn't seem to work...

> t17
Let (Var i "r2" 0) (Op i "mul" [Ref (Var i "a1" 0),Ref (Var i "a1" 0)]) 
 (LetRec [(Fun "fun0",Lambda [Var i "a1" 0] 
             (App (FRef (Fun "fun0")) [Ref (Var i "r2" 0)]))] 
   (App (FRef (Fun "fun0")) [Lit i "123"]))


I don't know what I'm doing.  It seems to be different from both the
Let and Lambda continuation juggling.

Maybe the problem is elsewhere.  Maybe Lambda isn't right..  All the
evaluation juggling should really be done already at this point.  This
is just using bind to obtain results in the monad and wrap them in
LetRec:

instance Loop Term MCode' Code where
  _letrec def expr = do
    [fName] <- nameList "fun" 1
    let ref  = Fun $ fName
        fref = Code $ FRef ref
      in do
      (Code def') <- def fref
      (Code expr') <- expr fref
      return $ Code $ LetRec [(ref, def')] expr'
  

So what's wrong with Lambda? Trouble is that evaluation of the body
really inserts things at the toplevel, so how to delimit that
toplevel?  In some way, that Lambda expression is really a separate
world, so maybe it should be run as a separate computation?

I had some trouble with the return type doing that.. How to fix?  Can
we keep the monad's result open?  I don't think we can because of this
naked Let.. in insertLet.

This implementation seems to work:

-- Run the cBody computation separate from our current context by
-- calling cBody directly.  This is necessary because insertLet would
-- mess with our continuation.

-- Note that because the toplevel continuation gets lost due to Let
-- insertion, we can't keep track of the compilation state that
-- threads through the lambda expression.  This means the variable
-- naming scheme will fork.  This doesn't seem to be a problem since
-- all variables used inside the Lambda are in an isolated context.
  
insertLambda vars (SC cBody) = SC cTerm where
  cTerm s k = k s $ Code $ Lambda vars body where
    body = cBody s $ \s (Code b) -> b
    

> t17


LetRec [(Fun "fun0",Lambda [Var i "a1" 0] 
           (Let (Var i "r2" 0)
              (Op i "mul" [Ref (Var i "a1" 0),
                           Ref (Var i "a1" 0)])
             (App (FRef (Fun "fun0")) [Ref (Var i "r2" 0)])))] 
   (App (FRef (Fun "fun0")) [Lit i "123"])


Interesting stuff!



t18 = term $ _letrec 
      t17def $
      \f -> do 
        x <- mul (lit 3) (lit 4)
        y <- mul x x
        _app f y
> t18

Let (Var i "r2" 0) (Op i "mul" [Lit i "3",Lit i "4"]) (Let (Var i "r3" 0) (Op i "mul" [Ref (Var i "r2" 0),Ref (Var i "r2" 0)]) (LetRec [(Fun "fun0",Lambda [Var i "a1" 0] (Let (Var i "r2" 0) (Op i "mul" [Ref (Var i "a1" 0),Ref (Var i "a1" 0)]) (App (FRef (Fun "fun0")) [Ref (Var i "r2" 0)])))] (App (FRef (Fun "fun0")) [Ref (Var i "r3" 0)])))

And wrong again..

Looks like the evaluation of the second expression needs to happen in
a delimited context also.  EDIT: see mBlock next post.


t17def :: Code (Tint -> MCode Tint) -> MCode (Code (Tint -> MCode Tint))
t17def = \f -> _lambda $ (\x -> do
                             x2 <- mul x x
                             _app f x2)
t18 = term $ _letrec 
      t17def $
      \f -> do 
        x <- mul (lit 3) (lit 4)
        y <- mul x x
        _app f y
  
> t18
LetRec [(Fun "fun0",Lambda [Var i "a1" 0] 
          (Let (Var i "r2" 0) (Op i "mul" [Ref (Var i "a1" 0), Ref (Var i "a1" 0)]) 
          (App (FRef (Fun "fun0")) [Ref (Var i "r2" 0)])))] 
   (Let (Var i "r2" 0) (Op i "mul" [Lit i "3",Lit i "4"]) 
   (Let (Var i "r3" 0) (Op i "mul" [Ref (Var i "r2" 0),Ref (Var i "r2" 0)])
   (App (FRef (Fun "fun0")) [Ref (Var i "r3" 0)])))




[Reply][About]
[<<][meta][>>][..]