2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-2000
4 \section{Generate Java}
6 Name mangling for Java.
9 Haskell has a number of namespaces. The Java translator uses
10 the standard Haskell mangles (see OccName.lhs), and some extra
13 All names are hidden inside packages.
16 - becomes a first level java package.
17 - can not clash with java, because haskell modules are upper case,
18 java default packages are lower case.
21 - these turn into classes
22 - java keywords (eg. private) have the suffix "zdk" ($k) added.
25 - These have a base class, so need to appear in the
26 same name space as other object. for example data Foo = Foo
27 - We add a postfix to types: "zdt" ($t)
28 - Types are upper case, so never clash with keywords
31 - There are tWO classes for each Constructor
32 (1) - Class with the payload extends the relevent datatype baseclass.
33 - This class has the prefix zdw ($W)
34 (2) - Constructor *wrapper* just use their own name.
35 - Constructors are upper case, so never clash with keywords
36 - So Foo would become 2 classes.
37 * Foo -- the constructor wrapper
38 * zdwFoo -- the worker, with the payload
41 module JavaGen( javaGen ) where
45 import Literal ( Literal(..) )
46 import Id ( Id, isDataConId_maybe, isId, idName, isDeadBinder, idPrimRep )
47 import Name ( NamedThing(..), getOccString, isGlobalName
49 import PrimRep ( PrimRep(..) )
50 import DataCon ( DataCon, dataConRepArity, dataConRepArgTys, dataConId )
51 import qualified TypeRep
53 import qualified CoreSyn
54 import CoreSyn ( CoreBind, CoreExpr, CoreAlt, CoreBndr,
55 Bind(..), Alt, AltCon(..), collectBinders, isValArg
57 import CoreUtils( exprIsValue, exprIsTrivial )
58 import Module ( Module, moduleString )
59 import TyCon ( TyCon, isDataTyCon, tyConDataCons )
62 #include "HsVersions.h"
68 javaGen :: Module -> [Module] -> [TyCon] -> [CoreBind] -> CompilationUnit
70 javaGen mod import_mods tycons binds
71 = id {-liftCompilationUnit-} package
73 decls = [Import "haskell.runtime.*"] ++
74 [Import (moduleString mod) | mod <- import_mods] ++
75 concat (map javaTyCon (filter isDataTyCon tycons)) ++
76 concat (map javaTopBind binds)
77 package = Package (moduleString mod) decls
81 %************************************************************************
83 \subsection{Type declarations}
85 %************************************************************************
88 javaTyCon :: TyCon -> [Decl]
89 -- public class List {}
91 -- public class $wCons extends List {
92 -- Object f1; Object f2
94 -- public class $wNil extends List {}
97 = tycon_jclass : concat (map constr_class constrs)
99 constrs = tyConDataCons tycon
100 tycon_jclass_jname = javaGlobTypeName tycon ++ "zdc"
101 tycon_jclass = Class [Public] (shortName tycon_jclass_jname) [] [] []
103 constr_class data_con
104 = [ Class [Public] (shortName constr_jname) [tycon_jclass_jname] []
105 (field_decls ++ [cons_meth,debug_meth])
108 constr_jname = javaConstrWkrName data_con
109 constr_jtype = javaConstrWkrType data_con
111 field_names = constrToFields data_con
112 field_decls = [ Field [Public] n Nothing
116 cons_meth = mkCons (shortName constr_jname) field_names
118 debug_meth = Method [Public] (Name "toString" stringType)
121 ( [ Declaration (Field [] txt Nothing) ]
126 getOccString data_con ++
135 (Op (Var n) "+" litSp)
140 ++ [ Return (Op (Var txt)
148 txt = Name "__txt" stringType
151 mkNew :: Type -> [Expr] -> Expr
152 mkNew t@(PrimType primType) [] = error "new primitive???"
153 mkNew t@(Type _) es = New t es Nothing
154 mkNew _ _ = error "new with strange arguments"
156 constrToFields :: DataCon -> [Name]
157 constrToFields cons =
159 | (i,t) <- zip [1..] (map javaTauType (dataConRepArgTys cons))
162 mkCons :: TypeName -> [Name] -> Decl
163 mkCons name args = Constructor [Public] name
164 [ Parameter [] n | n <- args ]
165 [ ExprStatement (Assign
171 mkStr :: String -> Expr
172 mkStr str = Literal (StringLit str)
175 %************************************************************************
177 \subsection{Bindings}
179 %************************************************************************
182 javaTopBind :: CoreBind -> [Decl]
183 javaTopBind (NonRec bndr rhs) = [java_top_bind bndr rhs]
184 javaTopBind (Rec prs) = [java_top_bind bndr rhs | (bndr,rhs) <- prs]
186 java_top_bind :: Id -> CoreExpr -> Decl
187 -- public class f implements Code {
188 -- public Object ENTER() { ...translation of rhs... }
190 java_top_bind bndr rhs
191 = Class [Public] (shortName (javaGlobTypeName bndr))
192 [] [codeName] [enter_meth]
194 enter_meth = Method [Public] enterName [vmArg] [excName]
195 (javaExpr vmRETURN rhs)
199 %************************************************************************
201 \subsection{Expressions}
203 %************************************************************************
206 javaVar :: Id -> Expr
207 javaVar v | isGlobalName (idName v) = mkNew (javaGlobType v) []
208 | otherwise = Var (javaName v)
210 javaLit :: Literal.Literal -> Expr
211 javaLit (MachInt i) = Literal (IntLit (fromInteger i))
212 javaLit (MachChar c) = Literal (CharLit c)
213 javaLit other = pprPanic "javaLit" (ppr other)
215 javaExpr :: (Expr -> Expr) -> CoreExpr -> [Statement]
216 -- Generate code to apply the value of
217 -- the expression to the arguments aleady on the stack
218 javaExpr r (CoreSyn.Var v) = [Return (r (javaVar v))]
219 javaExpr r (CoreSyn.Lit l) = [Return (r (javaLit l))]
220 javaExpr r (CoreSyn.App f a) = javaApp r f [a]
221 javaExpr r e@(CoreSyn.Lam _ _) = javaLam r (collectBinders e)
222 javaExpr r (CoreSyn.Case e x alts) = javaCase r e x alts
223 javaExpr r (CoreSyn.Let bind body) = javaBind bind ++ javaExpr r body
224 javaExpr r (CoreSyn.Note _ e) = javaExpr r e
226 javaCase :: (Expr -> Expr) -> CoreExpr -> Id -> [CoreAlt] -> [Statement]
227 -- case e of x { Nil -> r1
230 -- final Object x = VM.WHNF(...code for e...)
231 -- else if x instance_of Nil {
232 -- ...translation of r1...
233 -- } else if x instance_of Cons {
234 -- final Object p = ((Cons) x).f1
235 -- final Object q = ((Cons) x).f2
236 -- ...translation of r2...
237 -- } else return null
240 = [var [Final] (javaName x) (vmWHNF (javaArg e)),
241 IfThenElse (map mk_alt alts) Nothing]
243 mk_alt (DEFAULT, [], rhs) = (true, Block (javaExpr r rhs))
244 mk_alt (DataAlt d, bs, rhs) = (instanceOf x d, Block (bind_args d bs ++ javaExpr r rhs))
245 mk_alt alt@(LitAlt lit, [], rhs)
246 = (eqLit lit , Block (javaExpr r rhs))
247 mk_alt alt@(LitAlt _, _, _) = pprPanic "mk_alt" (ppr alt)
250 eqLit (MachInt n) = Op (Literal (IntLit n))
253 eqLit other = pprPanic "eqLit" (ppr other)
255 bind_args d bs = [var [Final] (javaName b)
256 (Access (Cast (javaConstrWkrType d) (javaVar x)
259 | (b,f) <- filter isId bs
260 `zip` (constrToFields d)
261 , not (isDeadBinder b)
264 javaBind (NonRec x rhs)
268 final Object x = new Thunk( new Code() { ...code for rhs_x... } )
270 = [var [Final] (javaLocName x objectType)
271 (newThunk (newCode (javaExpr vmRETURN rhs)))
275 {- rec { x = ...rhs_x...; y = ...rhs_y... }
277 class x implements Code {
279 public Object ENTER() { ...code for rhs_x...}
283 final x x_inst = new x();
286 final Thunk x = new Thunk( x_inst );
293 = (map mk_class prs) ++ (map mk_inst prs) ++
294 (map mk_thunk prs) ++ concat (map mk_knot prs)
296 mk_class (b,r) = Declaration (Class [] class_name [] [codeName] stmts)
298 class_name = javaLocTypeName b
299 stmts = [Field [] (javaLocName b codeType) Nothing | (b,_) <- prs] ++
300 [Method [Public] enterName [vmArg] [excName] (javaExpr vmRETURN r)]
302 mk_inst (b,r) = var [Final] (javaInstName b)
303 (mkNew (javaGlobType b) [])
305 mk_thunk (b,r) = var [Final] (javaLocName b thunkType)
306 (New thunkType [Var (javaInstName b)] Nothing)
308 mk_knot (b,_) = [ ExprStatement (Assign lhs rhs)
310 let lhs = Access (Var (javaInstName b)) (javaName b'),
311 let rhs = Var (javaName b')
316 javaLam :: (Expr -> Expr) -> ([CoreBndr], CoreExpr) -> [Statement]
317 javaLam r (bndrs, body)
318 | null val_bndrs = javaExpr r body
320 = vmCOLLECT (length val_bndrs) this
321 ++ [var [Final] n (vmPOP t) | n@(Name _ t) <- val_bndrs]
324 val_bndrs = map javaName (filter isId bndrs)
326 javaApp :: (Expr -> Expr) -> CoreExpr -> [CoreExpr] -> [Statement]
327 javaApp r (CoreSyn.App f a) as = javaApp r f (a:as)
328 javaApp r (CoreSyn.Var f) as
329 = case isDataConId_maybe f of {
330 Just dc | length as == dataConRepArity dc
331 -> -- Saturated constructors
332 [Return (New (javaGlobType f) (javaArgs as) Nothing)]
333 ; other -> -- Not a saturated constructor
334 java_apply r (CoreSyn.Var f) as
337 javaApp r f as = java_apply r f as
339 java_apply :: (Expr -> Expr) -> CoreExpr -> [CoreExpr] -> [Statement]
340 java_apply r f as = [ExprStatement (vmPUSH arg) | arg <- javaArgs as] ++ javaExpr r f
341 javaArgs :: [CoreExpr] -> [Expr]
342 javaArgs args = [javaArg a | a <- args, isValArg a]
344 javaArg :: CoreExpr -> Expr
345 javaArg (CoreSyn.Type t) = pprPanic "javaArg" (ppr t)
346 javaArg e | exprIsValue e || exprIsTrivial e = newCode (javaExpr id e)
347 | otherwise = newThunk (newCode (javaExpr id e))
350 %************************************************************************
352 \subsection{Helper functions}
354 %************************************************************************
359 true = Var (Name "true" (PrimType PrimBoolean))
361 vmCOLLECT :: Int -> Expr -> [Statement]
363 vmCOLLECT n e = [ExprStatement
364 (Call varVM collectName
365 [ Literal (IntLit (toInteger n))
371 vmPOP :: Type -> Expr
372 vmPOP ty = Call varVM (Name ("POP" ++ suffix ty) ty) []
374 vmPUSH :: Expr -> Expr
375 vmPUSH e = Call varVM (Name ("PUSH" ++ suffix (exprType e)) void) [e]
377 vmRETURN :: Expr -> Expr
380 PrimType _ -> Call varVM (Name ("RETURN" ++ suffix (exprType e))
387 var :: [Modifier] -> Name -> Expr -> Statement
388 var ms field_name value = Declaration (Field ms field_name (Just value))
390 vmWHNF :: Expr -> Expr
391 vmWHNF e = Call varVM whnfName [e]
393 suffix :: Type -> String
394 suffix (PrimType t) = primName t
397 primName :: PrimType -> String
398 primName PrimInt = "int"
399 primName PrimChar = "char"
400 primName _ = error "unsupported primitive"
405 instanceOf :: Id -> DataCon -> Expr
406 instanceOf x data_con
407 = InstanceOf (Var (javaName x)) (javaConstrWkrType data_con)
409 newCode :: [Statement] -> Expr
410 newCode [Return e] = e
411 newCode stmts = New codeType [] (Just [Method [Public] enterName [vmArg] [excName] stmts])
413 newThunk :: Expr -> Expr
414 newThunk e = New thunkType [e] Nothing
417 vmArg = Parameter [Final] vmName
420 %************************************************************************
422 \subsection{Haskell to Java Types}
424 %************************************************************************
427 exprType (Var (Name _ t)) = t
428 exprType (Literal lit) = litType lit
429 exprType (Cast t _) = t
430 exprType (New t _ _) = t
431 exprType _ = error "can't figure out an expression type"
433 litType (IntLit i) = PrimType PrimInt
434 litType (CharLit i) = PrimType PrimChar
435 litType (StringLit i) = error "<string?>"
438 %************************************************************************
440 \subsection{Name mangling}
442 %************************************************************************
445 codeName, excName, thunkName :: TypeName
446 codeName = "haskell.runtime.Code"
447 thunkName = "haskell.runtime.Thunk"
448 excName = "java.lang.Exception"
450 enterName, vmName,thisName,collectName, whnfName :: Name
451 enterName = Name "ENTER" objectType
452 vmName = Name "VM" vmType
453 thisName = Name "this" (Type "<this>")
454 collectName = Name "COLLECT" void
455 whnfName = Name "WNNF" objectType
457 fieldName :: Int -> Type -> Name -- Names for fields of a constructor
458 fieldName n ty = Name ("f" ++ show n) ty
460 -- TODO: change to idToJavaName :: Id -> Name
462 javaLocName :: Id -> Type -> Name
463 javaLocName n t = Name (getOccString n) t
465 javaName :: Id -> Name
466 javaName n = if isGlobalName n'
467 then Name (javaGlobTypeName n)
469 else Name (getOccString n)
474 -- TypeName's are always global
475 javaGlobTypeName :: NamedThing a => a -> TypeName
476 javaGlobTypeName n = (moduleString (nameModule n') ++ "." ++ getOccString n)
480 javaLocTypeName :: NamedThing a => a -> TypeName
481 javaLocTypeName n = (moduleString (nameModule n') ++ "." ++ getOccString n)
485 -- this is used for getting the name of a class when defining it.
486 shortName :: TypeName -> TypeName
487 shortName = reverse . takeWhile (/= '.') . reverse
489 -- The function that makes the constructor name
490 javaConstrWkrName :: DataCon -> TypeName
491 javaConstrWkrName con = javaGlobTypeName (dataConId con)
493 -- Makes x_inst for Rec decls
494 javaInstName :: NamedThing a => a -> Name
495 javaInstName n = Name (getOccString n ++ "_inst") (Type "<inst>")
498 %************************************************************************
500 \subsection{Types and type mangling}
502 %************************************************************************
506 codeType, thunkType, valueType :: Type
507 codeType = Type codeName
508 thunkType = Type thunkName
509 valueType = Type "haskell.runtime.Value"
510 vmType = Type "haskell.runtime.VMEngine"
513 objectType, stringType :: Type
514 objectType = Type "java.lang.Object"
515 stringType = Type "java.lang.String"
518 void = PrimType PrimVoid
521 inttype = PrimType PrimInt
524 chartype = PrimType PrimChar
526 -- This is where we map from type to possible primitive
527 mkType "PrelGHC.Intzh" = inttype
528 mkType "PrelGHC.Charzh" = chartype
529 mkType other = Type other
531 -- This mapping a global haskell name (typically a function name)
532 -- to the name of the class that handles it.
533 -- The name must be global. So foo in module Test maps to (Type "Test.foo")
534 -- TODO: change to Id
536 javaGlobType :: NamedThing a => a -> Type
537 javaGlobType n | '.' `notElem` name
538 = error ("not using a fully qualified name for javaGlobalType: " ++ name)
541 where name = javaGlobTypeName n
543 -- This takes an id, and finds the ids *type* (for example, Int, Bool, a, etc).
544 javaType :: Id -> Type
545 javaType id = case (idPrimRep id) of
547 _ -> if isGlobalName (idName id)
548 then Type (javaGlobTypeName id)
549 else objectType -- TODO: ?? for now ??
551 -- This is used to get inside constructors, to find out the types
552 -- of the payload elements
553 javaTauType :: Type.TauType -> Type
554 javaTauType (TypeRep.TyConApp tycon _) = javaGlobType tycon
555 javaTauType (TypeRep.NoteTy _ t) = javaTauType t
556 javaTauType _ = objectType
558 -- The function that makes the constructor name
559 javaConstrWkrType :: DataCon -> Type
560 javaConstrWkrType con = Type (javaConstrWkrName con)
563 %************************************************************************
565 \subsection{Class Lifting}
567 %************************************************************************
569 This is a very simple class lifter. It works by carrying inwards a
570 list of bound variables (things that might need to be passed to a
572 * Any variable references is check with this list, and if it is
573 bound, then it is not top level, external reference.
574 * This means that for the purposes of lifting, it might be free
575 inside a lifted inner class.
576 * We remember these "free inside the inner class" values, and
577 use this list (which is passed, via the monad, outwards)
585 combine :: [Name] -> [Name] -> [Name]
586 combine [] names = names
587 combine names [] = names
588 combine (name:names) (name':names')
589 | name < name' = name : combine names (name':names')
590 | name > name' = name' : combine (name:names) names'
591 | name == name = name : combine names names'
592 | otherwise = error "names are not a total order"
594 both :: [Name] -> [Name] -> [Name]
597 both (name:names) (name':names')
598 | name < name' = both names (name':names')
599 | name > name' = both (name:names) names'
600 | name == name = name : both names names'
601 | otherwise = error "names are not a total order"
603 combineEnv :: Env -> [Name] -> Env
604 combineEnv (Env bound env) new = Env (bound `combine` new) env
606 addTypeMapping :: Name -> Name -> [Name] -> Env -> Env
607 addTypeMapping origName newName frees (Env bound env)
608 = Env bound ((origName,(newName,frees)) : env)
610 -- This a list of bound vars (with types)
611 -- and a mapping from types (?) to (result * [arg]) pairs
612 data Env = Env Bound [(Name,(Name,[Name]))]
615 LifterM { unLifterM ::
619 , [Decl] -- lifted classes
624 instance Monad LifterM where
625 return a = LifterM (\ n s -> (a,[],[],s))
626 (LifterM m) >>= fn = LifterM (\ n s ->
629 -> case unLifterM (fn a) n s of
630 (a,frees2,lifted2,s) -> ( a
631 , combine frees frees2
636 access :: Env -> Name -> LifterM ()
637 access env@(Env bound _) name
638 | name `elem` bound = LifterM (\ n s -> ((),[name],[],s))
639 | otherwise = return ()
641 scopedName :: Name -> LifterM a -> LifterM a
642 scopedName name (LifterM m) =
645 (a,frees,lifted,_) -> (a,frees,lifted,s)
648 genAnonInnerClassName :: LifterM Name
649 genAnonInnerClassName = LifterM (\ n s ->
657 genInnerClassName :: Name -> LifterM Name
658 genInnerClassName name = LifterM (\ n s ->
666 getFrees :: LifterM a -> LifterM (a,Frees)
667 getFrees (LifterM m) = LifterM (\ n s ->
669 (a,frees,lifted,n) -> ((a,frees),frees,lifted,n)
672 rememberClass :: Decl -> LifterM ()
673 rememberClass decl = LifterM (\ n s -> ((),[],[decl],s))
676 liftCompilationUnit :: CompilationUnit -> CompilationUnit
677 liftCompilationUnit (Package name ds) =
678 Package name (concatMap liftCompilationUnit' ds)
680 liftCompilationUnit' :: Decl -> [Decl]
681 liftCompilationUnit' decl =
682 case unLifterM (liftDecls True (Env [] []) [decl]) [] 1 of
683 (ds,_,ds',_) -> ds ++ ds'
686 -- The bound vars for the current class have
687 -- already be captured before calling liftDecl,
688 -- because they are in scope everywhere inside the class.
690 liftDecl :: Bool -> Env -> Decl -> LifterM Decl
691 liftDecl = \ top env decl ->
693 { Import n -> return (Import n)
695 do { e <- liftMaybeExpr env e
696 ; return (Field mfs (liftType env t) n e)
698 ; Constructor mfs n as ss ->
699 do { let newBound = getBoundAtParameters as
700 ; (ss,_) <- liftStatements (combineEnv env newBound) ss
701 ; return (Constructor mfs n (liftParameters env as) ss)
703 ; Method mfs t n as ts ss ->
704 do { let newBound = getBoundAtParameters as
705 ; (ss,_) <- liftStatements (combineEnv env newBound) ss
706 ; return (Method mfs (liftType env t) n (liftParameters env as) ts ss)
708 ; Comment s -> return (Comment s)
709 ; Interface mfs n is ms -> error "interfaces not supported"
710 ; Class mfs n x is ms ->
711 do { let newBound = getBoundAtDecls ms
713 (liftDecls False (combineEnv env newBound) ms)
714 ; return (Class mfs n x is ms)
718 liftDecls :: Bool -> Env -> [Decl] -> LifterM [Decl]
719 liftDecls top env = mapM (liftDecl top env)
721 getBoundAtDecls :: [Decl] -> Bound
722 getBoundAtDecls = foldr combine [] . map getBoundAtDecl
725 getBoundAtDecl :: Decl -> Bound
726 getBoundAtDecl (Field _ _ n _) = [n]
727 getBoundAtDecl _ = []
729 getBoundAtParameters :: [Parameter] -> Bound
730 getBoundAtParameters = foldr combine [] . map getBoundAtParameter
733 getBoundAtParameter :: Parameter -> Bound
734 getBoundAtParameter (Parameter _ _ n) = [n]
736 liftStatement :: Env -> Statement -> LifterM (Statement,Env)
737 liftStatement = \ env stmt ->
739 { Skip -> return (stmt,env)
740 ; Return e -> do { e <- liftExpr env e
741 ; return (Return e,env)
743 ; Block ss -> do { (ss,env) <- liftStatements env ss
744 ; return (Block ss,env)
746 ; ExprStatement e -> do { e <- liftExpr env e
747 ; return (ExprStatement e,env)
749 ; Declaration decl@(Field mfs t n e) ->
750 do { e <- liftMaybeExpr env e
751 ; return ( Declaration (Field mfs t n e)
752 , env `combineEnv` getBoundAtDecl decl
755 ; Declaration decl@(Class mfs n x is ms) ->
756 do { innerName <- genInnerClassName n
757 ; frees <- liftClass env innerName ms x is
758 ; return ( Declaration (Comment ["lifted " ++ n])
759 , addTypeMapping n innerName frees env
762 ; Declaration d -> error "general Decl not supported"
763 ; IfThenElse ecs s -> ifthenelse env ecs s
764 ; Switch e as d -> error "switch not supported"
768 -> [(Expr,Statement)]
770 -> LifterM (Statement,Env)
771 ifthenelse env pairs may_stmt =
772 do { let (exprs,stmts) = unzip pairs
773 ; exprs <- liftExprs env exprs
774 ; (stmts,_) <- liftStatements env stmts
775 ; may_stmt <- case may_stmt of
776 Just stmt -> do { (stmt,_) <- liftStatement env stmt
779 Nothing -> return Nothing
780 ; return (IfThenElse (zip exprs stmts) may_stmt,env)
783 liftStatements :: Env -> [Statement] -> LifterM ([Statement],Env)
784 liftStatements env [] = return ([],env)
785 liftStatements env (s:ss) =
786 do { (s,env) <- liftStatement env s
787 ; (ss,env) <- liftStatements env ss
792 liftExpr :: Env -> Expr -> LifterM Expr
793 liftExpr = \ env expr ->
795 { Var n t -> do { access env n
798 ; Literal l _ -> return expr
799 ; Cast t e -> do { e <- liftExpr env e
800 ; return (Cast (liftType env t) e)
802 ; Access e n -> do { e <- liftExpr env e
803 -- do not consider n as an access, because
804 -- this is a indirection via a reference
805 ; return (Access e n)
807 ; Assign l r -> do { l <- liftExpr env l
808 ; r <- liftExpr env r
809 ; return (Assign l r)
811 ; InstanceOf e t -> do { e <- liftExpr env e
812 ; return (InstanceOf e (liftType env t))
814 ; Call e n es -> do { e <- liftExpr env e
815 ; es <- mapM (liftExpr env) es
816 ; return (Call e n es)
818 ; Op e1 o e2 -> do { e1 <- liftExpr env e1
819 ; e2 <- liftExpr env e2
820 ; return (Op e1 o e2)
822 ; New n es ds -> new env n es ds
825 liftParameter env (Parameter ms t n) = Parameter ms (liftType env t) n
826 liftParameters env = map (liftParameter env)
828 liftExprs :: Env -> [Expr] -> LifterM [Expr]
829 liftExprs = mapM . liftExpr
831 liftMaybeExpr :: Env -> (Maybe Expr) -> LifterM (Maybe Expr)
832 liftMaybeExpr env Nothing = return Nothing
833 liftMaybeExpr env (Just stmt) = do { stmt <- liftExpr env stmt
838 new :: Env -> Type -> [Expr] -> Maybe [Decl] -> LifterM Expr
839 new env@(Env _ pairs) typ args Nothing =
840 do { args <- liftExprs env args
841 ; return (listNew env typ args)
843 new env typ [] (Just inner) =
845 do { innerName <- genAnonInnerClassName
846 ; frees <- liftClass env innerName inner [] [unType typ]
847 ; return (New (Type (innerName))
848 [ Var name (Type "<arg>") | name <- frees ] Nothing)
850 where unType (Type name) = name
851 unType _ = error "incorrect type style"
853 new env typ _ (Just inner) = error "cant handle inner class with args"
855 liftClass :: Env -> Name -> [Decl] -> [Name] -> [Name] -> LifterM [ Name ]
856 liftClass env@(Env bound _) innerName inner xs is =
857 do { let newBound = getBoundAtDecls inner
859 getFrees (liftDecls False (env `combineEnv` newBound) inner)
860 ; let trueFrees = filter (\ xs -> xs /= "VM") (both frees bound)
861 ; let freeDefs = [ Field [Final] objectType n Nothing | n <- trueFrees ]
862 ; let cons = mkCons innerName [(name,objectType) | name <- trueFrees ]
863 ; let innerClass = Class [] innerName xs is (freeDefs ++ [cons] ++ inner)
864 ; rememberClass innerClass
868 liftType :: Env -> Type -> Type
869 liftType (Env _ env) typ@(Type name)
870 = case lookup name env of
872 Just (nm,_) -> Type nm
875 liftNew :: Env -> Type -> [Expr] -> Expr
876 liftNew (Env _ env) typ@(Type name) exprs
877 = case lookup name env of
878 Nothing -> New typ exprs Nothing
879 Just (nm,args) | null exprs
880 -> New (Type nm) (map (\ v -> Var v (Type "<arg>")) args) Nothing
881 _ -> error "pre-lifted constructor with arguments"
882 listNew _ typ exprs = New typ exprs Nothing