emilaxelsson / syntactic

Generic representation and manipulation of abstract syntax
BSD 3-Clause "New" or "Revised" License
25 stars 13 forks source link

Sharing results / Using Let and Lambda #7

Closed crockeea closed 10 years ago

crockeea commented 10 years ago

I'm trying to figure out how to use Let/Lambda to share a result, but I get the feeling I'm rather off track.

My impression is that I should do something like the following:

f :: ASTF dom a -> ASTF dom a
f = ...

g = inj Let :$ (literal 5) :$ (inj (Lambda $ VarId 0) :$ f (inj $ Variable VarId 0))

The idea is to make a Let that binds some expression (literal 5) as the argument to a Lambda. The lambda binds its argument to var0, which is then referenced in some expression. This seems logical, and I can even make it compile, but I cannot evaluate this expression. I've tried using evaluate, but Lambda does not have an instance for Eval. I've also tried evalBind, but there is no instance (Top :< Typeable) (my domain is a compound domain, dom ~ Variable :+: Let :+: Lambda :+: ...).

Aside from the evaluation problems, I'm wary of my solution since HigherOrder.hs warns against explicitly using Variable. I'm not sure if I should be concerned with that or not. Unfortunately, I've been unable to find an example of result sharing in the Feldspar example.

What is the recommended way to create evaluatable code sharing?

emwap commented 10 years ago

I guess that you are using syntactic 1.x, which is not the same as the master branch.

In 1.x, to evaluate with binding your domain has to be a higher-order domain as in: https://github.com/emilaxelsson/syntactic/blob/1.x/examples/NanoFeldspar/Core.hs#L130

However, it is often easier to work with the sugared syntax. In the NanoFeldspar example, there is a function share which will bind an expression:

g :: (Syntax b) => (Data Index -> b) -> b
g f = share (value 5) $ \v -> f v
crockeea commented 10 years ago

How soon can we expect v2.0 on Hackage?

emilaxelsson commented 10 years ago

Here is how to do what you want in syntactic-2.0:

import Data.Proxy
import Data.Syntactic
import Data.Syntactic.TypeUniverse
import Data.Syntactic.Constructs
import Data.Syntactic.Evaluation

data Let a where Let :: Let (a :-> (a -> b) :-> Full b)

instance Render Let where renderSym Let = "Let"
instance Eval Let t where toSemSym Let = Sem (flip ($))
instance StringTree Let

type Types = IntType :+: FunType

tr :: Typeable Types a => TypeRep Types a
tr = typeRep

type Dom = BindingT Types :+: Construct :+: Let

lit :: Show a => a -> ASTF Dom a
lit a = inj (Construct (show a) a)

f :: ASTF Dom a -> ASTF Dom a
f = id

g :: ASTF Dom Int
g = inj Let :$ lit (5 :: Int) :$ (inj (LamT tr 0) :$ f (inj $ VarT tr 0))

test1 = drawAST g
test2 = evalClosed (Proxy :: Proxy Types) g

Notes:

emilaxelsson commented 10 years ago

As Anders says, it's usually better (in the user front end) to use higher-order syntax. I've now added share to NanoFeldspar in the master branch so that Anders' example works.

emilaxelsson commented 10 years ago

How soon can we expect v2.0 on Hackage?

It has been releasable since a few days ago. I'm holding it off in order not to cause confusion, since 1.x is still alive and used by Feldspar (until it gets rewritten).

Another thing is that I've removed quite some stuff from Syntactic (predefined symbols such as Let, the code motion transform, etc.) that maybe someone will be missing (though I don't know if there are any actual users :) ). I would like to be able to point to alternatives for these things. One alternative is comp-edsl, which I'm currently working on. But it's not quite ready to be released yet. As another alternative, I'm considering making a separate package syntactic-utils containing stuff that has been removed.

Let me know if you need syntactic-2.0 released urgently.

crockeea commented 10 years ago

I've got a satisfactory solution for this with syntactic-2.0, so I'll post it here in case it helps someone else: https://gist.github.com/crockeea/920071d88fb4f02c6caa