
On Fri, Feb 22, 2008 at 2:42 PM, Daniel GorĂn
On Feb 21, 2008, at 7:55 PM, Roel van Dijk wrote:
Your solutions allows a bit more but fails with the equivalent of
def foo(): for i in range(10): if i == 6: return None
The loop context 'overwrites' the function context which makes the return statement illegal. I think I need a type level list.
i see. how about this?
if_ = If [(IntLit 6, Suite [] [Break])] (Just $ Suite [] [Return]) while_ = While (IntLit 6) (Suite [] [if_]) Nothing while2_ = While (IntLit 6) (Suite [] [Return]) Nothing foo = FunDecl $ Suite [] [while_, while2_]
p = Program [foo]
newtype Ident = Id String
data BinOp = Add | Sub
data Exp = IntLit Integer | BinOpExp BinOp Exp Exp
data Ctx reqloop reqfun data True data False
data Statement ctx where If :: [(Exp, Suite (Ctx reqloop reqfun))] -> Maybe (Else (Ctx reqloop reqfun)) -> Statement (Ctx reqloop reqfun) While :: Exp -> (Suite (Ctx True reqfun)) -> Maybe (Else (Ctx True reqfun)) -> Statement (Ctx reqloop reqfun) Pass :: Statement (Ctx reqloop reqfun) Break :: Statement (Ctx True reqfun) Return :: Statement (Ctx reqloop True) FunDecl :: Suite (Ctx False reqfun) -> Statement (Ctx False False)
newtype Global = Global [Ident]
data Suite ctx = Suite [Global] [Statement ctx]
type Else ctx = Suite ctx
newtype Program = Program [Statement (Ctx False False)]
Ah, you set a specific context when needed. Very nice. Although I had to remove the Ctx type. Otherwise I need pattern matching at the type level to bind the reqLoop and reqFun type variables (is such a thing even possible?): data Statement (Ctx reqLoop reqFun) where .... Now I simple pass 2 type variables to my statements: data Statement reqLoop reqFun where .... I now have a complete Python AST and pretty printer. Onwards towards a parser! Thanks again, Roel