diff --git a/frege/compiler/common/Errors.fr b/frege/compiler/common/Errors.fr index d5cab14f..de8063d1 100644 --- a/frege/compiler/common/Errors.fr +++ b/frege/compiler/common/Errors.fr @@ -7,9 +7,6 @@ import frege.compiler.enums.Flags import frege.compiler.types.Positions import Compiler.types.Global as G -derive Eq Severity -derive Show Severity - {-- Format an error message, remember in the state and update error counter in the state. -} diff --git a/frege/compiler/enums/CaseKind.fr b/frege/compiler/enums/CaseKind.fr index b89d8479..d9a02cf5 100644 --- a/frege/compiler/enums/CaseKind.fr +++ b/frege/compiler/enums/CaseKind.fr @@ -1,6 +1,8 @@ --- "Kind" of a case module frege.compiler.enums.CaseKind where +import frege.data.JSON (ToJSON, toJSON) + {-- case kind -} @@ -10,4 +12,8 @@ data CKind = | CNoWarn --- compiler generated, do not emit warnings derive Eq CKind -derive Enum CKind \ No newline at end of file +derive Enum CKind +derive Show CKind + +instance ToJSON CKind where + toJSON = toJSON . show \ No newline at end of file diff --git a/frege/compiler/enums/Flags.fr b/frege/compiler/enums/Flags.fr index e02762c0..1b005c2f 100644 --- a/frege/compiler/enums/Flags.fr +++ b/frege/compiler/enums/Flags.fr @@ -2,6 +2,7 @@ module frege.compiler.enums.Flags where import Data.Bits (BitSet()) +import Data.JSON (ToJSON, toJSON) --- the compiler flags data Flag = @@ -37,10 +38,12 @@ data Flag = derive Show Flag derive Enum Flag +instance ToJSON Flag where + toJSON = toJSON . show + --- 'BitSet' for 'Flag's type Flags = BitSet Flag - --- get flag bit flag :: Flag -> Flags flag = Flags.singleton diff --git a/frege/compiler/enums/Literals.fr b/frege/compiler/enums/Literals.fr index e05e5941..29cea12b 100644 --- a/frege/compiler/enums/Literals.fr +++ b/frege/compiler/enums/Literals.fr @@ -1,6 +1,8 @@ --- Classification of literals. module frege.compiler.enums.Literals where +import frege.data.JSON (ToJSON, toJSON) + {-- type tag for Literals -} @@ -24,3 +26,6 @@ derive Enum Literalkind derive Show Literalkind + +instance ToJSON Literalkind where + toJSON = toJSON . show diff --git a/frege/compiler/enums/RFlag.fr b/frege/compiler/enums/RFlag.fr index 54097271..0a408038 100644 --- a/frege/compiler/enums/RFlag.fr +++ b/frege/compiler/enums/RFlag.fr @@ -2,6 +2,7 @@ module frege.compiler.enums.RFlag where -- generated by Splitter import frege.data.Bits(BitSet) +import frege.data.JSON (ToJSON, toJSON) {-- Attributes that describe the run time behaviour of a function/value @@ -18,6 +19,10 @@ data RFlag = derive Show RFlag +instance ToJSON RFlag where + toJSON = toJSON . show + + derive Enum RFlag --- The 'RState' is maintained and persisted in class files for each variable and function diff --git a/frege/compiler/enums/SymState.fr b/frege/compiler/enums/SymState.fr index 718f309a..379a9b26 100644 --- a/frege/compiler/enums/SymState.fr +++ b/frege/compiler/enums/SymState.fr @@ -1,6 +1,8 @@ --- Symbol state module frege.compiler.enums.SymState where +import frege.data.JSON (ToJSON, toJSON) + {-- symbol state -} @@ -19,3 +21,5 @@ derive Show SymState derive Enum SymState +instance ToJSON SymState where + toJSON = toJSON . show diff --git a/frege/compiler/enums/TokenID.fr b/frege/compiler/enums/TokenID.fr index 3769eb8f..08084e77 100644 --- a/frege/compiler/enums/TokenID.fr +++ b/frege/compiler/enums/TokenID.fr @@ -1,6 +1,8 @@ --- 'TokenID' and associated instances module frege.compiler.enums.TokenID where +import frege.data.JSON (ToJSON, toJSON) + {-- The tokens for the frege language. -} @@ -55,4 +57,5 @@ derive Ord TokenID derive Enum TokenID - +instance ToJSON TokenID where + toJSON = toJSON . show diff --git a/frege/compiler/enums/Visibility.fr b/frege/compiler/enums/Visibility.fr index 379df99b..a66dcda2 100644 --- a/frege/compiler/enums/Visibility.fr +++ b/frege/compiler/enums/Visibility.fr @@ -1,6 +1,8 @@ --- cross module visibility of items module frege.compiler.enums.Visibility where +import frege.data.JSON (ToJSON, toJSON) + --- cross module visibility of items data Visibility = Private --- item is not available in other packages, except constructors for inlined code @@ -15,6 +17,10 @@ instance Show Visibility where show Abstract = "abstract" +instance ToJSON Visibility where + toJSON = toJSON . show + + derive Eq Visibility diff --git a/frege/compiler/gen/java/Bindings.fr b/frege/compiler/gen/java/Bindings.fr index 2f1dd09f..d059f21d 100644 --- a/frege/compiler/gen/java/Bindings.fr +++ b/frege/compiler/gen/java/Bindings.fr @@ -16,6 +16,7 @@ import frege.Prelude hiding(<+>) import Data.TreeMap (TreeMap Map) -- import Data.List as DL(zip4) import Data.Bits(BitSet.member) +import Data.JSON(ToJSON) -- import Compiler.common.Errors as E() @@ -59,6 +60,13 @@ instance Show Binding where ++ stype ++ ", " ++ show jtype ++ ", " ++ showJex jex ++ "}" +instance ToJSON Binding where + toJSON x = JSON.struct "Bind" $ JSON.Struct + [ JSON.assoc "stype" x.stype + , JSON.assoc "ftype" x.ftype + , JSON.assoc "jtype" x.jtype + , JSON.assoc "jex" x.jex + ] newBind g sigma jex = Bind{stype=nicer sigma g, ftype=sigma, jtype=sigmaJT g sigma, jex} diff --git a/frege/compiler/gen/java/MethodCall.fr b/frege/compiler/gen/java/MethodCall.fr index 3e018362..b9a27087 100644 --- a/frege/compiler/gen/java/MethodCall.fr +++ b/frege/compiler/gen/java/MethodCall.fr @@ -2,7 +2,7 @@ module frege.compiler.gen.java.MethodCall where import Data.TreeMap(TreeMap, values) -import Data.List(elemBy) +import Data.List(elemBy, zip4) import Compiler.Utilities as U() @@ -13,7 +13,6 @@ import Compiler.types.Types(unST, Sigma, Tau, TauT, ForAll, RhoTau, RhoFun) import Compiler.types.Symbols(SymbolT) import Compiler.types.Global import Compiler.types.JNames(JName, memberOf) -import Compiler.types.Strictness() import Compiler.common.Types as CT import Compiler.common.JavaName @@ -66,16 +65,23 @@ nativeCall ∷ Global → Symbol → TreeMap String Tau → [JExpr] → Binding nativeCall g (sym@SymV {nativ = Just item, gargs}) subst aexs = newBind g bsig (call jrty args) where (rty, sigmas) = U.returnType sym.typ.rho + -- The types of the arguments taus = [ tau | Just tau <- map U.sigmaAsTau sigmas ] + -- The base return type of the method + -- e.g. @b@ in @ST s (a|Maybe b)@ brty = substTau subst (baserty rty) bsig = U.tauAsSigma brty + -- The java type arguments (generics arguments) targs = map (boxed . tauJT g . substTau subst) gargs args | [tau] <- taus, Just _ <- U.isUnit tau = [] -- no arguments | otherwise = zipWith (argEx g) aexs taus bjt = tauJT g brty + -- The java type of the result jrty = strict bjt -- retmode = maxStrict jrty + -- a Java expression for an argument e.g. putting @.call()@, marshalling @Maybe@, etc. + argEx :: Global -> JExpr -> Tau -> JExpr argEx g arg tau | Just x <- U.isMaybe tau = JQC checknothing (JAtom "null") evex -- Just x <- arrayTau g tau = JCast x bind.jex @@ -101,21 +107,18 @@ nativeCall g (sym@SymV {nativ = Just item, gargs}) subst aexs = newBind g bsig ( _ -> JAtom "null" -- error was flagged before NINew -> JNew jrty args NIExtends -> - let evalStG :: Global -> StG a -> a - evalStG g st = fst $ st.run g - x = do g <- getST - si <- symInfo sym - let name = (head si.argSigs).rho.tau.name - irsym = unJust $ g.findit name - nms = mapMaybe (_.name) [ fld | x@SymD{} <- values irsym.env, fld <- x.flds ] - return $ flip mapMaybe nms $ \fldnm -> do - nativrsym <- g.findit $ si.retSig.rho.tau.name - nativsym <- TreeMap.lookup fldnm nativrsym.env - nativnm <- nativsym.nativ - let nativsi = evalStG g $ symInfo nativsym - fldsym <- TreeMap.lookup fldnm irsym.env - pure $ wrapIRMethod g (head args) (head si.argJTs) nativsi nativnm fldnm fldsym - in JNewClass jrty [] (evalStG g x) + let x = -- IR stands for an Implementation Record + let irsym = unJust $ g.findit irname where + irname = (head irtau.flat).name + irtau = (head sigmas).rho.tau + nms = mapMaybe (_.name) [ fld | x@SymD{} <- values irsym.env, fld <- x.flds ] + in + flip mapMaybe nms $ \fldnm -> do + nativrsym <- g.findit $ (head rty.flat).name + nativsym <- TreeMap.lookup fldnm nativrsym.env + fldsym <- TreeMap.lookup fldnm irsym.env + pure $ wrapIRMethod g (head args) (tauJT g $ head taus) fldsym fldnm nativsym + in JNewClass jrty (tail args) x NICast -> case args of [a] -> JInvoke (JAtom item) args -- was: JCast (Ref (JName "" item) []) a _ -> JAtom "null" @@ -300,39 +303,90 @@ wildReturn g (symv@SymV{}) = [ v | v@TVar{} ← values (U.freeTauTVars [] TreeM wildReturn _ _ = [] -wrapIRMethod :: Global -> JExpr -> JType -> SymInfo8 -> String -> String -> Symbol -> JDecl -wrapIRMethod g this irjt nativsi nativnm fldnm fldsym = - let nativargs = argDefs attrFinal (nativsi.{ argSigs <- tail, argJTs <- tail }) (getArgs g) - fldstri = case fldsym.strsig of - Strictness.S xs -> tail xs - _ -> [] - -- how to detect strictness of result value? - retstrict = all (_.isStrict) fldstri - -- retlazy = if not (null fldstri) then (last fldstri).isStrict else False - callit jex = JInvoke { args = [], jex = JExMem { jex, name = "call", targs = [] } } - call = if retstrict then id else callit +--- Generates a method that overrides an interface method and wraps a call to an IR method. +--- +--- Parameters: +--- - global +--- - The expression of the instance of the IR (i.e. the receiver). +--- - The Java type of the IR. +--- - The symbol of the invoked IR method. +--- - The name of the invoked IR method. +--- - The symbol of the native member function. +-- TODO make sure that the every field of an IR is 1-or-more arity functions beforehand +wrapIRMethod :: Global -> JExpr -> JType -> Symbol -> String -> Symbol -> JDecl +wrapIRMethod g this irjt fldsym fldnm nativsym = + let nativnm = unJust nativsym.nativ + -- the generalization of @argDefs@ + argDefs' :: Attributes -> [Sigma] -> [JType] -> [String] -> [FormalArg] + argDefs' attr argSigs argJTs argNms = zip4 (repeat attr) argSigs argJTs argNms + -- collect the FormalArgs of the native member function, excluding the receiver + nativargs = argDefs' attrFinal argSigs argJTs (getArgs g) where + argSigs = case U.returnType nativsym.typ.rho of (_, (_:xs)) -> xs + argJTs = map (sigmaJT g) argSigs + -- the tau of the result type of the IR field + fldrettau = fst $ U.returnType fldsym.typ.rho + -- the return type of the overridden method + methretjt = case unST fldrettau of + Just (_, a) + | isJust $ U.isUnit a -> nativ "void" [] + | otherwise -> tauJT g a + Nothing -> tauJT g $ fst (U.returnType nativsym.typ.rho) + -- force an expression. if it is an ST, run it after that + call = (if isST then tstRun (boxedv methretjt) else id) . callit where + isST = isJust $ unST fldrettau + -- add ".call()" after jex + callit jex = JInvoke { args = [], jex = JExMem { jex, name = "call", targs = [] } } + -- box JType, but box void into Short + boxedv (v@Nativ{typ="void"}) = boxed (v.{typ = "short"}) + boxedv jt = boxed jt + -- "return" if the return type is not the primitive void + ret = if isVoid methretjt then JEx else JReturn where + isVoid Nativ{typ="void"} = true + isVoid _ = false in JMethod { attr = attrs [JPublic] , gvars = [] - , jtype = nativsi.returnJT + , jtype = methretjt , name = nativnm , args = nativargs - , body = JBlock $ pure $ JReturn $ call $ invokeIR irjt fldnm this $ - zipWith (\(_, _, _, x) s -> StriArg x s.isStrict) nativargs fldstri + , body = JBlock $ pure $ ret $ call $ invokeIR irjt fldnm this $ + map (\(_, _, _, x) -> x) nativargs } -data StriArg = StriArg { name :: String, strict :: Bool } - -striArgExpr :: StriArg -> JExpr -striArgExpr (StriArg{name, strict}) = - let thunkjt = Ref { jname = JName { qual = "", base = "Thunk" }, gargs = [] } -- TODO use the proper JType - lazy s = JInvoke { args = [JAtom s], jex = JStMem { jt = thunkjt, name = "lazy", targs = [] } } +--- Wraps an expression into Thunk.lazy, without generics arguments: +--- > Thunk.lazy(expr) +asLazy :: JExpr -> JExpr +asLazy expr = + let thunkjt = Ref { jname = JName { qual = "", base = "Thunk" }, gargs = [] } + lazy = JInvoke { args = [expr], jex = JStMem { jt = thunkjt, name = "lazy", targs = [] } } in - if strict then JAtom name else lazy name + lazy -invokeIR :: JType -> String -> JExpr -> [StriArg] -> JExpr -invokeIR jt name this args = JInvoke - { args = this : map striArgExpr args - , jex = JStMem { jt, name, targs = [] } +--- Invokes a method of an implementation record. +--- +--- Parameters: +--- - The Java type of the IR. +--- - The name of the invoked IR method. +--- - The expression of the instance of the IR. +--- - The arguments of the invoked IR method, excluding the receiver of the implemented Java class. +invokeIR :: JType -> String -> JExpr -> [String] -> JExpr +invokeIR jt name irthis args = JInvoke + { args = irthis : asLazy (JAtom "this") : map (asLazy . JAtom) args + , jex = JStMem { jt = rawType jt, name, targs = [] } } + +--- Runs an expression of type ST/IO. +--- +--- Generated code should look like: +--- > PreludeBase.TST.performUnsafe(jex).call() +tstRun :: JType -> JExpr -> JExpr +tstRun retjt jex = + let call jex = JInvoke { args = [], jex = JExMem { jex, name = "call", targs = [] } } + run retjt = JStMem + { jt = Ref { jname = JName { qual = "PreludeBase", base = "TST" }, gargs = [] } + , name = "performUnsafe" + , targs = [retjt] + } + in + call $ JInvoke { jex = run retjt, args = [jex] } diff --git a/frege/compiler/types/AbstractJava.fr b/frege/compiler/types/AbstractJava.fr index 13fe23d1..484518c3 100644 --- a/frege/compiler/types/AbstractJava.fr +++ b/frege/compiler/types/AbstractJava.fr @@ -10,6 +10,8 @@ import Compiler.common.Roman(romanUpper) import Compiler.types.JNames import Compiler.types.Types import Data.Bits +import Data.BitSetJSON () +import Data.JSON (ToJSON, toJSON) {-- @@ -24,7 +26,10 @@ data JAttr = JUnchecked | JFunctionalInterface | JOverride | JRawTypes derive Enum JAttr derive Bounded JAttr +derive Show JAttr +instance ToJSON JAttr where + toJSON = toJSON . show type Attributes = BitSet JAttr type FormalArg = (Attributes, Sigma, JType, String) @@ -36,6 +41,12 @@ type FormalArg = (Attributes, Sigma, JType, String) -} data JTVar = JTVar { !var ∷ String, !bounds ∷ JTypeBounds } +instance ToJSON JTVar where + toJSON x = JSON.struct "JTVar" $ JSON.Struct + [ JSON.assoc "var" x.var + , JSON.assoc "bounds" x.bounds + ] + {-- the bounds for a 'JTVar' or a wildcard -} @@ -46,6 +57,10 @@ data JTypeBounds = derive Eq JTypeBounds +instance ToJSON JTypeBounds where + toJSON UNBOUNDED = toJSON "UNBOUNDED" + toJSON (EXTENDS jts) = JSON.struct "EXTENDS" jts + toJSON (SUPER jt) = JSON.struct "SUPER" jt {-- @@ -99,6 +114,31 @@ nativ s gs = Nativ s gs true derive Eq JType +instance ToJSON JType where + toJSON (Ref{jname, gargs}) = JSON.struct "Ref" $ JSON.Struct + [ JSON.assoc "jname" jname + , JSON.assoc "gargs" gargs + ] + toJSON (TArg{var}) = JSON.struct "TArg" $ JSON.struct "var" var + toJSON (Wild{bounds}) = JSON.struct "Wild" $ JSON.struct "bounds" bounds + toJSON (Nativ{typ, gargs, generic}) = JSON.struct "Nativ" $ JSON.Struct + [ JSON.assoc "typ" typ + , JSON.assoc "gargs" gargs + , JSON.assoc "generic" generic + ] + toJSON (Kinded{arity, gargs}) = JSON.struct "Kinded" $ JSON.Struct + [ JSON.assoc "arity" arity + , JSON.assoc "gargs" gargs + ] + toJSON (Lazy{yields}) = JSON.struct "Lazy" $ JSON.struct "yields" yields + toJSON (Func{gargs}) = JSON.struct "Func" $ JSON.struct "gargs" gargs + toJSON (Constr{jname, gargs}) = JSON.struct "Constr" $ JSON.Struct + [ JSON.assoc "jname" jname + , JSON.assoc "gargs" gargs + ] + toJSON Something = toJSON "Something" + + --- Create a raw type (generated types possibly not functional, except for display) rawType ∷ JType → JType @@ -184,6 +224,63 @@ data JExpr = --- make a 'JStMem' from a 'JName' staticMember (JName cl base) = JStMem{jt = nativ cl [], name = base, targs = []} +instance ToJSON JExpr where + toJSON (JAtom{name}) = JSON.struct "JAtom" $ JSON.Struct + [ JSON.assoc "name" name + ] + toJSON (JNew{jt, args}) = JSON.struct "JNew" $ JSON.Struct + [ JSON.assoc "jt" jt + , JSON.assoc "args" args + ] + toJSON (JNewClass{jt, args, decls}) = JSON.struct "JNewClass" $ JSON.Struct + [ JSON.assoc "jt" jt + , JSON.assoc "args" args + , JSON.assoc "decls" decls + ] + toJSON (JLambda{fargs, code}) = JSON.struct "JLambda" $ JSON.Struct + [ JSON.assoc "fargs" fargs + , JSON.assoc "code" code + ] + toJSON (JNewArray{jt, jex}) = JSON.struct "JNewArray" $ JSON.Struct + [ JSON.assoc "jt" jt + , JSON.assoc "jex" jex + ] + toJSON (JInvoke{jex, args}) = JSON.struct "JInvoke" $ JSON.Struct + [ JSON.assoc "jex" jex + , JSON.assoc "args" args + ] + toJSON (JStMem{jt, name, targs}) = JSON.struct "JStMem" $ JSON.Struct + [ JSON.assoc "jt" jt + , JSON.assoc "name" name + , JSON.assoc "targs" targs + ] + toJSON (JExMem{jex, name, targs}) = JSON.struct "JExMem" $ JSON.Struct + [ JSON.assoc "jex" jex + , JSON.assoc "name" name + , JSON.assoc "targs" targs + ] + toJSON (JCast{jt, jex}) = JSON.struct "JCast" $ JSON.Struct + [ JSON.assoc "jt" jt + , JSON.assoc "jex" jex + ] + toJSON (JUnop{ op, jex}) = JSON.struct "JUnop" $ JSON.Struct + [ JSON.assoc " op" op + , JSON.assoc "jex" jex + ] + toJSON (JBin{j1, op, j2}) = JSON.struct "JBin" $ JSON.Struct + [ JSON.assoc "j1" j1 + , JSON.assoc "op" op + , JSON.assoc "j2" j2 + ] + toJSON (JQC{j1, j2, j3}) = JSON.struct "JQC" $ JSON.Struct + [ JSON.assoc "j1" j1 + , JSON.assoc "j2" j2 + , JSON.assoc "j3" j3 + ] + toJSON (JArrayGet{j1, j2}) = JSON.struct "JArrayGet" $ JSON.Struct + [ JSON.assoc "j1" j1 + , JSON.assoc "j2" j2 + ] @@ -205,6 +302,31 @@ data JStmt = | !JCase {jex :: JExpr, stmt :: JStmt } +instance ToJSON JStmt where + toJSON (JError x) = JSON.struct "JError" x + toJSON JEmpty = toJSON "JEmpty" + toJSON (JBlock{stmts}) = JSON.struct "JBlock" $ JSON.struct "stmts" stmts + toJSON (JReturn x) = JSON.struct "JReturn" x + toJSON (JThrow x) = JSON.struct "JThrow" x + toJSON (JAssert x) = JSON.struct "JAssert" x + toJSON (JEx x) = JSON.struct "JEx" x + toJSON (JAssign x y) = JSON.struct "JAssign" (x, y) + toJSON (JLocal{decl}) = JSON.struct "JLocal" $ JSON.struct "decl" decl + toJSON (JCond{keyword, jex, stmts}) = JSON.struct "JCond" $ JSON.Struct + [ JSON.assoc "keyword" keyword + , JSON.assoc "jex" jex + , JSON.assoc "stmts" stmts + ] + toJSON (JBlockX{keyword, stmts}) = JSON.struct "JBlockX" $ JSON.Struct + [ JSON.assoc "keyword" keyword + , JSON.assoc "stmts" stmts + ] + toJSON (JCase{jex, stmt}) = JSON.struct "JCase" $ JSON.Struct + [ JSON.assoc "jex" jex + , JSON.assoc "stmt" stmt + ] + + --- placeholder for pipehole optimization postOpt x = x @@ -242,3 +364,42 @@ data JDecl = where isComment JComment{} = true isComment _ = false + +instance ToJSON JDecl where + toJSON (JComment x) = JSON.struct "JComment" x + toJSON (JClass{attr, name, gvars, extend, implement, defs}) = JSON.struct "JClass" $ JSON.Struct + [ JSON.assoc "attr" attr + , JSON.assoc "name" name + , JSON.assoc "gvars" gvars + , JSON.assoc "extend" extend + , JSON.assoc "implement" implement + , JSON.assoc "defs" defs + ] + toJSON (JInterface{attr, name, gvars, implement, defs}) = JSON.struct "JInterface" $ JSON.Struct + [ JSON.assoc "attr" attr + , JSON.assoc "name" name + , JSON.assoc "gvars" gvars + , JSON.assoc "implement" implement + , JSON.assoc "defs" defs + ] + toJSON (JMethod{attr, gvars, jtype, name, args, body}) = JSON.struct "JMethod" $ JSON.Struct + [ JSON.assoc "attr" attr + , JSON.assoc "gvars" gvars + , JSON.assoc "jtype" jtype + , JSON.assoc "name" name + , JSON.assoc "args" args + , JSON.assoc "body" body + ] + toJSON (JConstr{attr, jtype, args, body}) = JSON.struct "JConstr" $ JSON.Struct + [ JSON.assoc "attr" attr + , JSON.assoc "jtype" jtype + , JSON.assoc "args" args + , JSON.assoc "body" body + ] + toJSON (JMember{attr, jtype, name, init}) = JSON.struct "JMember" $ JSON.Struct + [ JSON.assoc "attr" attr + , JSON.assoc "jtype" jtype + , JSON.assoc "name" name + , JSON.assoc "init" init + ] + toJSON (JWhile{body}) = JSON.struct "JWhile" $ JSON.struct "body" body diff --git a/frege/compiler/types/ConstructorField.fr b/frege/compiler/types/ConstructorField.fr index 52342bdc..abd4f6e5 100644 --- a/frege/compiler/types/ConstructorField.fr +++ b/frege/compiler/types/ConstructorField.fr @@ -4,9 +4,18 @@ module frege.compiler.types.ConstructorField where import frege.compiler.types.Positions import frege.compiler.enums.Visibility import frege.compiler.types.Types +import frege.data.JSON (ToJSON, toJSON) --- a constructor field data ConField s = !Field { pos :: Position, name, doc :: Maybe String, vis :: Visibility, strict :: Bool, typ :: SigmaT s } - +instance (ToJSON s) => ToJSON (ConField s) where + toJSON x = JSON.struct "Field" $ JSON.Struct + [ JSON.assoc "pos" x.pos + , JSON.assoc "name" x.name + , JSON.assoc "doc" x.doc + , JSON.assoc "vis" x.vis + , JSON.assoc "strict" x.strict + , JSON.assoc "typ" x.typ + ] diff --git a/frege/compiler/types/Expression.fr b/frege/compiler/types/Expression.fr index ebcd5f80..231aaf63 100644 --- a/frege/compiler/types/Expression.fr +++ b/frege/compiler/types/Expression.fr @@ -11,6 +11,7 @@ import frege.compiler.types.QNames import frege.compiler.types.Types import frege.compiler.types.Patterns import frege.compiler.types.ConstructorField +import frege.data.JSON (ToJSON, toJSON) --- create 'App' with default type 'Nothing' nApp a b = App a b Nothing @@ -71,12 +72,74 @@ instance Positioned (ExprT) where getrange x = getpos x +instance ToJSON (ExprT) where + toJSON (Vbl{pos, name, typ}) = JSON.struct "Vbl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "name" name + , JSON.assoc "typ" typ + ] + toJSON (Con{pos, name, typ}) = JSON.struct "Con" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "name" name + , JSON.assoc "typ" typ + ] + toJSON (App{fun, arg, typ}) = JSON.struct "App" $ JSON.Struct + [ JSON.assoc "fun" fun + , JSON.assoc "arg" arg + , JSON.assoc "typ" typ + ] + toJSON (Lit{pos, kind, value, typ}) = JSON.struct "Lit" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "kind" kind + , JSON.assoc "value" value + , JSON.assoc "typ" typ + ] + toJSON (Let{env, ex, typ}) = JSON.struct "Let" $ JSON.Struct + [ JSON.assoc "env" env + , JSON.assoc "ex" ex + , JSON.assoc "typ" typ + ] + toJSON (Lam{pat, ex, typ}) = JSON.struct "Lam" $ JSON.Struct + [ JSON.assoc "pat" pat + , JSON.assoc "ex" ex + , JSON.assoc "typ" typ + ] + toJSON (Ifte{cnd, thn, els, typ}) = JSON.struct "Ifte" $ JSON.Struct + [ JSON.assoc "cnd" cnd + , JSON.assoc "thn" thn + , JSON.assoc "els" els + , JSON.assoc "typ" typ + ] + toJSON (Mem{ex, member, typ}) = JSON.struct "Mem" $ JSON.Struct + [ JSON.assoc "ex" ex + , JSON.assoc "member" member + , JSON.assoc "typ" typ + ] + toJSON (Case{ckind, ex, alts, typ}) = JSON.struct "Case" $ JSON.Struct + [ JSON.assoc "ckind" ckind + , JSON.assoc "ex" ex + , JSON.assoc "alts" alts + , JSON.assoc "typ" typ + ] + toJSON (Ann{ex, typ}) = JSON.struct "Ann" $ JSON.Struct + [ JSON.assoc "ex" ex + , JSON.assoc "typ" typ + ] + + instance Positioned (CAltT) where is _ = "case alternative" getpos c = c.pat.getpos.merge c.ex.getpos getrange c = c.pat.getrange.merge c.ex.getrange +instance ToJSON (CAltT) where + toJSON x = JSON.struct "CAlt" $ JSON.Struct + [ JSON.assoc "pat" x.pat + , JSON.assoc "ex" x.ex + ] + + --##################### pattern support functions ###################################### --##################### expr support functions ######################################### diff --git a/frege/compiler/types/External.fr b/frege/compiler/types/External.fr index 4b72dbf3..028ac43b 100644 --- a/frege/compiler/types/External.fr +++ b/frege/compiler/types/External.fr @@ -3,6 +3,7 @@ module frege.compiler.types.External where import frege.compiler.types.QNames +import frege.data.JSON (ToJSON, toJSON) {-- Encode 'Tau' types and 'Kind's. @@ -41,23 +42,53 @@ derive ArrayElement TauA derive Eq TauA derive Ord TauA +instance ToJSON TauA where + toJSON x = JSON.struct "TauA" $ JSON.Struct + [ JSON.assoc "kind" x.kind + , JSON.assoc "tcon" x.tcon + , JSON.assoc "suba" x.suba + , JSON.assoc "subb" x.subb + , JSON.assoc "tvar" x.tvar + ] + data RhoA = RhoA {!rhofun::Bool, !cont::[ContextA], !sigma::Int, !rhotau::Int} derive ArrayElement RhoA derive Eq RhoA derive Ord RhoA +instance ToJSON RhoA where + toJSON x = JSON.struct "RhoA" $ JSON.Struct + [ JSON.assoc "rhofun" x.rhofun + , JSON.assoc "cont" x.cont + , JSON.assoc "sigma" x.sigma + , JSON.assoc "rhotau" x.rhotau + ] + data ContextA = CtxA {!clas::QName, !tau::Int} derive Eq ContextA derive Ord ContextA +instance ToJSON ContextA where + toJSON x = JSON.struct "CtxA" $ JSON.Struct + [ JSON.assoc "clas" x.clas + , JSON.assoc "tau" x.tau + ] + data SigmaA = SigmaA {!bound::[String], !kinds::[Int], !rho::Int} derive ArrayElement SigmaA derive Eq SigmaA derive Ord SigmaA +instance ToJSON SigmaA where + toJSON x = JSON.struct "SigmaA" $ JSON.Struct + [ JSON.assoc "bound" x.bound + , JSON.assoc "kinds" x.kinds + , JSON.assoc "rho" x.rho + ] + data ExprA = !ExprA {xkind::Int, name::Maybe QName, lkind::Int, varval::Maybe String, alts :: [Int], subx1 :: Int, subx2 :: Int, subx3 :: Int} @@ -65,6 +96,18 @@ derive ArrayElement ExprA derive Eq ExprA derive Ord ExprA +instance ToJSON ExprA where + toJSON x = JSON.struct "ExprA" $ JSON.Struct + [ JSON.assoc "xkind" x.xkind + , JSON.assoc "name" x.name + , JSON.assoc "lkind" x.lkind + , JSON.assoc "varval" x.varval + , JSON.assoc "alts" x.alts + , JSON.assoc "subx1" x.subx1 + , JSON.assoc "subx2" x.subx2 + , JSON.assoc "subx3" x.subx3 + ] + --- default "serialized" expression defEA = ExprA {xkind = 7, name = Nothing, lkind = 0, varval = Nothing, alts = [], diff --git a/frege/compiler/types/Global.fr b/frege/compiler/types/Global.fr index 00de434d..4e8b57ea 100644 --- a/frege/compiler/types/Global.fr +++ b/frege/compiler/types/Global.fr @@ -4,6 +4,7 @@ module frege.compiler.types.Global changeSTT, getSTT, liftIO, liftStG) where +import frege.data.JSON (ToJSON, toJSON) import frege.data.TreeMap as TM(TreeMap, each) import frege.java.Net(URLClassLoader) import frege.control.monad.State (State, StateT) @@ -43,12 +44,39 @@ data Options = !Options { code :: [Token] --- the extra java code to include in the output } +instance ToJSON Options where + toJSON x = JSON.struct "Options" $ JSON.Struct + [ JSON.assoc "source" x.source + , JSON.assoc "sourcePath" x.sourcePath + , JSON.assoc "flags" x.flags + , JSON.assoc "dir" x.dir + , JSON.assoc "path" x.path + , JSON.assoc "prefix" x.prefix + , JSON.assoc "encoding" x.encoding + , JSON.assoc "tRanges" x.tRanges + , JSON.assoc "target" x.target + , JSON.assoc "extending" x.extending + , JSON.assoc "implementing" x.implementing + , JSON.assoc "code" x.code + ] data Severity = HINT | WARNING | ERROR +derive Eq Severity +derive Show Severity + +instance ToJSON Severity where + toJSON = toJSON . show data Message = !Msg { pos :: Position, level :: Severity, text :: String } +instance ToJSON Message where + toJSON x = JSON.struct "Msg" $ JSON.Struct + [ JSON.assoc "pos" x.pos + , JSON.assoc "level" x.level + , JSON.assoc "text" x.text + ] + {-- Informs how tokens like 'VARID', 'CONID' and 'QUALIFIER' have been @@ -106,6 +134,28 @@ data SubSt = !Sub { code :: CharSequence --- original code (for error messages, etc.) } +instance ToJSON SubSt where + toJSON x = JSON.struct "Sub" $ JSON.Struct + [ JSON.assoc "loader" "" + , JSON.assoc "toks" x.toks + , JSON.assoc "idKind" x.idKind + , JSON.assoc "packageDoc" x.packageDoc + , JSON.assoc "sourcedefs" x.sourcedefs + , JSON.assoc "numErrors" x.numErrors + , JSON.assoc "resErrors" x.resErrors + , JSON.assoc "messages" x.messages + , JSON.assoc "nextPass" x.nextPass + , JSON.assoc "cancelled" "" + , JSON.assoc "thisPack" x.thisPack + , JSON.assoc "thisPos" x.thisPos + , JSON.assoc "nsPos" x.nsPos + , JSON.assoc "packWhy" x.packWhy + , JSON.assoc "nsUsed" x.nsUsed + , JSON.assoc "stderr" "" + , JSON.assoc "toExport" x.toExport + , JSON.assoc "code" x.code.toString + ] + --- items that are set and used during code generation data GenSt = !Gen { @@ -125,6 +175,24 @@ data GenSt = !Gen { main :: String --- bare name of the top level class, set in GenMeta } +instance ToJSON GenSt where + toJSON x = JSON.struct "Gen" $ JSON.Struct + [ JSON.assoc "printer" "" + , JSON.assoc "tunique" x.tunique + , JSON.assoc "runique" x.runique + , JSON.assoc "sunique" x.sunique + , JSON.assoc "xunique" x.xunique + , JSON.assoc "tTree" x.tTree + , JSON.assoc "rTree" x.rTree + , JSON.assoc "sTree" x.sTree + , JSON.assoc "xTree" x.xTree + , JSON.assoc "expSym" x.expSym + , JSON.assoc "consts" x.consts + , JSON.assoc "symi8" x.symi8 + , JSON.assoc "jimport" x.jimport + , JSON.assoc "main" x.main + ] + --- compiler state, appears like it was global, but threaded through 'StG' monad data Global = !Global { @@ -242,6 +310,21 @@ data Global = !Global { hasLambdaSupport ∷ Global → Bool hasLambdaSupport g = g.options.target > java7 +instance ToJSON Global where + toJSON g = JSON.struct "Global" $ JSON.Struct + [ JSON.assoc "options" g.options + , JSON.assoc "sub" g.sub + , JSON.assoc "gen" g.gen + , JSON.assoc "unique" g.unique + , JSON.assoc "packages" g.packages + , JSON.assoc "namespaces" g.namespaces + , JSON.assoc "javaEnv" g.javaEnv + , JSON.assoc "genEnv" g.genEnv + , JSON.assoc "locals" g.locals + , JSON.assoc "typEnv" g.typEnv + , JSON.assoc "tySubst" g.tySubst + ] + {-- This predicate tells if a certain package is a Prelude package @@ -521,6 +604,14 @@ data SymInfo8 = SI8 { retSig :: Sigma --- return sigma type } +instance ToJSON SymInfo8 where + toJSON x = JSON.struct "SI8" $ JSON.Struct + [ JSON.assoc "returnJT" x.returnJT + , JSON.assoc "argJTs" x.argJTs + , JSON.assoc "argSigs" x.argSigs + , JSON.assoc "retSig" x.retSig + ] + --- produce a unique number uniqid :: StG Int uniqid = do diff --git a/frege/compiler/types/ImportDetails.fr b/frege/compiler/types/ImportDetails.fr index 523b7f32..563c72af 100644 --- a/frege/compiler/types/ImportDetails.fr +++ b/frege/compiler/types/ImportDetails.fr @@ -3,6 +3,7 @@ module frege.compiler.types.ImportDetails where import frege.compiler.types.SNames +import frege.data.JSON (ToJSON, toJSON) {-- structure of an import list @@ -12,6 +13,13 @@ data ImportList = Imports { items :: [ImportItem] } +instance ToJSON ImportList where + toJSON x = JSON.struct "Imports" $ JSON.Struct + [ JSON.assoc "publik" x.publik + , JSON.assoc "except" x.except + , JSON.assoc "items" x.items + ] + {-- a single import item @@ -25,6 +33,13 @@ data ImportItem = Item { export :: ImportItem -> ImportItem export it = it.{publik = true, members <- fmap (map export)} +instance ToJSON ImportItem where + toJSON x = JSON.struct "Item" $ JSON.Struct + [ JSON.assoc "publik" x.publik + , JSON.assoc "name" x.name + , JSON.assoc "members" x.members + , JSON.assoc "alias" x.alias + ] --- Prototype for an 'Item' protoItem = Item { publik = false, name = protoSimple, members = Nothing, alias = "" } diff --git a/frege/compiler/types/JNames.fr b/frege/compiler/types/JNames.fr index 3ba9f7d0..7a41e94f 100644 --- a/frege/compiler/types/JNames.fr +++ b/frege/compiler/types/JNames.fr @@ -1,6 +1,8 @@ --- Model of Java names. module frege.compiler.types.JNames where +import frege.data.JSON (ToJSON, toJSON) + --- A Java name --- The 'JName.qual' part may have "." in it, or may be empty for unqualified names. --- The 'JName.base' part will be a simple 'String' for the last component. @@ -14,7 +16,11 @@ instance Eq JName where ja == jb = show ja == show jb hashCode ja = hashCode ja.show - +instance ToJSON JName where + toJSON x = JSON.struct "JName" $ JSON.Struct + [ JSON.assoc "qual" x.qual + , JSON.assoc "base" x.base + ] {-- diff --git a/frege/compiler/types/NSNames.fr b/frege/compiler/types/NSNames.fr index 1611f703..776ac04c 100644 --- a/frege/compiler/types/NSNames.fr +++ b/frege/compiler/types/NSNames.fr @@ -2,6 +2,8 @@ module frege.compiler.types.NSNames where +import frege.data.JSON (ToJSON, toJSON) + --- A namespace name, not to be confused with an ordinary 'String' newtype NSName = NSX { unNS :: String } @@ -15,3 +17,5 @@ derive Ord NSName derive Show NSName +instance ToJSON NSName where + toJSON x = JSON.struct "NSX" $ JSON.struct "unNS" x.unNS diff --git a/frege/compiler/types/Packs.fr b/frege/compiler/types/Packs.fr index 670b3260..f0611871 100644 --- a/frege/compiler/types/Packs.fr +++ b/frege/compiler/types/Packs.fr @@ -2,6 +2,7 @@ module frege.compiler.types.Packs where import frege.compiler.types.NSNames +import frege.data.JSON (ToJSON, toJSON) {-- * A package name can not be read without resort to the global state, @@ -38,6 +39,9 @@ instance Ord Pack derive Show Pack +instance ToJSON Pack where + toJSON (Pack.P p) = JSON.String p + --- The value of the property @-Dfrege.prelude@ or just "frege.Prelude" pPrelude = (Pack.new • fromMaybe "frege.Prelude" • System.getProperty) "frege.prelude" diff --git a/frege/compiler/types/Patterns.fr b/frege/compiler/types/Patterns.fr index 43970e02..ab4f8de2 100644 --- a/frege/compiler/types/Patterns.fr +++ b/frege/compiler/types/Patterns.fr @@ -6,6 +6,7 @@ import frege.compiler.enums.Literals import frege.compiler.types.SNames import frege.compiler.types.QNames import frege.compiler.types.Types +import frege.data.JSON (ToJSON) {-- Patterns appear in the following places: @@ -53,6 +54,49 @@ instance Positioned (PatternT a) where -- untyped 'Pattern', this is yet another identity function -- untyped p = p +instance (ToJSON a) => ToJSON (PatternT a) where + toJSON (PVar{pos, uid, var}) = JSON.struct "PVar" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "uid" uid + , JSON.assoc "var" var + ] + toJSON (PCon{pos, qname, pats}) = JSON.struct "PCon" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "qname" qname + , JSON.assoc "pats" pats + ] + toJSON (PConFS{pos, qname, fields}) = JSON.struct "PConFS" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "qname" qname + , JSON.assoc "fields" fields + ] + toJSON (PAt{pos, uid, var, pat}) = JSON.struct "PAt" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "uid" uid + , JSON.assoc "var" var + , JSON.assoc "pat" pat + ] + toJSON (PUser{pat, lazy}) = JSON.struct "PUser" $ JSON.Struct + [ JSON.assoc "pat" pat + , JSON.assoc "lazy" lazy + ] + toJSON (PLit{pos, kind, value}) = JSON.struct "PLit" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "kind" kind + , JSON.assoc "value" value + ] + toJSON (PAnn{pat, typ}) = JSON.struct "PAnn" $ JSON.Struct + [ JSON.assoc "pat" pat + , JSON.assoc "typ" typ + ] + toJSON (PMat{pos, uid, var, value}) = JSON.struct "PMat" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "uid" uid + , JSON.assoc "var" var + , JSON.assoc "value" value + ] + + --- Get the variables in a pattern in the form of 'PVar's --- This does not care about duplicates, but duplicates are forbidden anyway. patVars :: PatternT a -> [PatternT a] diff --git a/frege/compiler/types/Positions.fr b/frege/compiler/types/Positions.fr index 8cace699..2e021b8a 100644 --- a/frege/compiler/types/Positions.fr +++ b/frege/compiler/types/Positions.fr @@ -45,6 +45,7 @@ package frege.compiler.types.Positions where import Compiler.enums.TokenID import Compiler.types.Tokens +import frege.data.JSON (ToJSON, toJSON) --- things that know where they were introduced and what they are class Positioned a where @@ -82,6 +83,15 @@ instance Show Position where show pos = show pos.line +instance ToJSON Position where + toJSON x + | x == Position.null = toJSON "Position.null" + | otherwise = JSON.struct "Pos" $ JSON.Struct + [ JSON.assoc "first" x.first + , JSON.assoc "last" x.last + ] + + data Position = Pos { !first, !last :: Token } where --- overwrite 'first's token id and value and set last = first --- used to construct custom tokens for generated code diff --git a/frege/compiler/types/QNames.fr b/frege/compiler/types/QNames.fr index 091ba17e..e603f356 100644 --- a/frege/compiler/types/QNames.fr +++ b/frege/compiler/types/QNames.fr @@ -2,6 +2,7 @@ module frege.compiler.types.QNames where import frege.compiler.types.Packs +import frege.data.JSON (ToJSON, toJSON) --- qualified name data QName = @@ -44,6 +45,17 @@ derive Ord QName derive Show QName +instance ToJSON QName where + toJSON (TName{pack,base}) = + JSON.struct "TName" $ JSON.Struct [ JSON.assoc "pack" pack, JSON.assoc "base" base ] + toJSON (VName{pack,base}) = + JSON.struct "VName" $ JSON.Struct [ JSON.assoc "pack" pack, JSON.assoc "base" base ] + toJSON (MName{tynm,base}) = + JSON.struct "MName" $ JSON.Struct [ JSON.assoc "tynm" tynm, JSON.assoc "base" base ] + toJSON (Local{uid,base}) = + JSON.struct "Local" $ JSON.Struct [ JSON.assoc "uid" uid, JSON.assoc "base" base ] + + {-- (isTName x) ist das Wahre gdw. x unter den Begriff Typname fällt -} isTName (TName _ _) = true isTName _ = false diff --git a/frege/compiler/types/SNames.fr b/frege/compiler/types/SNames.fr index 6f8a967d..f9b3c982 100644 --- a/frege/compiler/types/SNames.fr +++ b/frege/compiler/types/SNames.fr @@ -4,6 +4,7 @@ module frege.compiler.types.SNames where import frege.compiler.types.Tokens import frege.compiler.enums.TokenID(CONID,VARID,LOP1,NOP16) +import frege.data.JSON (ToJSON, toJSON) --- an unresolved, maybe qualified identifier data SName = ! Simple { id :: Token } {-- @@ -23,6 +24,18 @@ instance Show SName where show (With1 {ty, id}) = ty.value ++ "." ++ id.value show (With2 {ns, ty, id}) = ns.value ++ "." ++ ty.value ++ "." ++ id.value +instance ToJSON SName where + toJSON (Simple{id}) = JSON.struct "Simple" $ JSON.struct "id" id + toJSON (With1{ty,id}) = JSON.struct "With1" $ JSON.Struct + [ JSON.assoc "ty" ty + , JSON.assoc "id" id + ] + toJSON (With2{ns,ty,id}) = JSON.struct "With2" $ JSON.Struct + [ JSON.assoc "ns" ns + , JSON.assoc "ty" ty + , JSON.assoc "id" id + ] + --- > "foo" `qBy` Conid --- supplements a partial name with a "member" qBy :: Token -> SName -> SName diff --git a/frege/compiler/types/SourceDefinitions.fr b/frege/compiler/types/SourceDefinitions.fr index 0dd1b367..c2177578 100644 --- a/frege/compiler/types/SourceDefinitions.fr +++ b/frege/compiler/types/SourceDefinitions.fr @@ -12,6 +12,7 @@ import frege.compiler.types.ImportDetails import frege.compiler.types.Types import frege.compiler.instances.PositionedSName import frege.compiler.types.ConstructorField +import frege.data.JSON (ToJSON, toJSON) --- create 'App' @@ -55,6 +56,107 @@ data DefinitionS = doc::Maybe String} | ModDcl {pos::Position, extending::Maybe TauS, implementing::[TauS], code::[Token]} +instance ToJSON DefinitionS where + toJSON (ImpDcl{pos,pack,as,imports}) = JSON.struct "ImpDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "pack" pack + , JSON.assoc "as" as + , JSON.assoc "imports" imports + ] + toJSON (FixDcl{pos, opid, ops}) = JSON.struct "FixDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "opid" opid + , JSON.assoc "ops" ops + ] + toJSON (DocDcl{pos, text}) = JSON.struct "DocDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "text" text + ] + toJSON (TypDcl{pos, vis, name, vars, typ, doc}) = JSON.struct "TypDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "vars" vars + , JSON.assoc "typ" typ + , JSON.assoc "doc" doc + ] + toJSON (ClaDcl{pos, vis, name, clvar, supers, defs, doc}) = JSON.struct "ClaDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "clvar" clvar + , JSON.assoc "supers" supers + , JSON.assoc "defs" defs + , JSON.assoc "doc" doc + ] + toJSON (InsDcl{pos, vis, clas, typ, defs, doc}) = JSON.struct "InsDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "clas" clas + , JSON.assoc "typ" typ + , JSON.assoc "defs" defs + , JSON.assoc "doc" doc + ] + toJSON (DrvDcl{pos, vis, clas, typ, doc}) = JSON.struct "DrvDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "clas" clas + , JSON.assoc "typ" typ + , JSON.assoc "doc" doc + ] + toJSON (AnnDcl{pos, vis, name, typ, doc}) = JSON.struct "AnnDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "typ" typ + , JSON.assoc "doc" doc + ] + toJSON (NatDcl{pos, vis, name, txs, meth, isPure, gargs, doc}) = JSON.struct "NatDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "txs" txs + , JSON.assoc "meth" meth + , JSON.assoc "isPure" isPure + , JSON.assoc "gargs" gargs + , JSON.assoc "doc" doc + ] + toJSON (FunDcl{vis, lhs, pats, expr, doc, positions}) = JSON.struct "FunDcl" $ JSON.Struct + [ JSON.assoc "vis" vis + , JSON.assoc "lhs" lhs + , JSON.assoc "pats" pats + , JSON.assoc "expr" expr + , JSON.assoc "doc" doc + , JSON.assoc "positions" positions + ] + toJSON (DatDcl{pos, vis, name, newt, vars, ctrs, defs, doc}) = JSON.struct "DatDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "newt" newt + , JSON.assoc "vars" vars + , JSON.assoc "ctrs" ctrs + , JSON.assoc "defs" defs + , JSON.assoc "doc" doc + ] + toJSON (JavDcl{pos, vis, name, isPure, jclas, vars, gargs, defs, doc}) = JSON.struct "JavDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "isPure" isPure + , JSON.assoc "jclas" jclas + , JSON.assoc "vars" vars + , JSON.assoc "gargs" gargs + , JSON.assoc "defs" defs + , JSON.assoc "doc" doc + ] + toJSON (ModDcl{pos, extending, implementing, code}) = JSON.struct "ModDcl" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "extending" extending + , JSON.assoc "implementing" implementing + , JSON.assoc "code" code + ] + --- Is this a function binding? --- If so, return the identifier. funbinding FunDcl{lhs = Vbl{name=Simple{id}},pats} @@ -86,6 +188,14 @@ patbinding _ = false data DCon = DCon {pos::Position, vis::Visibility, name::String, flds::[ConField SName], doc::Maybe String} +instance ToJSON DCon where + toJSON x = JSON.struct "DCon" $ JSON.Struct + [ JSON.assoc "pos" x.pos + , JSON.assoc "vis" x.vis + , JSON.assoc "name" x.name + , JSON.assoc "flds" x.flds + , JSON.assoc "doc" x.doc + ] type DConS = DCon @@ -202,12 +312,73 @@ instance Positioned ExprS where getrange x = getpos x +instance ToJSON ExprS where + toJSON (Vbl{name}) = JSON.struct "Vbl" $ JSON.struct "name" name + toJSON (Lit{pos, kind, value}) = JSON.struct "Lit" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "kind" kind + , JSON.assoc "value" value + ] + toJSON (Con{name}) = JSON.struct "Con" $ JSON.struct "name" name + toJSON (ConFS{name, fields}) = JSON.struct "ConFS" $ JSON.Struct + [ JSON.assoc "name" name + , JSON.assoc "fields" fields + ] + toJSON (App{fun, arg}) = JSON.struct "App" $ JSON.Struct + [ JSON.assoc "fun" fun + , JSON.assoc "arg" arg + ] + toJSON (Let{defs, ex}) = JSON.struct "Let" $ JSON.Struct + [ JSON.assoc "defs" defs + , JSON.assoc "ex" ex + ] + toJSON (Lam{pat, ex, fromDO}) = JSON.struct "Lam" $ JSON.Struct + [ JSON.assoc "pat" pat + , JSON.assoc "ex" ex + , JSON.assoc "fromDO" fromDO + ] + toJSON (Ifte{cnd, thn, els}) = JSON.struct "Ifte" $ JSON.Struct + [ JSON.assoc "cnd" cnd + , JSON.assoc "thn" thn + , JSON.assoc "els" els + ] + toJSON (Mem{ex, member}) = JSON.struct "Mem" $ JSON.Struct + [ JSON.assoc "ex" ex + , JSON.assoc "member" member + ] + toJSON (Case{ckind, ex, alts}) = JSON.struct "Case" $ JSON.Struct + [ JSON.assoc "ckind" ckind + , JSON.assoc "ex" ex + , JSON.assoc "alts" alts + ] + toJSON (Ann{ex, typ}) = JSON.struct "Ann" $ JSON.Struct + [ JSON.assoc "ex" ex + , JSON.assoc "typ" typ + ] + toJSON (Term{ex}) = JSON.struct "Term" $ JSON.struct "ex" ex + toJSON (Infx{name, left, right}) = JSON.struct "Infx" $ JSON.Struct + [ JSON.assoc "name" name + , JSON.assoc "left" left + , JSON.assoc "right" right + ] + toJSON (Enclosed{firstT, lastT, ex}) = JSON.struct "Enclosed" $ JSON.Struct + [ JSON.assoc "firstT" firstT + , JSON.assoc "lastT" lastT + , JSON.assoc "ex" ex + ] + instance Positioned (CAltS) where is _ = "case alternative" getpos c = c.pat.getpos.merge c.ex.getpos getrange c = c.pat.getrange.merge c.ex.getrange +instance ToJSON (CAltS) where + toJSON x = JSON.struct "CAlt" $ JSON.Struct + [ JSON.assoc "pat" x.pat + , JSON.assoc "ex" x.ex + ] + --- retrieve and return the prospective pattern variables contained in this expression --- > Vbl {Simple{Token{VARID}}} --- expression types that cannot be patterns are ignored. diff --git a/frege/compiler/types/Strictness.fr b/frege/compiler/types/Strictness.fr index 669e2da1..4f14033f 100644 --- a/frege/compiler/types/Strictness.fr +++ b/frege/compiler/types/Strictness.fr @@ -1,6 +1,8 @@ --- Strictness information for function arguments module frege.compiler.types.Strictness where +import frege.data.JSON (ToJSON, toJSON) + --- Strictness information for function arguments --- This is stored in 'SymD' and 'SymV' symbols. data Strictness = U --- lazy argument @@ -32,6 +34,10 @@ instance Show Strictness where show (S []) = "s" show (S xs) = "s(" ++ joined "" (map show xs) ++ ")" +instance ToJSON Strictness where + toJSON U = toJSON "U" + toJSON (S xs) = JSON.struct "S" xs + {-- * [usage] @decodeS string@ diff --git a/frege/compiler/types/Symbols.fr b/frege/compiler/types/Symbols.fr index 91a40d18..d0fbf567 100644 --- a/frege/compiler/types/Symbols.fr +++ b/frege/compiler/types/Symbols.fr @@ -1,7 +1,9 @@ --- Information about named items. module frege.compiler.types.Symbols where +import frege.data.BitSetJSON () import frege.data.TreeMap as TM(TreeMap, each, values) +import frege.data.JSON (ToJSON, toJSON) import frege.control.monad.State import frege.compiler.enums.RFlag(RState, RFlag) import frege.compiler.types.Positions @@ -91,3 +93,98 @@ instance Positioned (SymbolT g) where -- untyped = id +instance ToJSON (SymbolT global) where + toJSON (SymT{sid, pos, vis, doc, name, kind, typ, env, nativ, gargs, product, enum, pur, newt}) = + JSON.struct "SymT" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "kind" kind + , JSON.assoc "typ" typ + , JSON.assoc "env" env + , JSON.assoc "nativ" nativ + , JSON.assoc "gargs" gargs + , JSON.assoc "product" product + , JSON.assoc "enum" enum + , JSON.assoc "pur" pur + , JSON.assoc "newt" newt + ] + toJSON (SymL{sid, pos, vis, name, alias}) = + JSON.struct "SymL" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "name" name + , JSON.assoc "alias" alias + ] + toJSON (SymD{sid, pos, vis, doc, name, cid, typ, flds, strsig, op}) = + JSON.struct "SymD" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "cid" cid + , JSON.assoc "typ" typ + , JSON.assoc "flds" flds + , JSON.assoc "strsig" strsig + , JSON.assoc "op" op + ] + toJSON (SymC{sid, pos, vis, doc, name, tau, supers, insts, env}) = + JSON.struct "SymC" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "tau" tau + , JSON.assoc "supers" supers + , JSON.assoc "insts" insts + , JSON.assoc "env" env + ] + toJSON (SymI{sid, pos, vis, doc, name, clas, typ, env}) = + JSON.struct "SymI" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "clas" clas + , JSON.assoc "typ" typ + , JSON.assoc "env" env + ] + toJSON (SymV{sid, pos, vis, doc, name, typ, expr, nativ, pur, anno, exported, state, strsig, depth, rkind, throwing, over, gargs, op}) = + JSON.struct "SymV" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "typ" typ + , JSON.assoc "expr" $ fmap (const "") expr + , JSON.assoc "nativ" nativ + , JSON.assoc "pur" pur + , JSON.assoc "anno" anno + , JSON.assoc "exported" exported + , JSON.assoc "state" state + , JSON.assoc "strsig" strsig + , JSON.assoc "depth" depth + , JSON.assoc "rkind" rkind + , JSON.assoc "throwing" throwing + , JSON.assoc "over" over + , JSON.assoc "gargs" gargs + , JSON.assoc "op" op + ] + toJSON (SymA{sid, pos, vis, doc, name, kind, typ, vars}) = + JSON.struct "SymA" $ JSON.Struct + [ JSON.assoc "sid" sid + , JSON.assoc "pos" pos + , JSON.assoc "vis" vis + , JSON.assoc "doc" doc + , JSON.assoc "name" name + , JSON.assoc "kind" kind + , JSON.assoc "typ" typ + , JSON.assoc "vars" vars + ] diff --git a/frege/compiler/types/Targets.fr b/frege/compiler/types/Targets.fr index 3e87897c..947bb79d 100644 --- a/frege/compiler/types/Targets.fr +++ b/frege/compiler/types/Targets.fr @@ -1,6 +1,8 @@ --- Model the compilation target, conversion between "1.8" and 'Target' module frege.compiler.types.Targets where +import frege.data.JSON (ToJSON, toJSON) + --- Compilation target data Target = Target {!major, !minor :: Int } where --- decode a target specification @@ -24,6 +26,12 @@ instance Show Target where derive Eq Target derive Ord Target +instance ToJSON Target where + toJSON x = JSON.struct "Target" $ JSON.Struct + [ JSON.assoc "major" x.major + , JSON.assoc "minor" x.minor + ] + --- The 'Target' corresponding to our running VM --- This is based on the system property *java.specification.version* thisTarget = fromMaybe bad do diff --git a/frege/compiler/types/Tokens.fr b/frege/compiler/types/Tokens.fr index 077f6b84..7aed0811 100644 --- a/frege/compiler/types/Tokens.fr +++ b/frege/compiler/types/Tokens.fr @@ -2,6 +2,7 @@ module frege.compiler.types.Tokens where import frege.compiler.enums.TokenID +import frege.data.JSON (ToJSON, toJSON) --- line numbers type Line = Int @@ -66,8 +67,18 @@ instance Ord KeyToken where derive ArrayElement Token - - +instance ToJSON Token where + toJSON x = JSON.struct "Token" $ JSON.Struct + [ JSON.assoc "tokid" x.tokid + , JSON.assoc "value" x.value + , JSON.assoc "line" x.line + , JSON.assoc "col" x.col + , JSON.assoc "offset" x.offset + , JSON.assoc "qual" x.qual + ] + +instance ToJSON KeyToken where + toJSON (KeyTk x) = toJSON x prelToken = Token CONID "Prelude" 1 0 0 [] diff --git a/frege/compiler/types/Types.fr b/frege/compiler/types/Types.fr index 3e10573f..45fc37cb 100644 --- a/frege/compiler/types/Types.fr +++ b/frege/compiler/types/Types.fr @@ -5,6 +5,7 @@ import frege.compiler.types.Positions import frege.compiler.types.SNames import frege.compiler.types.Packs import frege.compiler.types.QNames +import frege.data.JSON (ToJSON, toJSON) import Data.TreeMap(insert) type Kind = KindT QName @@ -42,6 +43,12 @@ instance Show (KindT s) where showsub KGen{} = "generic" showsub k = "(" ++ show k ++ ")" +instance (ToJSON s) => ToJSON (KindT s) where + toJSON KVar = toJSON "KVar" + toJSON KType = toJSON "KType" + toJSON (KGen t) = JSON.struct "KGen" t + toJSON (KApp k l) = JSON.struct "KApp" (k, l) + -- check equality of kinds, two KGen are treated equal keq :: Eq a ⇒ KindT a → KindT a → Bool keq KType KType = true @@ -84,6 +91,21 @@ instance Ord (MetaTvT s) where Rigid{} <=> Flexi{} = Gt tv1 <=> tv2 = tv1.uid. <=> tv2.uid + +instance (ToJSON s) => ToJSON (MetaTvT s) where + toJSON (Flexi {uid, hint, kind}) = + JSON.struct "Flexi" $ JSON.Struct + [ JSON.assoc "uid" uid + , JSON.assoc "hint" hint + , JSON.assoc "kind" kind + ] + toJSON (Rigid {uid, hint, kind}) = + JSON.struct "Rigid" $ JSON.Struct + [ JSON.assoc "uid" uid + , JSON.assoc "hint" hint + , JSON.assoc "kind" kind + ] + --- The only variant that is ever used. type MetaTv = MetaTvT QName @@ -297,6 +319,20 @@ instance Positioned (TauT a) where getpos t | t.{pos?} = t.pos | otherwise = Position.null +instance (ToJSON a) => ToJSON (TauT a) where + toJSON (TApp s t) = JSON.struct "TApp" (s, t) + toJSON (TCon {pos, name}) = JSON.struct "TCon" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "name" name + ] + toJSON (TVar {pos, kind, var}) = JSON.struct "TVar" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "kind" kind + , JSON.assoc "var" var + ] + toJSON (TSig s) = JSON.struct "TSig" s + toJSON (Meta m) = JSON.struct "Meta" m + instance Positioned (RhoT a) where is p = "rho type" @@ -306,17 +342,44 @@ instance Positioned (RhoT a) where where c = Position.merges (map Context.getpos rho.context) +instance (ToJSON a) => ToJSON (RhoT a) where + toJSON (RhoFun {context, sigma, rho}) = + JSON.struct "RhoFun" $ JSON.Struct + [ JSON.assoc "context" context + , JSON.assoc "sigma" sigma + , JSON.assoc "rho" rho + ] + toJSON (RhoTau {context, tau}) = + JSON.struct "RhoTau" $ JSON.Struct + [ JSON.assoc "context" context + , JSON.assoc "tau" tau + ] + instance Positioned (ContextT a) where is p = "constraint" getpos c = c.pos +instance (ToJSON a) => ToJSON (ContextT a) where + toJSON (Ctx {pos, cname, tau}) = + JSON.struct "Ctx" $ JSON.Struct + [ JSON.assoc "pos" pos + , JSON.assoc "cname" cname + , JSON.assoc "tau" tau + ] + instance Positioned (SigmaT a) where is s = "sigma type" getpos s = s.rho.getpos +instance (ToJSON a) => ToJSON (SigmaT a) where + toJSON s = JSON.struct "ForAll" $ JSON.Struct + [ JSON.assoc "bound" s.bound + , JSON.assoc "rho" s.rho + ] + --- true if and only if the 'Tau' type is a 'TVar' or an application of 'TVar's isTvApp (TVar {}) = true diff --git a/frege/data/BitSetJSON.fr b/frege/data/BitSetJSON.fr new file mode 100644 index 00000000..c8860544 --- /dev/null +++ b/frege/data/BitSetJSON.fr @@ -0,0 +1,8 @@ +--- frege.data.JSON depends on frege.data.Bits; importing frege.data.JSOn from frege.data.Bits leads to a circular dependency +module frege.data.BitSetJSON where + +import frege.data.JSON (ToJSON, toJSON) +import frege.data.Bits (BitSet) + +instance (ToJSON a, Enum a) => ToJSON (BitSet a) where + toJSON = toJSON . BitSet.toList diff --git a/frege/data/TreeMap.fr b/frege/data/TreeMap.fr index 952f4731..f5447015 100644 --- a/frege/data/TreeMap.fr +++ b/frege/data/TreeMap.fr @@ -155,6 +155,7 @@ module frege.data.TreeMap -- import frege.data.List (elemBy, partitioned, sortBy, groupBy) import frege.Prelude hiding (!!) +import frege.data.JSON (ToJSON, toJSON) import frege.data.Monoid as M(Monoid) import Data.Traversable(traverse, Traversable) @@ -827,6 +828,9 @@ instance Traversable (TreeMap k) where foldl = foldValues foldr = foldrValues +instance (ToJSON k, ToJSON v) => ToJSON (TreeMap k v) where + toJSON = toJSON . each + type TreeSet a = TreeMap a () including s o = insert o () s diff --git a/sample/.gitignore b/sample/.gitignore new file mode 100644 index 00000000..ea8c4bf7 --- /dev/null +++ b/sample/.gitignore @@ -0,0 +1 @@ +/target diff --git a/sample/Hello.java b/sample/Hello.java new file mode 100644 index 00000000..1014cb23 --- /dev/null +++ b/sample/Hello.java @@ -0,0 +1,3 @@ +public interface Hello { + public void hello(); +} diff --git a/sample/J.java b/sample/J.java new file mode 100644 index 00000000..7ff53681 --- /dev/null +++ b/sample/J.java @@ -0,0 +1,8 @@ +public interface J { + public int getFoo(); + public int getBarJava(); + public boolean getBool(); + + public int add(int x, int y); + public int add(int x, int y, int z); +} diff --git a/sample/Makefile b/sample/Makefile new file mode 100644 index 00000000..6e035916 --- /dev/null +++ b/sample/Makefile @@ -0,0 +1,11 @@ +all: + mkdir -p build + -java -cp ../build frege.compiler.Main -d build -ascii -make *.fr + +clean: + $(RM) -r build + +run: all + for f in *.fr; do cls=$${f%.fr}; echo ========== $$cls ==========; java -cp ../build:build $$cls; done + +.PHONY: all clean run diff --git a/sample/UseHello.fr b/sample/UseHello.fr new file mode 100644 index 00000000..f1a48dbf --- /dev/null +++ b/sample/UseHello.fr @@ -0,0 +1,11 @@ +module UseHello where + +data HelloImpl s = HelloImpl { hello :: Hello -> ST s () } + +data Hello = pure native Hello where + pure native new "extends" :: HelloImpl s -> Hello + native hello :: Hello -> ST s () + +main = do + let h = Hello.new $ HelloImpl { hello = \_ -> println "Hello Frege!" } + h.hello diff --git a/sample/UseJ.fr b/sample/UseJ.fr new file mode 100644 index 00000000..9df10b2d --- /dev/null +++ b/sample/UseJ.fr @@ -0,0 +1,40 @@ +module UseJ where + +data IR = IR + { getFoo :: J -> Int, getBar :: J -> Int, getBool :: J -> Bool + , add2 :: J -> Int -> Int -> Int + , add3 :: J -> Int -> Int -> Int -> Int + } + +data J = pure native J where + pure native new "extends" :: IR -> J + pure native getFoo :: J -> Int + pure native getBar getBarJava :: J -> Int + pure native getBool :: J -> Bool + pure native add2 add :: J -> Int -> Int -> Int + pure native add3 add :: J -> Int -> Int -> Int -> Int + +-- an alternative way to create a new J +pure native newJ "extends" :: IR -> J + +main = do + let j = J.new $ IR + { getFoo = const 123, getBar = const 5, getBool = const False + , add2 = \_ x y -> x + y + , add3 = \_ x y z -> x + y + z + } + useJ j + let j = newJ $ IR + { getFoo = const 15000, getBar = const 80, getBool = const True + , add2 = \_ x y -> x * y + , add3 = \_ x y z -> x * y * z + } + useJ j + +useJ :: J -> IO () +useJ j = do + println j.getFoo + println j.getBar + println j.getBool + println $ j.add2 3 4 + println $ j.add3 3 4 5 diff --git a/sample/UsePureFunction.fr b/sample/UsePureFunction.fr new file mode 100644 index 00000000..5a9b837c --- /dev/null +++ b/sample/UsePureFunction.fr @@ -0,0 +1,13 @@ +module UsePureFunction where + +data PureFunctionImpl t r = PureFunctionImpl + { apply :: PureFunction t r -> t -> r + } + +data PureFunction t r = pure native java.util.function.Function where + pure native apply :: PureFunction t r -> t -> r + pure native new "extends" :: PureFunctionImpl t r -> PureFunction t r + +main = do + let pf = PureFunction.new PureFunctionImpl { apply = \_ -> Int.succ } + println $ "This should hold: 2 == " ++ show (pf.apply 1)