1{-# LANGUAGE PatternGuards #-}
2module IRTS.CodegenJava (codegenJava) where
4import Core.TT hiding (mkApp)
5import IRTS.CodegenCommon
6import IRTS.Java.ASTBuilding
8import IRTS.Java.Mangling
9import IRTS.Java.Pom (pomString)
14import Control.Applicative hiding (Const)
17import Control.Monad.Error
18import qualified Control.Monad.Trans as T
19import Control.Monad.Trans.State
20import Data.List (foldl', isSuffixOf)
21import qualified Data.Text as T
22import qualified Data.Text.IO as TIO
23import qualified Data.Vector.Unboxed as V
24import Language.Java.Parser
25import Language.Java.Pretty
26import Language.Java.Syntax hiding (Name)
27import qualified Language.Java.Syntax as J
28import System.Directory
34-----------------------------------------------------------------------
36codegenJava :: [(Name, SExp)] -> -- initialization of globals
37 [(Name, SDecl)] -> -- decls
38 FilePath -> -- output file name
39 [String] -> -- headers
43codegenJava globalInit defs out hdrs libs exec =
44 withTgtDir exec out (codegenJava' exec)
46 codegenJava' :: OutputType -> FilePath -> IO ()
47 codegenJava' Raw tgtDir = do
48 srcDir <- prepareSrcDir exec tgtDir
49 generateJavaFile globalInit defs hdrs srcDir out
50 codegenJava' MavenProject tgtDir = do
51 codegenJava' Raw tgtDir
52 generatePom tgtDir out libs
53 codegenJava' Object tgtDir = do
54 codegenJava' MavenProject tgtDir
55 invokeMvn tgtDir "compile"
56 copyClassFiles tgtDir out
58 codegenJava' _ tgtDir = do
59 codegenJava' MavenProject tgtDir
60 invokeMvn tgtDir "package";
65-----------------------------------------------------------------------
68withTgtDir :: OutputType -> FilePath -> (FilePath -> IO ()) -> IO ()
69withTgtDir Raw out action = action (dropFileName out)
70withTgtDir MavenProject out action = createDirectoryIfMissing False out >> action out
71withTgtDir _ out action = withTempdir (takeBaseName out) action
73prepareSrcDir :: OutputType -> FilePath -> IO FilePath
74prepareSrcDir Raw tgtDir = return tgtDir
75prepareSrcDir _ tgtDir = do
76 let srcDir = (tgtDir </> "src" </> "main" </> "java")
77 createDirectoryIfMissing True srcDir
80javaFileName :: FilePath -> FilePath -> FilePath
81javaFileName srcDir out =
82 either error (\ (Ident clsName) -> srcDir </> clsName <.> "java") (mkClassName out)
84generateJavaFile :: [(Name, SExp)] -> -- initialization of globals
85 [(Name, SDecl)] -> -- definitions
86 [String] -> -- headers
87 FilePath -> -- Source dir
88 FilePath -> -- output target
90generateJavaFile globalInit defs hdrs srcDir out = do
91 let code = either error
92 (prettyPrint)-- flatIndent . prettyPrint)
93 (evalStateT (mkCompilationUnit globalInit defs hdrs out) mkCodeGenEnv)
94 writeFile (javaFileName srcDir out) code
96pomFileName :: FilePath -> FilePath
97pomFileName tgtDir = tgtDir </> "pom.xml"
99generatePom :: FilePath -> -- tgt dir
100 FilePath -> -- output target
103generatePom tgtDir out libs = writeFile (pomFileName tgtDir) execPom
105 (Ident clsName) = either error id (mkClassName out)
106 execPom = pomString clsName (takeBaseName out) libs
109invokeMvn :: FilePath -> String -> IO ()
110invokeMvn tgtDir command = do
112 let args = ["-f", pomFileName tgtDir]
113 (exit, mvout, err) <- readProcessWithExitCode mvnCmd (args ++ [command]) ""
114 when (exit /= ExitSuccess) $
115 error ("FAILURE: " ++ mvnCmd ++ " " ++ command ++ "\n" ++ err ++ mvout)
117classFileDir :: FilePath -> FilePath
118classFileDir tgtDir = tgtDir </> "target" </> "classes"
120copyClassFiles :: FilePath -> FilePath -> IO ()
121copyClassFiles tgtDir out = do
122 classFiles <- map (\ clsFile -> classFileDir tgtDir </> clsFile)
123 . filter ((".class" ==) . takeExtension)
124 <$> getDirectoryContents (classFileDir tgtDir)
125 mapM_ (\ clsFile -> copyFile clsFile (takeDirectory out </> takeFileName clsFile)) classFiles
127jarFileName :: FilePath -> FilePath -> FilePath
128jarFileName tgtDir out = tgtDir </> "target" </> (takeBaseName out) <.> "jar"
130copyJar :: FilePath -> FilePath -> IO ()
132 copyFile (jarFileName tgtDir out) out
134makeJarExecutable :: FilePath -> IO ()
135makeJarExecutable out = do
136 handle <- openBinaryFile out ReadMode
137 contents <- TIO.hGetContents handle
139 handle <- openBinaryFile out WriteMode
140 TIO.hPutStr handle (T.append (T.pack jarHeader) contents)
143 perms <- getPermissions out
144 setPermissions out (setOwnerExecutable True perms)
146removePom :: FilePath -> IO ()
147removePom tgtDir = removeFile (pomFileName tgtDir)
149cleanUpTmp :: FilePath -> IO ()
150cleanUpTmp tgtDir = do
151 invokeMvn tgtDir "clean"
154-----------------------------------------------------------------------
155-- Jar and Pom infrastructure
160 ++ "MYSELF=`which \"$0\" 2>/dev/null`\n"
161 ++ "[ $? -gt 0 -a -f \"$0\" ] && MYSELF=\"./$0\"\n"
163 ++ "if test -n \"$JAVA_HOME\"; then\n"
164 ++ " java=\"$JAVA_HOME/bin/java\"\n"
166 ++ "exec \"$java\" $java_args -jar $MYSELF \"$@\""
169-----------------------------------------------------------------------
170-- Code generation environment
172data CodeGenerationEnv
174 { globalVariables :: [(Name, ArrayIndex)]
175 , localVariables :: [[(Int, Ident)]]
176 , localVarCounter :: Int
179type CodeGeneration = StateT (CodeGenerationEnv) (Either String)
181mkCodeGenEnv :: CodeGenerationEnv
182mkCodeGenEnv = CodeGenerationEnv [] [] 0
184varPos :: LVar -> CodeGeneration (Either ArrayIndex Ident)
186 vars <- (concat . localVariables) <$> get
187 case lookup i vars of
188 (Just varName) -> return (Right varName)
189 Nothing -> throwError $ "Invalid local variable id: " ++ show i
190varPos (Glob name) = do
191 vars <- globalVariables <$> get
192 case lookup name vars of
193 (Just varIdx) -> return (Left varIdx)
194 Nothing -> throwError $ "Invalid global variable id: " ++ show name
196pushScope :: CodeGeneration ()
198 modify (\ env -> env { localVariables = []:(localVariables env) })
200popScope :: CodeGeneration ()
203 let lVars = tail $ localVariables env
204 let vC = if null lVars then 0 else localVarCounter env
205 put $ env { localVariables = tail (localVariables env)
206 , localVarCounter = vC }
208setVariable :: LVar -> CodeGeneration (Either ArrayIndex Ident)
209setVariable (Loc i) = do
211 let lVars = localVariables env
212 let getter = localVar $ localVarCounter env
213 let lVars' = ((i, getter) : head lVars) : tail lVars
214 put $ env { localVariables = lVars'
215 , localVarCounter = 1 + localVarCounter env}
216 return (Right getter)
217setVariable (Glob n) = do
219 let gVars = globalVariables env
220 let getter = globalContext @! length gVars
221 let gVars' = (n, getter):gVars
222 put (env { globalVariables = gVars' })
225pushParams :: [Ident] -> CodeGeneration ()
226pushParams paramNames =
227 let varMap = zipWith (flip (,)) paramNames [0..] in
228 modify (\ env -> env { localVariables = varMap:(localVariables env)
229 , localVarCounter = (length varMap) + (localVarCounter env) })
231flatIndent :: String -> String
232flatIndent (' ' : ' ' : xs) = flatIndent xs
233flatIndent (x:xs) = x:flatIndent xs
236-----------------------------------------------------------------------
237-- Maintaining control structures over code blocks
239data BlockPostprocessor
241 { ppInnerBlock :: [BlockStmt] -> Exp -> CodeGeneration [BlockStmt]
242 , ppOuterBlock :: [BlockStmt] -> CodeGeneration [BlockStmt]
245ppExp :: BlockPostprocessor -> Exp -> CodeGeneration [BlockStmt]
246ppExp pp exp = ((ppInnerBlock pp) [] exp) >>= ppOuterBlock pp
248addReturn :: BlockPostprocessor
251 { ppInnerBlock = (\ block exp -> return $ block ++ [jReturn exp])
252 , ppOuterBlock = return
255ignoreResult :: BlockPostprocessor
258 { ppInnerBlock = (\ block exp -> return block)
259 , ppOuterBlock = return
262ignoreOuter :: BlockPostprocessor -> BlockPostprocessor
263ignoreOuter pp = pp { ppOuterBlock = return }
265throwRuntimeException :: BlockPostprocessor -> BlockPostprocessor
266throwRuntimeException pp =
269 (\ blk exp -> return $
270 blk ++ [ BlockStmt $ Throw
273 (toClassType runtimeExceptionType)
282rethrowAsRuntimeException :: BlockPostprocessor -> BlockPostprocessor
283rethrowAsRuntimeException pp =
287 ex <- ppInnerBlock (throwRuntimeException pp) [] (ExpName $ J.Name [Ident "ex"])
291 [Catch (FormalParam [] exceptionType False (VarId (Ident "ex"))) $
299-----------------------------------------------------------------------
302mkCompilationUnit :: [(Name, SExp)] -> [(Name, SDecl)] -> [String] -> FilePath -> CodeGeneration CompilationUnit
303mkCompilationUnit globalInit defs hdrs out = do
304 clsName <- mkClassName out
305 CompilationUnit Nothing ( [ ImportDecl False idrisRts True
306 , ImportDecl True idrisPrelude True
307 , ImportDecl False bigInteger False
308 , ImportDecl False runtimeException False
311 <$> mkTypeDecl clsName globalInit defs
313 idrisRts = J.Name $ map Ident ["org", "idris", "rts"]
314 idrisPrelude = J.Name $ map Ident ["org", "idris", "rts", "Prelude"]
315 bigInteger = J.Name $ map Ident ["java", "math", "BigInteger"]
316 runtimeException = J.Name $ map Ident ["java", "lang", "RuntimeException"]
317 otherHdrs = map ( (\ name -> ImportDecl False name False)
319 . map (Ident . T.unpack)
320 . T.splitOn (T.pack ".")
322 $ filter (not . isSuffixOf ".h") hdrs
324-----------------------------------------------------------------------
327mkTypeDecl :: Ident -> [(Name, SExp)] -> [(Name, SDecl)] -> CodeGeneration [TypeDecl]
328mkTypeDecl name globalInit defs =
329 (\ body -> [ClassTypeDecl $ ClassDecl [ Public
330 , Annotation $ SingleElementAnnotation
331 (jName "SuppressWarnings")
332 (EVVal . InitExp $ jString "unchecked")
339 <$> mkClassBody globalInit (map (second (prefixCallNamespaces name)) defs)
341mkClassBody :: [(Name, SExp)] -> [(Name, SDecl)] -> CodeGeneration ClassBody
342mkClassBody globalInit defs =
343 (\ globals defs -> ClassBody . (globals++) . addMainMethod . mergeInnerClasses $ defs)
344 <$> mkGlobalContext globalInit
347mkGlobalContext :: [(Name, SExp)] -> CodeGeneration [Decl]
348mkGlobalContext [] = return []
349mkGlobalContext initExps = do
352 mapM (\ (name, exp) -> do
353 pos <- setVariable (Glob name)
354 mkUpdate ignoreResult (Glob name) exp
357 return [ MemberDecl $ FieldDecl [Private, Static, Final]
359 [ VarDecl (VarId $ globalContextID). Just . InitExp
360 $ ArrayCreate objectType [jInt $ length initExps] 0
362 , InitDecl True (Block $ concat varInit)
365addMainMethod :: [Decl] -> [Decl]
367 | findMain decls = mkMainMethod : decls
370 findMain ((MemberDecl (MemberClassDecl (ClassDecl _ name _ _ _ (ClassBody body)))):_)
371 | name == mangle' (UN "Main") = findMainMethod body
372 findMain (_:decls) = findMain decls
375 innerMainMethod = (either error id $ mangle (UN "main"))
376 findMainMethod ((MemberDecl (MethodDecl _ _ _ name [] _ _)):_)
377 | name == mangle' (UN "main") = True
378 findMainMethod (_:decls) = findMainMethod decls
379 findMainMethod [] = False
387 [FormalParam [] (array stringType) False (VarId $ Ident "args")]
388 $ Block [ BlockStmt . ExpStmt
389 $ call "idris_initArgs" [ (threadType ~> "currentThread") []
392 , BlockStmt . ExpStmt $ call (mangle' (MN 0 "runMain")) []
395-----------------------------------------------------------------------
396-- Inner classes (idris namespaces)
398mergeInnerClasses :: [Decl] -> [Decl]
399mergeInnerClasses = foldl' mergeInner []
401 mergeInner ((decl@(MemberDecl (MemberClassDecl (ClassDecl priv name targs ext imp (ClassBody body))))):decls)
402 decl'@(MemberDecl (MemberClassDecl (ClassDecl _ name' _ ext' imp' (ClassBody body'))))
404 (MemberDecl $ MemberClassDecl $
410 (ClassBody $ mergeInnerClasses (body ++ body')))
412 | otherwise = decl:(mergeInner decls decl')
413 mergeInner (decl:decls) decl' = decl:(mergeInner decls decl')
414 mergeInner [] decl' = [decl']
418mkDecl :: (Name, SDecl) -> CodeGeneration Decl
419mkDecl ((NS n (ns:nss)), decl) =
421 MemberDecl $ MemberClassDecl $ ClassDecl [Public, Static] name [] Nothing [] body)
423 <*> mkClassBody [] [(NS n nss, decl)]
424mkDecl (_, SFun name params stackSize body) = do
425 (Ident methodName) <- mangle name
426 methodParams <- mapM mkFormalParam params
427 paramNames <- mapM mangle params
428 pushParams paramNames
429 methodBody <- mkExp addReturn body
432 simpleMethod [Public, Static] (Just objectType) methodName methodParams
435mkFormalParam :: Name -> CodeGeneration FormalParam
437 (\ name -> FormalParam [Final] objectType False (VarId name))
440-----------------------------------------------------------------------
443-- | Compile a simple expression and use the given continuation to postprocess
444-- the resulting value.
445mkExp :: BlockPostprocessor -> SExp -> CodeGeneration [BlockStmt]
448 (Nothing <>@! var) >>= ppExp pp
451mkExp pp (SApp pushTail name args) =
452 mkApp pushTail name args >>= ppExp pp
455mkExp pp (SLet var newExp inExp) =
456 mkLet pp var newExp inExp
457mkExp pp (SUpdate var@(Loc i) newExp) = -- can only update locals
458 mkUpdate pp var newExp
459mkExp pp (SUpdate var newExp) =
463mkExp pp (SCon conId _ args) =
464 mkIdrisObject conId args >>= ppExp pp
467mkExp pp (SCase var alts) = mkCase pp True var alts
468mkExp pp (SChkCase var alts) = mkCase pp False var alts
471mkExp pp (SProj var i) =
472 mkProjection var i >>= ppExp pp
476 ppExp pp $ mkConstant c
478-- Foreign function calls
479mkExp pp (SForeign lang resTy text params) =
480 mkForeign pp lang resTy text params
482-- Primitive functions
483mkExp pp (SOp LFork [arg]) =
484 (mkThread arg) >>= ppExp pp
485mkExp pp (SOp LPar [arg]) =
486 (Nothing <>@! arg) >>= ppExp pp
487mkExp pp (SOp LNoOp args) =
488 (Nothing <>@! (last args)) >>= ppExp pp
489mkExp pp (SOp LNullPtr args) =
491mkExp pp (SOp op args) =
492 (mkPrimitiveFunction op args) >>= ppExp pp
495mkExp pp (SNothing) = ppExp pp $ Lit Null
498mkExp pp (SError err) = ppExp (throwRuntimeException pp) (jString err)
500-----------------------------------------------------------------------
503(<>@!) :: Maybe J.Type -> LVar -> CodeGeneration Exp
505 either ArrayAccess (\ n -> ExpName $ J.Name [n]) <$> varPos var
506(<>@!) (Just castTo) var =
507 (castTo <>) <$> (Nothing <>@! var)
509-----------------------------------------------------------------------
510-- Application (wrap method calls in tail call closures)
512mkApp :: Bool -> Name -> [LVar] -> CodeGeneration Exp
513mkApp False name args =
514 (\ methodName params ->
515 (idrisClosureType ~> "unwrapTailCall") [call methodName params]
518 <*> mapM (Nothing <>@!) args
519mkApp True name args = mkMethodCallClosure name args
521mkMethodCallClosure :: Name -> [LVar] -> CodeGeneration Exp
522mkMethodCallClosure name args =
523 (\ name args -> closure (call name args))
525 <*> mapM (Nothing <>@!) args
527-----------------------------------------------------------------------
528-- Updates (change context array) and Let bindings (Update, execute)
530mkUpdate :: BlockPostprocessor -> LVar -> SExp -> CodeGeneration [BlockStmt]
536 pos <- setVariable var
537 vExp <- Nothing <>@! var
538 ppInnerBlock pp (blk ++ [pos @:= rhs]) vExp
543mkLet :: BlockPostprocessor -> LVar -> SExp -> SExp -> CodeGeneration [BlockStmt]
544mkLet pp var@(Loc pos) newExp inExp =
545 mkUpdate (pp { ppInnerBlock =
547 inBlk <- mkExp pp inExp
548 return (blk ++ inBlk)
552mkLet _ (Glob _) _ _ = T.lift $ Left "Cannot let bind to global variable"
554-----------------------------------------------------------------------
557mkIdrisObject :: Int -> [LVar] -> CodeGeneration Exp
558mkIdrisObject conId args =
560 InstanceCreation [] (toClassType idrisObjectType) ((jInt conId):args) Nothing
562 <$> mapM (Nothing <>@!) args
564-----------------------------------------------------------------------
567mkCase :: BlockPostprocessor -> Bool -> LVar -> [SAlt] -> CodeGeneration [BlockStmt]
568mkCase pp checked var cases
569 | isDefaultOnlyCase cases = mkDefaultMatch pp cases
570 | isConstCase cases = do
571 ifte <- mkConstMatch (ignoreOuter pp) (\ pp -> mkDefaultMatch pp cases) var cases
572 ppOuterBlock pp [BlockStmt ifte]
574 switchExp <- mkGetConstructorId checked var
575 matchBlocks <- mkConsMatch (ignoreOuter pp) (\ pp -> mkDefaultMatch pp cases) var cases
576 ppOuterBlock pp [BlockStmt $ Switch switchExp matchBlocks]
578isConstCase :: [SAlt] -> Bool
579isConstCase ((SConstCase _ _):_) = True
580isConstCase ((SDefaultCase _):cases) = isConstCase cases
583isDefaultOnlyCase :: [SAlt] -> Bool
584isDefaultOnlyCase [SDefaultCase _] = True
585isDefaultOnlyCase [] = True
586isDefaultOnlyCase _ = False
588mkDefaultMatch :: BlockPostprocessor -> [SAlt] -> CodeGeneration [BlockStmt]
589mkDefaultMatch pp (x@(SDefaultCase branchExpression):_) =
591 stmt <- mkExp pp branchExpression
594mkDefaultMatch pp (x:xs) = mkDefaultMatch pp xs
595mkDefaultMatch pp [] =
596 ppExp (throwRuntimeException pp) (jString "Non-exhaustive pattern")
598mkMatchConstExp :: LVar -> Const -> CodeGeneration Exp
601 (\ var -> (primFnType ~> opName (LEq undefined)) [var, jc] ~==~ jInt 1)
602 <$> (Just cty <>@! var)
604 (\ var -> (arraysType ~> "equals") [var, jc])
605 <$> (Just cty <>@! var)
607 (\ var -> ((primFnType ~> opName (LStrEq)) [var, jc] ~==~ jInt 1))
608 <$> (Just cty <>@! var)
610 (\ var -> (var ~> "equals") [jc])
611 <$> (Just cty <>@! var)
616mkConstMatch :: BlockPostprocessor ->
617 (BlockPostprocessor -> CodeGeneration [BlockStmt]) ->
621mkConstMatch pp getDefaultStmts var ((SConstCase constant branchExpression):cases) = do
622 matchExp <- mkMatchConstExp var constant
624 branchBlock <- mkExp pp branchExpression
626 otherBranches <- mkConstMatch pp getDefaultStmts var cases
628 $ IfThenElse matchExp (StmtBlock $ Block branchBlock) otherBranches
629mkConstMatch pp getDefaultStmts var (c:cases) = mkConstMatch pp getDefaultStmts var cases
630mkConstMatch pp getDefaultStmts _ [] = do
631 defaultBlock <- getDefaultStmts pp
632 return $ StmtBlock (Block defaultBlock)
634mkGetConstructorId :: Bool -> LVar -> CodeGeneration Exp
635mkGetConstructorId True var =
636 (\ var -> ((idrisObjectType <> var) ~> "getConstructorId") [])
637 <$> (Nothing <>@! var)
638mkGetConstructorId False var =
640 Cond (InstanceOf var (toRefType idrisObjectType)) match (jInt (-1))
642 <$> (Nothing <>@! var)
643 <*> mkGetConstructorId True var
645mkConsMatch :: BlockPostprocessor ->
646 (BlockPostprocessor -> CodeGeneration [BlockStmt]) ->
649 CodeGeneration [SwitchBlock]
650mkConsMatch pp getDefaultStmts var ((SConCase parentStackPos consIndex _ params branchExpression):cases) = do
652 caseBranch <- mkCaseBinding pp var parentStackPos params branchExpression
654 otherBranches <- mkConsMatch pp getDefaultStmts var cases
656 (SwitchBlock (SwitchCase $ jInt consIndex) caseBranch):otherBranches
657mkConsMatch pp getDefaultStmts var (c:cases) = mkConsMatch pp getDefaultStmts var cases
658mkConsMatch pp getDefaultStmts _ [] = do
659 defaultBlock <- getDefaultStmts pp
661 [SwitchBlock Default defaultBlock]
663mkCaseBinding :: BlockPostprocessor -> LVar -> Int -> [Name] -> SExp -> CodeGeneration [BlockStmt]
664mkCaseBinding pp var stackStart params branchExpression =
665 mkExp pp (toLetIn var stackStart params branchExpression)
667 toLetIn :: LVar -> Int -> [Name] -> SExp -> SExp
668 toLetIn var stackStart members start =
670 (\ pos inExp -> SLet (Loc (stackStart + pos)) (SProj var pos) inExp)
672 [0.. (length members - 1)]
674-----------------------------------------------------------------------
675-- Projection (retrieve the n-th field of an object)
677mkProjection :: LVar -> Int -> CodeGeneration Exp
678mkProjection var memberNr =
679 (\ var -> ArrayAccess $ ((var ~> "getData") []) @! memberNr)
680 <$> (Just idrisObjectType <>@! var)
682-----------------------------------------------------------------------
685mkConstantArray :: (V.Unbox a) => J.Type -> (a -> Const) -> V.Vector a -> Exp
686mkConstantArray cty elemToConst elems =
690 (ArrayInit . map (InitExp . mkConstant . elemToConst) $ V.toList elems)
692mkConstant :: Const -> Exp
693mkConstant c@(I x) = constType c <> (Lit . Word $ toInteger x)
694mkConstant c@(BI x) = bigInteger (show x)
695mkConstant c@(Fl x) = constType c <> (Lit . Double $ x)
696mkConstant c@(Ch x) = constType c <> (Lit . Char $ x)
697mkConstant c@(Str x) = constType c <> (Lit . String $ x)
698mkConstant c@(B8 x) = constType c <> (Lit . Word $ toInteger x)
699mkConstant c@(B16 x) = constType c <> (Lit . Word $ toInteger x)
700mkConstant c@(B32 x) = constType c <> (Lit . Word $ toInteger x)
701mkConstant c@(B64 x) = (bigInteger (show c) ~> "longValue") []
702mkConstant c@(B8V x) = mkConstantArray (constType c) B8 x
703mkConstant c@(B16V x) = mkConstantArray (constType c) B16 x
704mkConstant c@(B32V x) = mkConstantArray (constType c) B32 x
705mkConstant c@(B64V x) = mkConstantArray (constType c) B64 x
706mkConstant c@(AType x) = ClassLit (Just $ box (constType c))
707mkConstant c@(StrType ) = ClassLit (Just $ stringType)
708mkConstant c@(PtrType ) = ClassLit (Just $ objectType)
709mkConstant c@(VoidType ) = ClassLit (Just $ voidType)
710mkConstant c@(Forgot ) = ClassLit (Just $ objectType)
712-----------------------------------------------------------------------
713-- Foreign function calls
715mkForeign :: BlockPostprocessor -> FLang -> FType -> String -> [(FType, LVar)] -> CodeGeneration [BlockStmt]
716mkForeign pp (LANG_C) resTy text params = mkForeign pp (LANG_JAVA FStatic) resTy text params
717mkForeign pp (LANG_JAVA callType) resTy text params
718 | callType <- FStatic = do
719 method <- liftParsed (parser name text)
720 args <- foreignVarAccess params
721 wrapReturn resTy (call method args)
722 | callType <- FObject = do
723 method <- liftParsed (parser ident text)
724 (tgt:args) <- foreignVarAccess params
725 wrapReturn resTy ((tgt ~> (show $ pretty method)) args)
726 | callType <- FConstructor = do
727 clsTy <- liftParsed (parser classType text)
728 args <- foreignVarAccess params
729 wrapReturn resTy (InstanceCreation [] clsTy args Nothing)
731 foreignVarAccess args =
732 mapM (\ (fty, var) -> (foreignType fty <>@! var)) args
734 pp' = rethrowAsRuntimeException pp
736 wrapReturn FUnit exp =
737 ((ppInnerBlock pp') [BlockStmt $ ExpStmt exp] (Lit Null)) >>= ppOuterBlock pp'
739 ((ppInnerBlock pp') [] exp) >>= ppOuterBlock pp'
741-----------------------------------------------------------------------
742-- Primitive functions
744mkPrimitiveFunction :: PrimFn -> [LVar] -> CodeGeneration Exp
745mkPrimitiveFunction op args =
746 (\ args -> (primFnType ~> opName op) args)
747 <$> sequence (zipWith (\ a t -> (Just t) <>@! a) args (sourceTypes op))
749mkThread :: LVar -> CodeGeneration Exp
751 (\ closure -> (closure ~> "fork") []) <$> mkMethodCallClosure (MN 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