1{-# LANGUAGE PatternGuards #-}
2module IRTS.CodegenJava (codegenJava) where
4import Idris.Core.TT hiding (mkApp)
5import IRTS.CodegenCommon
6import IRTS.Java.ASTBuilding
8import IRTS.Java.Mangling
9import IRTS.Java.Pom (pomString)
15import Control.Applicative hiding (Const)
18import Control.Monad.Error
19import qualified Control.Monad.Trans as T
20import Control.Monad.Trans.State
21import Data.List (foldl', isSuffixOf)
22import qualified Data.Text as T
23import qualified Data.Text.IO as TIO
24import qualified Data.Vector.Unboxed as V
25import Language.Java.Parser
26import Language.Java.Pretty
27import Language.Java.Syntax hiding (Name)
28import qualified Language.Java.Syntax as J
29import System.Directory
35-----------------------------------------------------------------------
37codegenJava :: [(Name, SExp)] -> -- initialization of globals
38 [(Name, SDecl)] -> -- decls
39 FilePath -> -- output file name
40 [String] -> -- headers
44codegenJava globalInit defs out hdrs libs exec =
45 withTgtDir exec out (codegenJava' exec)
47 codegenJava' :: OutputType -> FilePath -> IO ()
48 codegenJava' Raw tgtDir = do
49 srcDir <- prepareSrcDir exec tgtDir
50 generateJavaFile globalInit defs hdrs srcDir out
51 codegenJava' MavenProject tgtDir = do
52 codegenJava' Raw tgtDir
53 generatePom tgtDir out libs
54 codegenJava' Object tgtDir = do
55 codegenJava' MavenProject tgtDir
56 invokeMvn tgtDir "compile"
57 copyClassFiles tgtDir out
59 codegenJava' _ tgtDir = do
60 codegenJava' MavenProject tgtDir
61 invokeMvn tgtDir "package";
66-----------------------------------------------------------------------
69withTgtDir :: OutputType -> FilePath -> (FilePath -> IO ()) -> IO ()
70withTgtDir Raw out action = action (dropFileName out)
71withTgtDir MavenProject out action = createDirectoryIfMissing False out >> action out
72withTgtDir _ out action = withTempdir (takeBaseName out) action
74prepareSrcDir :: OutputType -> FilePath -> IO FilePath
75prepareSrcDir Raw tgtDir = return tgtDir
76prepareSrcDir _ tgtDir = do
77 let srcDir = (tgtDir </> "src" </> "main" </> "java")
78 createDirectoryIfMissing True srcDir
81javaFileName :: FilePath -> FilePath -> FilePath
82javaFileName srcDir out =
83 either error (\ (Ident clsName) -> srcDir </> clsName <.> "java") (mkClassName out)
85generateJavaFile :: [(Name, SExp)] -> -- initialization of globals
86 [(Name, SDecl)] -> -- definitions
87 [String] -> -- headers
88 FilePath -> -- Source dir
89 FilePath -> -- output target
91generateJavaFile globalInit defs hdrs srcDir out = do
92 let code = either error
93 (prettyPrint)-- flatIndent . prettyPrint)
94 (evalStateT (mkCompilationUnit globalInit defs hdrs out) mkCodeGenEnv)
95 writeFile (javaFileName srcDir out) code
97pomFileName :: FilePath -> FilePath
98pomFileName tgtDir = tgtDir </> "pom.xml"
100generatePom :: FilePath -> -- tgt dir
101 FilePath -> -- output target
104generatePom tgtDir out libs = writeFile (pomFileName tgtDir) execPom
106 (Ident clsName) = either error id (mkClassName out)
107 execPom = pomString clsName (takeBaseName out) libs
110invokeMvn :: FilePath -> String -> IO ()
111invokeMvn tgtDir command = do
113 let args = ["-f", pomFileName tgtDir]
114 (exit, mvout, err) <- readProcessWithExitCode mvnCmd (args ++ [command]) ""
115 when (exit /= ExitSuccess) $
116 error ("FAILURE: " ++ mvnCmd ++ " " ++ command ++ "\n" ++ err ++ mvout)
118classFileDir :: FilePath -> FilePath
119classFileDir tgtDir = tgtDir </> "target" </> "classes"
121copyClassFiles :: FilePath -> FilePath -> IO ()
122copyClassFiles tgtDir out = do
123 classFiles <- map (\ clsFile -> classFileDir tgtDir </> clsFile)
124 . filter ((".class" ==) . takeExtension)
125 <$> getDirectoryContents (classFileDir tgtDir)
126 mapM_ (\ clsFile -> copyFile clsFile (takeDirectory out </> takeFileName clsFile)) classFiles
128jarFileName :: FilePath -> FilePath -> FilePath
129jarFileName tgtDir out = tgtDir </> "target" </> (takeBaseName out) <.> "jar"
131copyJar :: FilePath -> FilePath -> IO ()
133 copyFile (jarFileName tgtDir out) out
135makeJarExecutable :: FilePath -> IO ()
136makeJarExecutable out = do
137 handle <- openBinaryFile out ReadMode
138 contents <- TIO.hGetContents handle
140 handle <- openBinaryFile out WriteMode
141 TIO.hPutStr handle (T.append (T.pack jarHeader) contents)
144 perms <- getPermissions out
145 setPermissions out (setOwnerExecutable True perms)
147removePom :: FilePath -> IO ()
148removePom tgtDir = removeFile (pomFileName tgtDir)
150cleanUpTmp :: FilePath -> IO ()
151cleanUpTmp tgtDir = do
152 invokeMvn tgtDir "clean"
155-----------------------------------------------------------------------
156-- Jar and Pom infrastructure
160 "#!/usr/bin/env sh\n"
161 ++ "MYSELF=`which \"$0\" 2>/dev/null`\n"
162 ++ "[ $? -gt 0 -a -f \"$0\" ] && MYSELF=\"./$0\"\n"
164 ++ "if test -n \"$JAVA_HOME\"; then\n"
165 ++ " java=\"$JAVA_HOME/bin/java\"\n"
167 ++ "exec \"$java\" $java_args -jar $MYSELF \"$@\""
170-----------------------------------------------------------------------
171-- Code generation environment
173data CodeGenerationEnv
175 { globalVariables :: [(Name, ArrayIndex)]
176 , localVariables :: [[(Int, Ident)]]
177 , localVarCounter :: Int
180type CodeGeneration = StateT (CodeGenerationEnv) (Either String)
182mkCodeGenEnv :: CodeGenerationEnv
183mkCodeGenEnv = CodeGenerationEnv [] [] 0
185varPos :: LVar -> CodeGeneration (Either ArrayIndex Ident)
187 vars <- (concat . localVariables) <$> get
188 case lookup i vars of
189 (Just varName) -> return (Right varName)
190 Nothing -> throwError $ "Invalid local variable id: " ++ show i
191varPos (Glob name) = do
192 vars <- globalVariables <$> get
193 case lookup name vars of
194 (Just varIdx) -> return (Left varIdx)
195 Nothing -> throwError $ "Invalid global variable id: " ++ show name
197pushScope :: CodeGeneration ()
199 modify (\ env -> env { localVariables = []:(localVariables env) })
201popScope :: CodeGeneration ()
204 let lVars = tail $ localVariables env
205 let vC = if null lVars then 0 else localVarCounter env
206 put $ env { localVariables = tail (localVariables env)
207 , localVarCounter = vC }
209setVariable :: LVar -> CodeGeneration (Either ArrayIndex Ident)
210setVariable (Loc i) = do
212 let lVars = localVariables env
213 let getter = localVar $ localVarCounter env
214 let lVars' = ((i, getter) : head lVars) : tail lVars
215 put $ env { localVariables = lVars'
216 , localVarCounter = 1 + localVarCounter env}
217 return (Right getter)
218setVariable (Glob n) = do
220 let gVars = globalVariables env
221 let getter = globalContext @! length gVars
222 let gVars' = (n, getter):gVars
223 put (env { globalVariables = gVars' })
226pushParams :: [Ident] -> CodeGeneration ()
227pushParams paramNames =
228 let varMap = zipWith (flip (,)) paramNames [0..] in
229 modify (\ env -> env { localVariables = varMap:(localVariables env)
230 , localVarCounter = (length varMap) + (localVarCounter env) })
232flatIndent :: String -> String
233flatIndent (' ' : ' ' : xs) = flatIndent xs
234flatIndent (x:xs) = x:flatIndent xs
237-----------------------------------------------------------------------
238-- Maintaining control structures over code blocks
240data BlockPostprocessor
242 { ppInnerBlock :: [BlockStmt] -> Exp -> CodeGeneration [BlockStmt]
243 , ppOuterBlock :: [BlockStmt] -> CodeGeneration [BlockStmt]
246ppExp :: BlockPostprocessor -> Exp -> CodeGeneration [BlockStmt]
247ppExp pp exp = ((ppInnerBlock pp) [] exp) >>= ppOuterBlock pp
249addReturn :: BlockPostprocessor
252 { ppInnerBlock = (\ block exp -> return $ block ++ [jReturn exp])
253 , ppOuterBlock = return
256ignoreResult :: BlockPostprocessor
259 { ppInnerBlock = (\ block exp -> return block)
260 , ppOuterBlock = return
263ignoreOuter :: BlockPostprocessor -> BlockPostprocessor
264ignoreOuter pp = pp { ppOuterBlock = return }
266throwRuntimeException :: BlockPostprocessor -> BlockPostprocessor
267throwRuntimeException pp =
270 (\ blk exp -> return $
271 blk ++ [ BlockStmt $ Throw
274 (toClassType runtimeExceptionType)
283rethrowAsRuntimeException :: BlockPostprocessor -> BlockPostprocessor
284rethrowAsRuntimeException pp =
288 ex <- ppInnerBlock (throwRuntimeException pp) [] (ExpName $ J.Name [Ident "ex"])
292 [Catch (FormalParam [] exceptionType False (VarId (Ident "ex"))) $
300-----------------------------------------------------------------------
303mkCompilationUnit :: [(Name, SExp)] -> [(Name, SDecl)] -> [String] -> FilePath -> CodeGeneration CompilationUnit
304mkCompilationUnit globalInit defs hdrs out = do
305 clsName <- mkClassName out
306 CompilationUnit Nothing ( [ ImportDecl False idrisRts True
307 , ImportDecl True idrisPrelude True
308 , ImportDecl False bigInteger False
309 , ImportDecl False runtimeException False
312 <$> mkTypeDecl clsName globalInit defs
314 idrisRts = J.Name $ map Ident ["org", "idris", "rts"]
315 idrisPrelude = J.Name $ map Ident ["org", "idris", "rts", "Prelude"]
316 bigInteger = J.Name $ map Ident ["java", "math", "BigInteger"]
317 runtimeException = J.Name $ map Ident ["java", "lang", "RuntimeException"]
318 otherHdrs = map ( (\ name -> ImportDecl False name False)
320 . map (Ident . T.unpack)
321 . T.splitOn (T.pack ".")
323 $ filter (not . isSuffixOf ".h") hdrs
325-----------------------------------------------------------------------
328mkTypeDecl :: Ident -> [(Name, SExp)] -> [(Name, SDecl)] -> CodeGeneration [TypeDecl]
329mkTypeDecl name globalInit defs =
330 (\ body -> [ClassTypeDecl $ ClassDecl [ Public
331 , Annotation $ SingleElementAnnotation
332 (jName "SuppressWarnings")
333 (EVVal . InitExp $ jString "unchecked")
340 <$> mkClassBody globalInit (map (second (prefixCallNamespaces name)) defs)
342mkClassBody :: [(Name, SExp)] -> [(Name, SDecl)] -> CodeGeneration ClassBody
343mkClassBody globalInit defs =
344 (\ globals defs -> ClassBody . (globals++) . addMainMethod . mergeInnerClasses $ defs)
345 <$> mkGlobalContext globalInit
348mkGlobalContext :: [(Name, SExp)] -> CodeGeneration [Decl]
349mkGlobalContext [] = return []
350mkGlobalContext initExps = do
353 mapM (\ (name, exp) -> do
354 pos <- setVariable (Glob name)
355 mkUpdate ignoreResult (Glob name) exp
358 return [ MemberDecl $ FieldDecl [Private, Static, Final]
360 [ VarDecl (VarId $ globalContextID). Just . InitExp
361 $ ArrayCreate objectType [jInt $ length initExps] 0
363 , InitDecl True (Block $ concat varInit)
366addMainMethod :: [Decl] -> [Decl]
368 | findMain decls = mkMainMethod : decls
371 findMain ((MemberDecl (MemberClassDecl (ClassDecl _ name _ _ _ (ClassBody body)))):_)
372 | name == mangle' (sUN "Main") = findMainMethod body
373 findMain (_:decls) = findMain decls
376 innerMainMethod = (either error id $ mangle (sUN "main"))
377 findMainMethod ((MemberDecl (MethodDecl _ _ _ name [] _ _)):_)
378 | name == mangle' (sUN "main") = True
379 findMainMethod (_:decls) = findMainMethod decls
380 findMainMethod [] = False
388 [FormalParam [] (array stringType) False (VarId $ Ident "args")]
389 $ Block [ BlockStmt . ExpStmt
390 $ call "idris_initArgs" [ (threadType ~> "currentThread") []
393 , BlockStmt . ExpStmt $ call (mangle' (sMN 0 "runMain")) []
396-----------------------------------------------------------------------
397-- Inner classes (idris namespaces)
399mergeInnerClasses :: [Decl] -> [Decl]
400mergeInnerClasses = foldl' mergeInner []
402 mergeInner ((decl@(MemberDecl (MemberClassDecl (ClassDecl priv name targs ext imp (ClassBody body))))):decls)
403 decl'@(MemberDecl (MemberClassDecl (ClassDecl _ name' _ ext' imp' (ClassBody body'))))
405 (MemberDecl $ MemberClassDecl $
411 (ClassBody $ mergeInnerClasses (body ++ body')))
413 | otherwise = decl:(mergeInner decls decl')
414 mergeInner (decl:decls) decl' = decl:(mergeInner decls decl')
415 mergeInner [] decl' = [decl']
419mkDecl :: (Name, SDecl) -> CodeGeneration Decl
420mkDecl ((NS n (ns:nss)), decl) =
422 MemberDecl $ MemberClassDecl $ ClassDecl [Public, Static] name [] Nothing [] body)
424 <*> mkClassBody [] [(NS n nss, decl)]
425mkDecl (_, SFun name params stackSize body) = do
426 (Ident methodName) <- mangle name
427 methodParams <- mapM mkFormalParam params
428 paramNames <- mapM mangle params
429 pushParams paramNames
430 methodBody <- mkExp addReturn body
433 simpleMethod [Public, Static] (Just objectType) methodName methodParams
436mkFormalParam :: Name -> CodeGeneration FormalParam
438 (\ name -> FormalParam [Final] objectType False (VarId name))
441-----------------------------------------------------------------------
444-- | Compile a simple expression and use the given continuation to postprocess
445-- the resulting value.
446mkExp :: BlockPostprocessor -> SExp -> CodeGeneration [BlockStmt]
449 (Nothing <>@! var) >>= ppExp pp
452mkExp pp (SApp pushTail name args) =
453 mkApp pushTail name args >>= ppExp pp
456mkExp pp (SLet var newExp inExp) =
457 mkLet pp var newExp inExp
458mkExp pp (SUpdate var@(Loc i) newExp) = -- can only update locals
459 mkUpdate pp var newExp
460mkExp pp (SUpdate var newExp) =
464mkExp pp (SCon conId _ args) =
465 mkIdrisObject conId args >>= ppExp pp
468mkExp pp (SCase var alts) = mkCase pp True var alts
469mkExp pp (SChkCase var alts) = mkCase pp False var alts
472mkExp pp (SProj var i) =
473 mkProjection var i >>= ppExp pp
477 ppExp pp $ mkConstant c
479-- Foreign function calls
480mkExp pp (SForeign lang resTy text params) =
481 mkForeign pp lang resTy text params
483-- Primitive functions
484mkExp pp (SOp LFork [arg]) =
485 (mkThread arg) >>= ppExp pp
486mkExp pp (SOp LPar [arg]) =
487 (Nothing <>@! arg) >>= ppExp pp
488mkExp pp (SOp LNoOp args) =
489 (Nothing <>@! (last args)) >>= ppExp pp
490mkExp pp (SOp LNullPtr args) =
492mkExp pp (SOp op args) =
493 (mkPrimitiveFunction op args) >>= ppExp pp
496mkExp pp (SNothing) = ppExp pp $ Lit Null
499mkExp pp (SError err) = ppExp (throwRuntimeException pp) (jString err)
501-----------------------------------------------------------------------
504(<>@!) :: Maybe J.Type -> LVar -> CodeGeneration Exp
506 either ArrayAccess (\ n -> ExpName $ J.Name [n]) <$> varPos var
507(<>@!) (Just castTo) var =
508 (castTo <>) <$> (Nothing <>@! var)
510-----------------------------------------------------------------------
511-- Application (wrap method calls in tail call closures)
513mkApp :: Bool -> Name -> [LVar] -> CodeGeneration Exp
514mkApp False name args =
515 (\ methodName params ->
516 (idrisClosureType ~> "unwrapTailCall") [call methodName params]
519 <*> mapM (Nothing <>@!) args
520mkApp True name args = mkMethodCallClosure name args
522mkMethodCallClosure :: Name -> [LVar] -> CodeGeneration Exp
523mkMethodCallClosure name args =
524 (\ name args -> closure (call name args))
526 <*> mapM (Nothing <>@!) args
528-----------------------------------------------------------------------
529-- Updates (change context array) and Let bindings (Update, execute)
531mkUpdate :: BlockPostprocessor -> LVar -> SExp -> CodeGeneration [BlockStmt]
537 pos <- setVariable var
538 vExp <- Nothing <>@! var
539 ppInnerBlock pp (blk ++ [pos @:= rhs]) vExp
544mkLet :: BlockPostprocessor -> LVar -> SExp -> SExp -> CodeGeneration [BlockStmt]
545mkLet pp var@(Loc pos) newExp inExp =
546 mkUpdate (pp { ppInnerBlock =
548 inBlk <- mkExp pp inExp
549 return (blk ++ inBlk)
553mkLet _ (Glob _) _ _ = T.lift $ Left "Cannot let bind to global variable"
555-----------------------------------------------------------------------
558mkIdrisObject :: Int -> [LVar] -> CodeGeneration Exp
559mkIdrisObject conId args =
561 InstanceCreation [] (toClassType idrisObjectType) ((jInt conId):args) Nothing
563 <$> mapM (Nothing <>@!) args
565-----------------------------------------------------------------------
568mkCase :: BlockPostprocessor -> Bool -> LVar -> [SAlt] -> CodeGeneration [BlockStmt]
569mkCase pp checked var cases
570 | isDefaultOnlyCase cases = mkDefaultMatch pp cases
571 | isConstCase cases = do
572 ifte <- mkConstMatch (ignoreOuter pp) (\ pp -> mkDefaultMatch pp cases) var cases
573 ppOuterBlock pp [BlockStmt ifte]
575 switchExp <- mkGetConstructorId checked var
576 matchBlocks <- mkConsMatch (ignoreOuter pp) (\ pp -> mkDefaultMatch pp cases) var cases
577 ppOuterBlock pp [BlockStmt $ Switch switchExp matchBlocks]
579isConstCase :: [SAlt] -> Bool
580isConstCase ((SConstCase _ _):_) = True
581isConstCase ((SDefaultCase _):cases) = isConstCase cases
584isDefaultOnlyCase :: [SAlt] -> Bool
585isDefaultOnlyCase [SDefaultCase _] = True
586isDefaultOnlyCase [] = True
587isDefaultOnlyCase _ = False
589mkDefaultMatch :: BlockPostprocessor -> [SAlt] -> CodeGeneration [BlockStmt]
590mkDefaultMatch pp (x@(SDefaultCase branchExpression):_) =
592 stmt <- mkExp pp branchExpression
595mkDefaultMatch pp (x:xs) = mkDefaultMatch pp xs
596mkDefaultMatch pp [] =
597 ppExp (throwRuntimeException pp) (jString "Non-exhaustive pattern")
599mkMatchConstExp :: LVar -> Const -> CodeGeneration Exp
602 (\ var -> (primFnType ~> opName (LEq undefined)) [var, jc] ~==~ jInt 1)
603 <$> (Just cty <>@! var)
605 (\ var -> (arraysType ~> "equals") [var, jc])
606 <$> (Just cty <>@! var)
608 (\ var -> ((primFnType ~> opName (LStrEq)) [var, jc] ~==~ jInt 1))
609 <$> (Just cty <>@! var)
611 (\ var -> (var ~> "equals") [jc])
612 <$> (Just cty <>@! var)
617mkConstMatch :: BlockPostprocessor ->
618 (BlockPostprocessor -> CodeGeneration [BlockStmt]) ->
622mkConstMatch pp getDefaultStmts var ((SConstCase constant branchExpression):cases) = do
623 matchExp <- mkMatchConstExp var constant
625 branchBlock <- mkExp pp branchExpression
627 otherBranches <- mkConstMatch pp getDefaultStmts var cases
629 $ IfThenElse matchExp (StmtBlock $ Block branchBlock) otherBranches
630mkConstMatch pp getDefaultStmts var (c:cases) = mkConstMatch pp getDefaultStmts var cases
631mkConstMatch pp getDefaultStmts _ [] = do
632 defaultBlock <- getDefaultStmts pp
633 return $ StmtBlock (Block defaultBlock)
635mkGetConstructorId :: Bool -> LVar -> CodeGeneration Exp
636mkGetConstructorId True var =
637 (\ var -> ((idrisObjectType <> var) ~> "getConstructorId") [])
638 <$> (Nothing <>@! var)
639mkGetConstructorId False var =
641 Cond (InstanceOf var (toRefType idrisObjectType)) match (jInt (-1))
643 <$> (Nothing <>@! var)
644 <*> mkGetConstructorId True var
646mkConsMatch :: BlockPostprocessor ->
647 (BlockPostprocessor -> CodeGeneration [BlockStmt]) ->
650 CodeGeneration [SwitchBlock]
651mkConsMatch pp getDefaultStmts var ((SConCase parentStackPos consIndex _ params branchExpression):cases) = do
653 caseBranch <- mkCaseBinding pp var parentStackPos params branchExpression
655 otherBranches <- mkConsMatch pp getDefaultStmts var cases
657 (SwitchBlock (SwitchCase $ jInt consIndex) caseBranch):otherBranches
658mkConsMatch pp getDefaultStmts var (c:cases) = mkConsMatch pp getDefaultStmts var cases
659mkConsMatch pp getDefaultStmts _ [] = do
660 defaultBlock <- getDefaultStmts pp
662 [SwitchBlock Default defaultBlock]
664mkCaseBinding :: BlockPostprocessor -> LVar -> Int -> [Name] -> SExp -> CodeGeneration [BlockStmt]
665mkCaseBinding pp var stackStart params branchExpression =
666 mkExp pp (toLetIn var stackStart params branchExpression)
668 toLetIn :: LVar -> Int -> [Name] -> SExp -> SExp
669 toLetIn var stackStart members start =
671 (\ pos inExp -> SLet (Loc (stackStart + pos)) (SProj var pos) inExp)
673 [0.. (length members - 1)]
675-----------------------------------------------------------------------
676-- Projection (retrieve the n-th field of an object)
678mkProjection :: LVar -> Int -> CodeGeneration Exp
679mkProjection var memberNr =
680 (\ var -> ArrayAccess $ ((var ~> "getData") []) @! memberNr)
681 <$> (Just idrisObjectType <>@! var)
683-----------------------------------------------------------------------
686mkConstantArray :: (V.Unbox a) => J.Type -> (a -> Const) -> V.Vector a -> Exp
687mkConstantArray cty elemToConst elems =
691 (ArrayInit . map (InitExp . mkConstant . elemToConst) $ V.toList elems)
693mkConstant :: Const -> Exp
694mkConstant c@(I x) = constType c <> (Lit . Word $ toInteger x)
695mkConstant c@(BI x) = bigInteger (show x)
696mkConstant c@(Fl x) = constType c <> (Lit . Double $ x)
697mkConstant c@(Ch x) = constType c <> (Lit . Char $ x)
698mkConstant c@(Str x) = constType c <> (Lit . String $ x)
699mkConstant c@(B8 x) = constType c <> (Lit . Word $ toInteger x)
700mkConstant c@(B16 x) = constType c <> (Lit . Word $ toInteger x)
701mkConstant c@(B32 x) = constType c <> (Lit . Word $ toInteger x)
702mkConstant c@(B64 x) = (bigInteger (show c) ~> "longValue") []
703mkConstant c@(B8V x) = mkConstantArray (constType c) B8 x
704mkConstant c@(B16V x) = mkConstantArray (constType c) B16 x
705mkConstant c@(B32V x) = mkConstantArray (constType c) B32 x
706mkConstant c@(B64V x) = mkConstantArray (constType c) B64 x
707mkConstant c@(AType x) = ClassLit (Just $ box (constType c))
708mkConstant c@(StrType ) = ClassLit (Just $ stringType)
709mkConstant c@(PtrType ) = ClassLit (Just $ objectType)
710mkConstant c@(VoidType ) = ClassLit (Just $ voidType)
711mkConstant c@(Forgot ) = ClassLit (Just $ objectType)
713-----------------------------------------------------------------------
714-- Foreign function calls
716mkForeign :: BlockPostprocessor -> FLang -> FType -> String -> [(FType, LVar)] -> CodeGeneration [BlockStmt]
717mkForeign pp (LANG_C) resTy text params = mkForeign pp (LANG_JAVA FStatic) resTy text params
718mkForeign pp (LANG_JAVA callType) resTy text params
719 | callType <- FStatic = do
720 method <- liftParsed (parser name text)
721 args <- foreignVarAccess params
722 wrapReturn resTy (call method args)
723 | callType <- FObject = do
724 method <- liftParsed (parser ident text)
725 (tgt:args) <- foreignVarAccess params
726 wrapReturn resTy ((tgt ~> (show $ pretty method)) args)
727 | callType <- FConstructor = do
728 clsTy <- liftParsed (parser classType text)
729 args <- foreignVarAccess params
730 wrapReturn resTy (InstanceCreation [] clsTy args Nothing)
732 foreignVarAccess args =
733 mapM (\ (fty, var) -> (foreignType fty <>@! var)) args
735 pp' = rethrowAsRuntimeException pp
737 wrapReturn FUnit exp =
738 ((ppInnerBlock pp') [BlockStmt $ ExpStmt exp] (Lit Null)) >>= ppOuterBlock pp'
740 ((ppInnerBlock pp') [] exp) >>= ppOuterBlock pp'
742-----------------------------------------------------------------------
743-- Primitive functions
745mkPrimitiveFunction :: PrimFn -> [LVar] -> CodeGeneration Exp
746mkPrimitiveFunction op args =
747 (\ args -> (primFnType ~> opName op) args)
748 <$> sequence (zipWith (\ a t -> (Just t) <>@! a) args (sourceTypes op))
750mkThread :: LVar -> CodeGeneration Exp
752 (\ closure -> (closure ~> "fork") []) <$> mkMethodCallClosure (sMN 0 "EVAL") [arg]
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list