hydra-java-0.17.0: src/main/haskell/Hydra/Java/Coder.hs
-- Note: this is an automatically generated file. Do not edit.
-- | Java code generator: converts Hydra modules to Java source code
module Hydra.Java.Coder where
import qualified Hydra.Analysis as Analysis
import qualified Hydra.Annotations as Annotations
import qualified Hydra.Arity as Arity
import qualified Hydra.Ast as Ast
import qualified Hydra.Checking as Checking
import qualified Hydra.Classes as Classes
import qualified Hydra.Coders as Coders
import qualified Hydra.Constants as Constants
import qualified Hydra.Core as Core
import qualified Hydra.Decode.Core as DecodeCore
import qualified Hydra.Dependencies as Dependencies
import qualified Hydra.Encode.Core as EncodeCore
import qualified Hydra.Environment as Environment
import qualified Hydra.Error.Checking as ErrorChecking
import qualified Hydra.Error.Core as ErrorCore
import qualified Hydra.Error.Packaging as ErrorPackaging
import qualified Hydra.Errors as Errors
import qualified Hydra.File as File
import qualified Hydra.Formatting as Formatting
import qualified Hydra.Graph as Graph
import qualified Hydra.Inference as Inference
import qualified Hydra.Java.Environment as JavaEnvironment
import qualified Hydra.Java.Language as Language
import qualified Hydra.Java.Names as JavaNames
import qualified Hydra.Java.Serde as Serde
import qualified Hydra.Java.Syntax as Syntax
import qualified Hydra.Java.Utils as Utils
import qualified Hydra.Json.Model as Model
import qualified Hydra.Lexical as Lexical
import qualified Hydra.Overlay.Haskell.Lib.Eithers as Eithers
import qualified Hydra.Overlay.Haskell.Lib.Equality as Equality
import qualified Hydra.Overlay.Haskell.Lib.Lists as Lists
import qualified Hydra.Overlay.Haskell.Lib.Literals as Literals
import qualified Hydra.Overlay.Haskell.Lib.Logic as Logic
import qualified Hydra.Overlay.Haskell.Lib.Maps as Maps
import qualified Hydra.Overlay.Haskell.Lib.Math as Math
import qualified Hydra.Overlay.Haskell.Lib.Optionals as Optionals
import qualified Hydra.Overlay.Haskell.Lib.Pairs as Pairs
import qualified Hydra.Overlay.Haskell.Lib.Sets as Sets
import qualified Hydra.Overlay.Haskell.Lib.Strings as Strings
import qualified Hydra.Names as Names
import qualified Hydra.Packaging as Packaging
import qualified Hydra.Parsing as Parsing
import qualified Hydra.Paths as Paths
import qualified Hydra.Predicates as Predicates
import qualified Hydra.Query as Query
import qualified Hydra.Relational as Relational
import qualified Hydra.Resolution as Resolution
import qualified Hydra.Rewriting as Rewriting
import qualified Hydra.Scoping as Scoping
import qualified Hydra.Serialization as Serialization
import qualified Hydra.Show.Core as ShowCore
import qualified Hydra.Sorting as Sorting
import qualified Hydra.Strip as Strip
import qualified Hydra.Tabular as Tabular
import qualified Hydra.Testing as Testing
import qualified Hydra.Topology as Topology
import qualified Hydra.Typed as Typed
import qualified Hydra.Typing as Typing
import qualified Hydra.Util as Util
import qualified Hydra.Validation as Validation
import qualified Hydra.Variables as Variables
import qualified Hydra.Variants as Variants
import Prelude hiding (Enum, Ordering, decodeFloat, encodeFloat, fail, map, pure, sum)
import qualified Data.Scientific as Sci
import qualified Data.Map as M
import qualified Data.Set as S
addComment :: Syntax.ClassBodyDeclaration -> Core.FieldType -> t0 -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
addComment decl field cx g =
Eithers.map (\c -> Syntax.ClassBodyDeclarationWithComments {
Syntax.classBodyDeclarationWithCommentsValue = decl,
Syntax.classBodyDeclarationWithCommentsComments = c}) (Annotations.commentsFromFieldType cx g field)
analyzeJavaFunction :: JavaEnvironment.JavaEnvironment -> Core.Term -> Typing.InferenceContext -> t0 -> Either t1 (Typing.FunctionStructure JavaEnvironment.JavaEnvironment)
analyzeJavaFunction env term cx g = Analysis.analyzeFunctionTerm cx javaEnvGetGraph javaEnvSetGraph env term
annotateBodyWithCod :: Core.Type -> Core.Term -> Core.Term
annotateBodyWithCod typ term =
let setAnn = \t -> Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ typ)) t
in case (Strip.deannotateTerm term) of
Core.TermTypeApplication _ -> setAnn term
Core.TermApplication v0 ->
let lhs = Core.applicationFunction v0
rhs = Core.applicationArgument v0
annotatedRhs =
case (Strip.deannotateTerm rhs) of
Core.TermTypeApplication _ -> annotateBodyWithCod (extractArgType lhs typ) rhs
_ -> rhs
in (setAnn (Core.TermApplication (Core.Application {
Core.applicationFunction = lhs,
Core.applicationArgument = annotatedRhs})))
_ -> setAnn term
annotateLambdaArgs :: Core.Name -> [Core.Type] -> [Core.Term] -> t0 -> Graph.Graph -> Either t1 [Core.Term]
annotateLambdaArgs cname tApps argTerms cx g =
Logic.ifElse (Lists.null tApps) (Right argTerms) (Eithers.bind (Eithers.bind (Right (Lexical.lookupBinding g cname)) (\mel -> Optionals.cases mel (Right (Optionals.map (\prim -> Scoping.termSignatureToTypeScheme (Packaging.primitiveDefinitionSignature (Graph.primitiveDefinition prim))) (Maps.lookup cname (Graph.graphPrimitives g)))) (\el -> Right (Core.bindingTypeScheme el)))) (\mts -> Optionals.cases mts (Right argTerms) (\ts ->
let schemeType = Core.typeSchemeBody ts
schemeTypeVars = collectTypeVars schemeType
schemeVars = Lists.filter (\v -> Sets.member v schemeTypeVars) (Core.typeSchemeVariables ts)
in (Logic.ifElse (Logic.or (Lists.null schemeVars) (Logic.not (Equality.equal (Lists.length schemeVars) (Lists.length tApps)))) (Right argTerms) (
let subst = Maps.fromList (Lists.zip schemeVars tApps)
expectedTypes = peelExpectedTypes subst (Lists.length argTerms) schemeType
in (Right (Lists.zipWith (\arg -> \mExpected -> propagateType mExpected arg) argTerms (Lists.concat2 expectedTypes (Lists.replicate (Lists.length argTerms) (Core.TypeVariable (Core.Name "unused")))))))))))
applyCastIfSafe :: JavaEnvironment.Aliases -> Core.Type -> Syntax.Expression -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Expression
applyCastIfSafe aliases castType expr cx g =
let trusted = JavaEnvironment.aliasesTrustedTypeVars aliases
inScope = JavaEnvironment.aliasesInScopeTypeParams aliases
castVars = collectTypeVars castType
javaTypeVars =
Sets.fromList (Lists.filter (\v -> Logic.or (Sets.member v inScope) (isLambdaBoundVariable v)) (Sets.toList castVars))
isSafe = Logic.or (Sets.null trusted) (Logic.or (Sets.null javaTypeVars) (Sets.null (Sets.difference javaTypeVars trusted)))
in (Logic.ifElse isSafe (Eithers.bind (encodeType aliases Sets.empty castType cx g) (\jtype -> Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt -> Right (Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression rt (Utils.javaExpressionToJavaUnaryExpression expr)))))) (Right expr))
applyJavaArg :: Syntax.Expression -> Syntax.Expression -> Syntax.Expression
applyJavaArg expr jarg =
Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation (Just (Right (Utils.javaExpressionToJavaPrimary expr))) (Syntax.Identifier JavaNames.applyMethodName) [
jarg])
applyOvergenSubstToTermAnnotations :: M.Map Core.Name Core.Type -> Core.Term -> t0 -> Graph.Graph -> Either t1 Core.Term
applyOvergenSubstToTermAnnotations subst term0 cx g = Right (applyOvergenSubstToTermAnnotations_go subst g term0)
applyOvergenSubstToTermAnnotations_go :: M.Map Core.Name Core.Type -> Graph.Graph -> Core.Term -> Core.Term
applyOvergenSubstToTermAnnotations_go subst cx term =
case term of
Core.TermAnnotated v0 ->
let inner = Core.annotatedTermBody v0
ann = Annotations.getAnnotationMap (Core.annotatedTermAnnotation v0)
ann_ =
Optionals.cases (Maps.lookup Constants.keyType ann) ann (\typeTerm -> Eithers.either (\_ -> ann) (\t ->
let t_ = substituteTypeVarsWithTypes subst t
in (Maps.insert Constants.keyType (EncodeCore.type_ t_) ann)) (DecodeCore.type_ cx typeTerm))
in (Core.TermAnnotated (Core.AnnotatedTerm {
Core.annotatedTermBody = (applyOvergenSubstToTermAnnotations_go subst cx inner),
Core.annotatedTermAnnotation = (Annotations.wrapAnnotationMap ann_)}))
Core.TermApplication v0 -> Core.TermApplication (Core.Application {
Core.applicationFunction = (applyOvergenSubstToTermAnnotations_go subst cx (Core.applicationFunction v0)),
Core.applicationArgument = (applyOvergenSubstToTermAnnotations_go subst cx (Core.applicationArgument v0))})
Core.TermLambda v0 -> Core.TermLambda (Core.Lambda {
Core.lambdaParameter = (Core.lambdaParameter v0),
Core.lambdaDomain = (Optionals.map (\d -> substituteTypeVarsWithTypes subst d) (Core.lambdaDomain v0)),
Core.lambdaBody = (applyOvergenSubstToTermAnnotations_go subst cx (Core.lambdaBody v0))})
Core.TermCases v0 -> Core.TermCases (Core.CaseStatement {
Core.caseStatementTypeName = (Core.caseStatementTypeName v0),
Core.caseStatementDefault = (Optionals.map (\d -> applyOvergenSubstToTermAnnotations_go subst cx d) (Core.caseStatementDefault v0)),
Core.caseStatementCases = (Lists.map (\fld -> Core.CaseAlternative {
Core.caseAlternativeName = (Core.caseAlternativeName fld),
Core.caseAlternativeHandler = (applyOvergenSubstToTermAnnotations_go subst cx (Core.caseAlternativeHandler fld))}) (Core.caseStatementCases v0))})
Core.TermLet v0 -> Core.TermLet (Core.Let {
Core.letBindings = (Lists.map (\b -> Core.Binding {
Core.bindingName = (Core.bindingName b),
Core.bindingTerm = (applyOvergenSubstToTermAnnotations_go subst cx (Core.bindingTerm b)),
Core.bindingTypeScheme = (Core.bindingTypeScheme b)}) (Core.letBindings v0)),
Core.letBody = (applyOvergenSubstToTermAnnotations_go subst cx (Core.letBody v0))})
Core.TermTypeApplication v0 -> Core.TermTypeApplication (Core.TypeApplicationTerm {
Core.typeApplicationTermBody = (applyOvergenSubstToTermAnnotations_go subst cx (Core.typeApplicationTermBody v0)),
Core.typeApplicationTermType = (substituteTypeVarsWithTypes subst (Core.typeApplicationTermType v0))})
Core.TermTypeLambda v0 -> Core.TermTypeLambda (Core.TypeLambda {
Core.typeLambdaParameter = (Core.typeLambdaParameter v0),
Core.typeLambdaBody = (applyOvergenSubstToTermAnnotations_go subst cx (Core.typeLambdaBody v0))})
_ -> term
applySubstFull :: M.Map Core.Name Core.Type -> Core.Type -> Core.Type
applySubstFull s t =
case (Strip.deannotateType t) of
Core.TypeVariable v0 -> Maps.findWithDefault t v0 s
Core.TypeFunction v0 -> Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = (applySubstFull s (Core.functionTypeDomain v0)),
Core.functionTypeCodomain = (applySubstFull s (Core.functionTypeCodomain v0))})
Core.TypeApplication v0 -> Core.TypeApplication (Core.ApplicationType {
Core.applicationTypeFunction = (applySubstFull s (Core.applicationTypeFunction v0)),
Core.applicationTypeArgument = (applySubstFull s (Core.applicationTypeArgument v0))})
Core.TypeList v0 -> Core.TypeList (applySubstFull s v0)
Core.TypeSet v0 -> Core.TypeSet (applySubstFull s v0)
Core.TypeOptional v0 -> Core.TypeOptional (applySubstFull s v0)
Core.TypeEffect v0 -> Core.TypeEffect (applySubstFull s v0)
Core.TypeMap v0 -> Core.TypeMap (Core.MapType {
Core.mapTypeKeys = (applySubstFull s (Core.mapTypeKeys v0)),
Core.mapTypeValues = (applySubstFull s (Core.mapTypeValues v0))})
Core.TypePair v0 -> Core.TypePair (Core.PairType {
Core.pairTypeFirst = (applySubstFull s (Core.pairTypeFirst v0)),
Core.pairTypeSecond = (applySubstFull s (Core.pairTypeSecond v0))})
Core.TypeEither v0 -> Core.TypeEither (Core.EitherType {
Core.eitherTypeLeft = (applySubstFull s (Core.eitherTypeLeft v0)),
Core.eitherTypeRight = (applySubstFull s (Core.eitherTypeRight v0))})
Core.TypeForall v0 -> Core.TypeForall (Core.ForallType {
Core.forallTypeParameter = (Core.forallTypeParameter v0),
Core.forallTypeBody = (applySubstFull (Maps.delete (Core.forallTypeParameter v0) s) (Core.forallTypeBody v0))})
_ -> t
applySubstSimple :: M.Map Core.Name Core.Type -> Core.Type -> Core.Type
applySubstSimple subst t =
case (Strip.deannotateType t) of
Core.TypeVariable v0 -> Maps.findWithDefault t v0 subst
_ -> t
arraysCompareExpr :: String -> String -> Syntax.Expression
arraysCompareExpr otherVar fname =
let header =
Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantType (Utils.javaTypeName (Syntax.Identifier "java.util.Arrays"))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "compare")})
arg1 =
Utils.javaExpressionNameToJavaExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Syntax.Identifier (Utils.sanitizeJavaName fname))})
arg2 =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.javaIdentifier otherVar) (Utils.javaIdentifier fname))
in (Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = [
arg1,
arg2]}))
arraysEqualsClause :: String -> String -> Syntax.InclusiveOrExpression
arraysEqualsClause tmpName fname =
let thisArg =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Syntax.Identifier "this") (Utils.javaIdentifier fname))
otherArg =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.javaIdentifier tmpName) (Utils.javaIdentifier fname))
header =
Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantType (Utils.javaTypeName (Syntax.Identifier "java.util.Arrays"))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.equalsMethodName)})
in (Utils.javaPostfixExpressionToJavaInclusiveOrExpression (Utils.javaMethodInvocationToJavaPostfixExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = [
thisArg,
otherArg]})))
augmentVariantClass :: JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> Syntax.ClassDeclaration -> Syntax.ClassDeclaration
augmentVariantClass aliases tparams elName cd =
case cd of
Syntax.ClassDeclarationNormal v0 ->
let args = Lists.map (\tp -> Utils.typeParameterToTypeArgument tp) tparams
extendsPart = Utils.nameToJavaClassType aliases True args elName Nothing
newMods =
[
Syntax.ClassModifierPublic,
Syntax.ClassModifierStatic,
Syntax.ClassModifierFinal]
oldBody = Syntax.normalClassDeclarationBody v0
oldDecls = Syntax.unClassBody oldBody
acceptDecl = withCommentString "Dispatch to {@code visitor}." (Utils.toAcceptMethod False tparams)
newBody = Syntax.ClassBody (Lists.concat2 oldDecls [
acceptDecl])
in (Syntax.ClassDeclarationNormal (Syntax.NormalClassDeclaration {
Syntax.normalClassDeclarationModifiers = newMods,
Syntax.normalClassDeclarationIdentifier = (Syntax.normalClassDeclarationIdentifier v0),
Syntax.normalClassDeclarationParameters = tparams,
Syntax.normalClassDeclarationExtends = (Just extendsPart),
Syntax.normalClassDeclarationImplements = (Syntax.normalClassDeclarationImplements v0),
Syntax.normalClassDeclarationPermits = (Syntax.normalClassDeclarationPermits v0),
Syntax.normalClassDeclarationBody = newBody}))
_ -> cd
bindingIsFunctionType :: Core.Binding -> Bool
bindingIsFunctionType b =
Optionals.cases (Core.bindingTypeScheme b) (case (Strip.deannotateTerm (Core.bindingTerm b)) of
Core.TermLambda _ -> True
Core.TermProject _ -> True
Core.TermCases _ -> True
Core.TermUnwrap _ -> True
_ -> False) (\ts -> case (Strip.deannotateType (Core.typeSchemeBody ts)) of
Core.TypeFunction _ -> True
Core.TypeForall v0 -> case (Strip.deannotateType (Core.forallTypeBody v0)) of
Core.TypeFunction _ -> True
_ -> False
_ -> False)
bindingNameToFilePath :: Core.Name -> String
bindingNameToFilePath name =
let qn = Names.qualifyName name
ns_ = Util.qualifiedNameModuleName qn
local = Util.qualifiedNameLocal qn
sanitized = Formatting.sanitizeWithUnderscores Language.reservedWords local
unq =
Names.unqualifyName (Util.QualifiedName {
Util.qualifiedNameModuleName = ns_,
Util.qualifiedNameLocal = sanitized})
in (Names.nameToFilePath Util.CaseConventionCamel Util.CaseConventionPascal (File.FileExtension "java") unq)
bindingsToStatements :: JavaEnvironment.JavaEnvironment -> [Core.Binding] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error ([Syntax.BlockStatement], JavaEnvironment.JavaEnvironment)
bindingsToStatements env bindings cx g0 =
let aliases = JavaEnvironment.javaEnvironmentAliases env
g = JavaEnvironment.javaEnvironmentGraph env
flatBindings = dedupBindings (JavaEnvironment.aliasesInScopeJavaVars aliases) (flattenBindings bindings)
gExtended =
Scoping.extendGraphForLet (\g2 -> \b -> Logic.ifElse (Predicates.isComplexBinding g2 b) (Just (Core.TermLiteral (Core.LiteralBoolean True))) Nothing) g (Core.Let {
Core.letBindings = flatBindings,
Core.letBody = (Core.TermVariable (Core.Name "dummy"))})
bindingVars = Sets.fromList (Lists.map (\b -> Core.bindingName b) flatBindings)
allDeps =
Maps.fromList (Lists.map (\b ->
let key = Core.bindingName b
deps = Sets.intersection bindingVars (Variables.freeVariablesInTerm (Core.bindingTerm b))
in (key, deps)) flatBindings)
sorted =
Sorting.topologicalSortComponents (Lists.map (\entry ->
let key = Pairs.first entry
deps = Pairs.second entry
in (key, (Sets.toList deps))) (Maps.toList allDeps))
recursiveVars =
Sets.fromList (Lists.concat (Lists.map (\names -> Logic.ifElse (Equality.equal (Lists.length names) 1) (Optionals.cases (Lists.maybeHead names) [] (\singleName -> Optionals.cases (Maps.lookup singleName allDeps) [] (\deps -> Logic.ifElse (Sets.member singleName deps) [
singleName] []))) names) sorted))
thunkedVars =
Sets.fromList (Lists.concat (Lists.map (\b ->
let bname = Core.bindingName b
in (Logic.ifElse (Logic.and (Logic.not (Sets.member bname recursiveVars)) (Logic.and (Logic.and (Predicates.isComplexBinding g b) (Logic.not (Predicates.isTrivialTerm (Core.bindingTerm b)))) (Logic.not (bindingIsFunctionType b)))) [
bname] [])) flatBindings))
aliasesExtended =
JavaEnvironment.Aliases {
JavaEnvironment.aliasesCurrentNamespace = (JavaEnvironment.aliasesCurrentNamespace aliases),
JavaEnvironment.aliasesPackages = (JavaEnvironment.aliasesPackages aliases),
JavaEnvironment.aliasesBranchVars = (JavaEnvironment.aliasesBranchVars aliases),
JavaEnvironment.aliasesRecursiveVars = (Sets.union (JavaEnvironment.aliasesRecursiveVars aliases) recursiveVars),
JavaEnvironment.aliasesInScopeTypeParams = (JavaEnvironment.aliasesInScopeTypeParams aliases),
JavaEnvironment.aliasesPolymorphicLocals = (JavaEnvironment.aliasesPolymorphicLocals aliases),
JavaEnvironment.aliasesInScopeJavaVars = (Sets.union (JavaEnvironment.aliasesInScopeJavaVars aliases) bindingVars),
JavaEnvironment.aliasesVarRenames = (JavaEnvironment.aliasesVarRenames aliases),
JavaEnvironment.aliasesLambdaVars = (JavaEnvironment.aliasesLambdaVars aliases),
JavaEnvironment.aliasesTypeVarSubst = (JavaEnvironment.aliasesTypeVarSubst aliases),
JavaEnvironment.aliasesTrustedTypeVars = (JavaEnvironment.aliasesTrustedTypeVars aliases),
JavaEnvironment.aliasesMethodCodomain = (JavaEnvironment.aliasesMethodCodomain aliases),
JavaEnvironment.aliasesThunkedVars = (Sets.union (JavaEnvironment.aliasesThunkedVars aliases) thunkedVars)}
envExtended =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = aliasesExtended,
JavaEnvironment.javaEnvironmentGraph = gExtended}
in (Logic.ifElse (Lists.null bindings) (Right ([], envExtended)) (Eithers.bind (Eithers.mapList (\names -> Eithers.bind (Eithers.mapList (\n -> toDeclInit aliasesExtended gExtended recursiveVars flatBindings n cx g) names) (\inits -> Eithers.bind (Eithers.mapList (\n -> toDeclStatement envExtended aliasesExtended gExtended recursiveVars thunkedVars flatBindings n cx g) names) (\decls -> Right (Lists.concat2 (Optionals.cat inits) decls)))) sorted) (\groups -> Right (Lists.concat groups, envExtended))))
boundTypeVariables :: Core.Type -> [Core.Name]
boundTypeVariables typ =
case typ of
Core.TypeAnnotated v0 -> boundTypeVariables (Core.annotatedTypeBody v0)
Core.TypeForall v0 -> Lists.cons (Core.forallTypeParameter v0) (boundTypeVariables (Core.forallTypeBody v0))
_ -> []
buildArgSubst :: S.Set Core.Name -> [Core.Type] -> [t0] -> M.Map Core.Name t0
buildArgSubst schemeVarSet schemeDoms argTypes =
Maps.fromList (Lists.bind (Lists.zip schemeDoms argTypes) (\p ->
let sdom = Pairs.first p
argType = Pairs.second p
in case (Strip.deannotateType sdom) of
Core.TypeVariable v0 -> Logic.ifElse (Sets.member v0 schemeVarSet) [
(v0, argType)] []
_ -> []))
buildCurriedLambda :: [Core.Name] -> Syntax.Expression -> Syntax.Expression
buildCurriedLambda params inner = Lists.foldl (\acc -> \p -> Utils.javaLambda p acc) inner (Lists.reverse params)
buildSubstFromAnnotations :: S.Set Core.Name -> Core.Term -> t0 -> Graph.Graph -> Either t1 (M.Map Core.Name Core.Name)
buildSubstFromAnnotations schemeVarSet term cx g = Right (buildSubstFromAnnotations_go schemeVarSet g term)
buildSubstFromAnnotations_go :: S.Set Core.Name -> Graph.Graph -> Core.Term -> M.Map Core.Name Core.Name
buildSubstFromAnnotations_go schemeVarSet g term =
case term of
Core.TermAnnotated v0 ->
let body = Core.annotatedTermBody v0
anns = Annotations.getAnnotationMap (Core.annotatedTermAnnotation v0)
bodySubst = buildSubstFromAnnotations_go schemeVarSet g body
annSubst =
Optionals.cases (Maps.lookup Constants.keyType anns) Maps.empty (\typeTerm -> Eithers.either (\_ -> Maps.empty) (\annType -> case (Strip.deannotateTerm body) of
Core.TermLambda v1 -> Optionals.cases (Core.lambdaDomain v1) Maps.empty (\dom -> case (Strip.deannotateType annType) of
Core.TypeFunction v2 -> buildTypeVarSubst schemeVarSet (Core.functionTypeDomain v2) dom
_ -> Maps.empty)
_ -> Maps.empty) (DecodeCore.type_ g typeTerm))
in (Maps.union annSubst bodySubst)
Core.TermApplication v0 -> Maps.union (buildSubstFromAnnotations_go schemeVarSet g (Core.applicationFunction v0)) (buildSubstFromAnnotations_go schemeVarSet g (Core.applicationArgument v0))
Core.TermLambda v0 -> buildSubstFromAnnotations_go schemeVarSet g (Core.lambdaBody v0)
Core.TermCases v0 ->
let defSubst = Optionals.cases (Core.caseStatementDefault v0) Maps.empty (\d -> buildSubstFromAnnotations_go schemeVarSet g d)
caseSubsts =
Lists.foldl (\acc -> \fld -> Maps.union acc (buildSubstFromAnnotations_go schemeVarSet g (Core.caseAlternativeHandler fld))) Maps.empty (Core.caseStatementCases v0)
in (Maps.union defSubst caseSubsts)
Core.TermLet v0 ->
let bindingSubst =
Lists.foldl (\acc -> \b -> Maps.union acc (buildSubstFromAnnotations_go schemeVarSet g (Core.bindingTerm b))) Maps.empty (Core.letBindings v0)
in (Maps.union bindingSubst (buildSubstFromAnnotations_go schemeVarSet g (Core.letBody v0)))
Core.TermList v0 -> Lists.foldl (\acc -> \t -> Maps.union acc (buildSubstFromAnnotations_go schemeVarSet g t)) Maps.empty v0
Core.TermOptional v0 -> Optionals.cases v0 Maps.empty (\t -> buildSubstFromAnnotations_go schemeVarSet g t)
Core.TermPair v0 -> Maps.union (buildSubstFromAnnotations_go schemeVarSet g (Pairs.first v0)) (buildSubstFromAnnotations_go schemeVarSet g (Pairs.second v0))
Core.TermRecord v0 -> Lists.foldl (\acc -> \fld -> Maps.union acc (buildSubstFromAnnotations_go schemeVarSet g (Core.fieldTerm fld))) Maps.empty (Core.recordFields v0)
Core.TermSet v0 -> Lists.foldl (\acc -> \t -> Maps.union acc (buildSubstFromAnnotations_go schemeVarSet g t)) Maps.empty (Sets.toList v0)
Core.TermTypeApplication v0 -> buildSubstFromAnnotations_go schemeVarSet g (Core.typeApplicationTermBody v0)
Core.TermTypeLambda v0 -> buildSubstFromAnnotations_go schemeVarSet g (Core.typeLambdaBody v0)
Core.TermEither v0 -> Eithers.either (\t -> buildSubstFromAnnotations_go schemeVarSet g t) (\t -> buildSubstFromAnnotations_go schemeVarSet g t) v0
_ -> Maps.empty
buildTypeSubst :: S.Set Core.Name -> Core.Type -> Core.Type -> M.Map Core.Name Core.Type
buildTypeSubst schemeVarSet schemeType actualType =
buildTypeSubst_go schemeVarSet (Strip.deannotateType schemeType) (Strip.deannotateType actualType)
buildTypeSubst_go :: S.Set Core.Name -> Core.Type -> Core.Type -> M.Map Core.Name Core.Type
buildTypeSubst_go svs st at =
let goSub = \a -> \b -> buildTypeSubst_go svs (Strip.deannotateType a) (Strip.deannotateType b)
in case st of
Core.TypeVariable v0 -> Logic.ifElse (Sets.member v0 svs) (Maps.singleton v0 at) Maps.empty
Core.TypeFunction v0 -> case at of
Core.TypeFunction v1 -> Maps.union (goSub (Core.functionTypeDomain v0) (Core.functionTypeDomain v1)) (goSub (Core.functionTypeCodomain v0) (Core.functionTypeCodomain v1))
_ -> Maps.empty
Core.TypeApplication v0 -> case at of
Core.TypeApplication v1 -> Maps.union (goSub (Core.applicationTypeFunction v0) (Core.applicationTypeFunction v1)) (goSub (Core.applicationTypeArgument v0) (Core.applicationTypeArgument v1))
_ -> Maps.empty
Core.TypeList v0 -> case at of
Core.TypeList v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeSet v0 -> case at of
Core.TypeSet v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeOptional v0 -> case at of
Core.TypeOptional v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeMap v0 -> case at of
Core.TypeMap v1 -> Maps.union (goSub (Core.mapTypeKeys v0) (Core.mapTypeKeys v1)) (goSub (Core.mapTypeValues v0) (Core.mapTypeValues v1))
_ -> Maps.empty
Core.TypePair v0 -> case at of
Core.TypePair v1 -> Maps.union (goSub (Core.pairTypeFirst v0) (Core.pairTypeFirst v1)) (goSub (Core.pairTypeSecond v0) (Core.pairTypeSecond v1))
_ -> Maps.empty
Core.TypeEither v0 -> case at of
Core.TypeEither v1 -> Maps.union (goSub (Core.eitherTypeLeft v0) (Core.eitherTypeLeft v1)) (goSub (Core.eitherTypeRight v0) (Core.eitherTypeRight v1))
_ -> Maps.empty
Core.TypeForall v0 -> case at of
Core.TypeForall v1 -> goSub (Core.forallTypeBody v0) (Core.forallTypeBody v1)
_ -> goSub (Core.forallTypeBody v0) at
_ -> Maps.empty
buildTypeVarSubst :: S.Set Core.Name -> Core.Type -> Core.Type -> M.Map Core.Name Core.Name
buildTypeVarSubst schemeVarSet freshTyp canonTyp =
buildTypeVarSubst_go schemeVarSet (Strip.deannotateType freshTyp) (Strip.deannotateType canonTyp)
buildTypeVarSubst_go :: S.Set Core.Name -> Core.Type -> Core.Type -> M.Map Core.Name Core.Name
buildTypeVarSubst_go svs ft ct =
let goSub = \a -> \b -> buildTypeVarSubst_go svs (Strip.deannotateType a) (Strip.deannotateType b)
in case ft of
Core.TypeVariable v0 -> case ct of
Core.TypeVariable v1 -> Logic.ifElse (Logic.and (Logic.not (Equality.equal v0 v1)) (Sets.member v1 svs)) (Maps.singleton v0 v1) Maps.empty
_ -> Maps.empty
Core.TypeFunction v0 -> case ct of
Core.TypeFunction v1 -> Maps.union (goSub (Core.functionTypeDomain v0) (Core.functionTypeDomain v1)) (goSub (Core.functionTypeCodomain v0) (Core.functionTypeCodomain v1))
_ -> Maps.empty
Core.TypeApplication v0 -> case ct of
Core.TypeApplication v1 -> Maps.union (goSub (Core.applicationTypeFunction v0) (Core.applicationTypeFunction v1)) (goSub (Core.applicationTypeArgument v0) (Core.applicationTypeArgument v1))
_ -> Maps.empty
Core.TypeList v0 -> case ct of
Core.TypeList v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeSet v0 -> case ct of
Core.TypeSet v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeOptional v0 -> case ct of
Core.TypeOptional v1 -> goSub v0 v1
_ -> Maps.empty
Core.TypeMap v0 -> case ct of
Core.TypeMap v1 -> Maps.union (goSub (Core.mapTypeKeys v0) (Core.mapTypeKeys v1)) (goSub (Core.mapTypeValues v0) (Core.mapTypeValues v1))
_ -> Maps.empty
Core.TypePair v0 -> case ct of
Core.TypePair v1 -> Maps.union (goSub (Core.pairTypeFirst v0) (Core.pairTypeFirst v1)) (goSub (Core.pairTypeSecond v0) (Core.pairTypeSecond v1))
_ -> Maps.empty
Core.TypeEither v0 -> case ct of
Core.TypeEither v1 -> Maps.union (goSub (Core.eitherTypeLeft v0) (Core.eitherTypeLeft v1)) (goSub (Core.eitherTypeRight v0) (Core.eitherTypeRight v1))
_ -> Maps.empty
Core.TypeForall v0 -> case ct of
Core.TypeForall v1 -> goSub (Core.forallTypeBody v0) (Core.forallTypeBody v1)
_ -> buildTypeVarSubst_go svs (Strip.deannotateType (Core.forallTypeBody v0)) ct
_ -> case ct of
Core.TypeForall v0 -> buildTypeVarSubst_go svs ft (Strip.deannotateType (Core.forallTypeBody v0))
_ -> Maps.empty
builderSetterName :: Core.Name -> String
builderSetterName fname =
let base = Utils.sanitizeJavaName (Core.unName fname)
in (Logic.ifElse (Logic.or (Equality.equal base "build") (Equality.equal base "builder")) (Strings.cat2 base "_") base)
classModsPublic :: [Syntax.ClassModifier]
classModsPublic = [
Syntax.ClassModifierPublic]
classifyDataReference :: Core.Name -> t0 -> Graph.Graph -> Either Errors.Error JavaEnvironment.JavaSymbolClass
classifyDataReference name cx g =
Eithers.bind (Right (Lexical.lookupBinding g name)) (\mel -> Optionals.cases mel (Right JavaEnvironment.JavaSymbolClassLocalVariable) (\el -> Optionals.cases (Core.bindingTypeScheme el) (Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "no type scheme for element " (Core.unName (Core.bindingName el)))))) (\ts -> Right (classifyDataTerm ts (Core.bindingTerm el)))))
classifyDataTerm :: Core.TypeScheme -> Core.Term -> JavaEnvironment.JavaSymbolClass
classifyDataTerm ts term =
Logic.ifElse (Dependencies.isLambda term) (
let n = classifyDataTerm_countLambdaParams term
in (Logic.ifElse (Equality.gt n 1) (JavaEnvironment.JavaSymbolClassHoistedLambda n) JavaEnvironment.JavaSymbolClassUnaryFunction)) (
let hasTypeParams = Logic.not (Lists.null (Core.typeSchemeVariables ts))
in (Logic.ifElse hasTypeParams (
let n2 = classifyDataTerm_countLambdaParams (classifyDataTerm_stripTypeLambdas term)
in (Logic.ifElse (Equality.gt n2 0) (JavaEnvironment.JavaSymbolClassHoistedLambda n2) JavaEnvironment.JavaSymbolClassNullaryFunction)) JavaEnvironment.JavaSymbolClassNullaryFunction))
classifyDataTerm_countLambdaParams :: Core.Term -> Int
classifyDataTerm_countLambdaParams t =
case (Strip.deannotateTerm t) of
Core.TermLambda v0 -> Math.add 1 (classifyDataTerm_countLambdaParams (Core.lambdaBody v0))
Core.TermLet v0 -> classifyDataTerm_countLambdaParams (Core.letBody v0)
_ -> 0
classifyDataTerm_stripTypeLambdas :: Core.Term -> Core.Term
classifyDataTerm_stripTypeLambdas t =
case (Strip.deannotateTerm t) of
Core.TermTypeLambda v0 -> classifyDataTerm_stripTypeLambdas (Core.typeLambdaBody v0)
_ -> t
cmpDeclStatement :: t0 -> Syntax.BlockStatement
cmpDeclStatement aliases =
Utils.variableDeclarationStatement aliases Utils.javaIntType (Utils.javaIdentifier "cmp") (Utils.javaIntExpression 0)
cmpNotZeroExpr :: Syntax.Expression
cmpNotZeroExpr =
Utils.javaEqualityExpressionToJavaExpression (Syntax.EqualityExpressionNotEqual (Syntax.EqualityExpression_Binary {
Syntax.equalityExpression_BinaryLhs = lhs,
Syntax.equalityExpression_BinaryRhs = rhs}))
where
lhs =
Utils.javaRelationalExpressionToJavaEqualityExpression (Utils.javaPostfixExpressionToJavaRelationalExpression (Syntax.PostfixExpressionName (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Utils.javaIdentifier "cmp")})))
rhs =
Utils.javaPostfixExpressionToJavaRelationalExpression (Syntax.PostfixExpressionPrimary (Utils.javaLiteralToJavaPrimary (Utils.javaInt 0)))
collectForallParams :: Core.Type -> [Core.Name]
collectForallParams t =
case (Strip.deannotateType t) of
Core.TypeForall v0 -> Lists.cons (Core.forallTypeParameter v0) (collectForallParams (Core.forallTypeBody v0))
_ -> []
collectLambdaDomains :: Core.Term -> ([Core.Type], Core.Term)
collectLambdaDomains t =
case (Strip.deannotateTerm t) of
Core.TermLambda v0 -> Optionals.cases (Core.lambdaDomain v0) ([], t) (\dom ->
let rest = collectLambdaDomains (Core.lambdaBody v0)
in (Lists.cons dom (Pairs.first rest), (Pairs.second rest)))
_ -> ([], t)
collectTypeApps :: Core.Term -> [Core.Type] -> (Core.Term, [Core.Type])
collectTypeApps t acc =
case (Strip.deannotateTerm t) of
Core.TermTypeApplication v0 -> collectTypeApps (Core.typeApplicationTermBody v0) (Lists.cons (Core.typeApplicationTermType v0) acc)
_ -> (Strip.deannotateTerm t, acc)
collectTypeApps0 :: Core.Term -> [Core.Type] -> (Core.Term, [Core.Type])
collectTypeApps0 t acc =
case (Strip.deannotateTerm t) of
Core.TermTypeApplication v0 -> collectTypeApps0 (Core.typeApplicationTermBody v0) (Lists.cons (Core.typeApplicationTermType v0) acc)
_ -> (t, acc)
collectTypeVars :: Core.Type -> S.Set Core.Name
collectTypeVars typ = collectTypeVars_go (Strip.deannotateType typ)
collectTypeVars_go :: Core.Type -> S.Set Core.Name
collectTypeVars_go t =
case t of
Core.TypeVariable v0 -> Sets.singleton v0
Core.TypeFunction v0 -> Sets.union (collectTypeVars_go (Strip.deannotateType (Core.functionTypeDomain v0))) (collectTypeVars_go (Strip.deannotateType (Core.functionTypeCodomain v0)))
Core.TypeApplication v0 -> Sets.union (collectTypeVars_go (Strip.deannotateType (Core.applicationTypeFunction v0))) (collectTypeVars_go (Strip.deannotateType (Core.applicationTypeArgument v0)))
Core.TypeList v0 -> collectTypeVars_go (Strip.deannotateType v0)
Core.TypeSet v0 -> collectTypeVars_go (Strip.deannotateType v0)
Core.TypeOptional v0 -> collectTypeVars_go (Strip.deannotateType v0)
Core.TypeEffect v0 -> collectTypeVars_go (Strip.deannotateType v0)
Core.TypeMap v0 -> Sets.union (collectTypeVars_go (Strip.deannotateType (Core.mapTypeKeys v0))) (collectTypeVars_go (Strip.deannotateType (Core.mapTypeValues v0)))
Core.TypePair v0 -> Sets.union (collectTypeVars_go (Strip.deannotateType (Core.pairTypeFirst v0))) (collectTypeVars_go (Strip.deannotateType (Core.pairTypeSecond v0)))
Core.TypeEither v0 -> Sets.union (collectTypeVars_go (Strip.deannotateType (Core.eitherTypeLeft v0))) (collectTypeVars_go (Strip.deannotateType (Core.eitherTypeRight v0)))
Core.TypeForall v0 -> collectTypeVars_go (Strip.deannotateType (Core.forallTypeBody v0))
_ -> Sets.empty
collectionTypeArgs :: String -> Int -> JavaEnvironment.Aliases -> [M.Map Core.Name Core.Term] -> [Syntax.Type] -> t0 -> Graph.Graph -> Either Errors.Error [Syntax.TypeArgument]
collectionTypeArgs label n aliases anns tyapps cx g =
Logic.ifElse (Logic.not (Lists.null tyapps)) (takeTypeArgs label n tyapps cx g) (
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mtyp -> Eithers.bind (Optionals.cases mtyp (Right []) (\typ -> case (Strip.deannotateType typ) of
Core.TypeList v0 -> Right [
v0]
Core.TypeSet v0 -> Right [
v0]
Core.TypeOptional v0 -> Right [
v0]
Core.TypeMap v0 -> Right [
Core.mapTypeKeys v0,
(Core.mapTypeValues v0)]
_ -> Right [])) (\compTypes -> Eithers.mapList (\ct -> Eithers.bind (encodeType aliases Sets.empty ct cx g) (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt)))) compTypes))))
comparableCompareExpr :: String -> String -> Syntax.Expression
comparableCompareExpr otherVar fname =
let thisField = Utils.javaIdentifierToJavaExpression (Syntax.Identifier (Utils.sanitizeJavaName fname))
otherField =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.javaIdentifier otherVar) (Utils.javaIdentifier fname))
in (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.Comparing") (Syntax.Identifier "compare") [
thisField,
otherField]))
compareAndReturnStmts :: String -> Core.FieldType -> [Syntax.BlockStatement]
compareAndReturnStmts otherVar f =
[
Syntax.BlockStatementStatement (Utils.javaAssignmentStatement (Syntax.LeftHandSideExpressionName (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Utils.javaIdentifier "cmp")})) (compareFieldExpr otherVar f)),
(Syntax.BlockStatementStatement (Syntax.StatementIfThen (Syntax.IfThenStatement {
Syntax.ifThenStatementExpression = cmpNotZeroExpr,
Syntax.ifThenStatementStatement = (Utils.javaReturnStatement (Just (Utils.javaExpressionNameToJavaExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Utils.javaIdentifier "cmp")}))))})))]
compareFieldExpr :: String -> Core.FieldType -> Syntax.Expression
compareFieldExpr otherVar ft =
let fname = Core.unName (Core.fieldTypeName ft)
ftype = Core.fieldTypeType ft
in (Logic.ifElse (isBinaryType ftype) (arraysCompareExpr otherVar fname) (Logic.ifElse (isNonComparableType ftype) (hashCodeCompareExpr otherVar fname) (comparableCompareExpr otherVar fname)))
compareToBody :: t0 -> String -> [Core.FieldType] -> [Syntax.BlockStatement]
compareToBody aliases otherVar fields =
let zeroStmts = [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaIntExpression 0)))]
in (Optionals.fromOptional zeroStmts (Optionals.map (\p ->
let firstField = Pairs.first p
restFields = Pairs.second p
in (Logic.ifElse (Lists.null restFields) [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (compareFieldExpr otherVar firstField)))] (Lists.concat2 [
cmpDeclStatement aliases] (Lists.concat2 (Lists.concat (Lists.map (\f -> compareAndReturnStmts otherVar f) (Lists.cons firstField (Optionals.fromOptional [] (Lists.maybeInit restFields))))) [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (compareFieldExpr otherVar (Optionals.fromOptional firstField (Lists.maybeLast restFields)))))])))) (Lists.uncons fields)))
compareToZeroClause :: String -> String -> Syntax.InclusiveOrExpression
compareToZeroClause tmpName fname =
let compareToArg =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.javaIdentifier tmpName) (Utils.javaIdentifier fname))
compareToVar =
Syntax.MethodInvocation_VariantExpression (Utils.fieldExpression (Syntax.Identifier "this") (Utils.javaIdentifier fname))
compareToHeader =
Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = compareToVar,
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.compareToMethodName)})
lhs =
Utils.javaRelationalExpressionToJavaEqualityExpression (Utils.javaPostfixExpressionToJavaRelationalExpression (Utils.javaMethodInvocationToJavaPostfixExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = compareToHeader,
Syntax.methodInvocationArguments = [
compareToArg]})))
rhs =
Utils.javaPostfixExpressionToJavaRelationalExpression (Syntax.PostfixExpressionPrimary (Utils.javaLiteralToJavaPrimary (Utils.javaInt 0)))
in (Utils.javaEqualityExpressionToJavaInclusiveOrExpression (Syntax.EqualityExpressionEqual (Syntax.EqualityExpression_Binary {
Syntax.equalityExpression_BinaryLhs = lhs,
Syntax.equalityExpression_BinaryRhs = rhs})))
constantDecl :: String -> String -> JavaEnvironment.Aliases -> Core.Name -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
constantDecl comment javaName aliases name cx g =
let mods =
[
Syntax.FieldModifierPublic,
Syntax.FieldModifierStatic,
Syntax.FieldModifierFinal]
nameName = Utils.nameToJavaName aliases (Core.Name "hydra.core.Name")
env =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = aliases,
JavaEnvironment.javaEnvironmentGraph = g}
in (Eithers.bind (encodeType aliases Sets.empty (Core.TypeVariable (Core.Name "hydra.core.Name")) cx g) (\jt -> Eithers.bind (encodeTerm env (Core.TermLiteral (Core.LiteralString (Core.unName name))) cx g) (\arg ->
let init =
Syntax.VariableInitializerExpression (Utils.javaConstructorCall (Utils.javaConstructorName nameName Nothing) [
arg] Nothing)
var = Utils.javaVariableDeclarator (Syntax.Identifier javaName) (Just init)
in (Right (withCommentString comment (Utils.javaMemberField mods jt var))))))
constantDeclForFieldType :: Core.Name -> JavaEnvironment.Aliases -> Core.FieldType -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
constantDeclForFieldType parentName aliases ftyp cx g =
let name = Core.fieldTypeName ftyp
javaName =
Formatting.nonAlnumToUnderscores (Formatting.convertCase Util.CaseConventionCamel Util.CaseConventionUpperSnake (Core.unName name))
comment =
Strings.cat [
"Name of the {@code ",
(Core.unName parentName),
".",
(Core.unName name),
"} field."]
in (constantDecl comment javaName aliases name cx g)
constantDeclForTypeName :: JavaEnvironment.Aliases -> Core.Name -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
constantDeclForTypeName aliases name cx g =
let comment =
Strings.cat [
"Name of the {@code ",
(Core.unName name),
"} type."]
in (constantDecl comment "TYPE_" aliases name cx g)
constructElementsInterface :: Packaging.Module -> [Syntax.InterfaceMemberDeclarationWithComments] -> (Core.Name, Syntax.CompilationUnit)
constructElementsInterface mod members =
let ns = Packaging.moduleName mod
parentNs = namespaceParent ns
pkg = Optionals.cases parentNs (Utils.javaPackageDeclaration ns) (\pns -> Utils.javaPackageDeclaration pns)
mods = [
Syntax.InterfaceModifierPublic]
className = elementsClassName ns
elName = elementsQualifiedName ns
body = Syntax.InterfaceBody members
itf =
Syntax.TopLevelClassOrInterfaceDeclarationInterface (Syntax.InterfaceDeclarationNormalInterface (Syntax.NormalInterfaceDeclaration {
Syntax.normalInterfaceDeclarationModifiers = mods,
Syntax.normalInterfaceDeclarationIdentifier = (Utils.javaTypeIdentifier className),
Syntax.normalInterfaceDeclarationParameters = [],
Syntax.normalInterfaceDeclarationExtends = [],
Syntax.normalInterfaceDeclarationPermits = [],
Syntax.normalInterfaceDeclarationBody = body}))
decl =
Syntax.TopLevelClassOrInterfaceDeclarationWithComments {
Syntax.topLevelClassOrInterfaceDeclarationWithCommentsValue = itf,
Syntax.topLevelClassOrInterfaceDeclarationWithCommentsComments = (Optionals.bind (Packaging.moduleMetadata mod) (\em -> Packaging.entityMetadataDescription em))}
in (
elName,
(Syntax.CompilationUnitOrdinary (Syntax.OrdinaryCompilationUnit {
Syntax.ordinaryCompilationUnitPackage = (Just pkg),
Syntax.ordinaryCompilationUnitImports = [],
Syntax.ordinaryCompilationUnitTypes = [
decl]})))
correctCastType :: Core.Term -> [Core.Type] -> Core.Type -> t0 -> t1 -> Either t2 Core.Type
correctCastType innerBody typeArgs fallback cx g =
case (Strip.deannotateTerm innerBody) of
Core.TermPair _ -> Logic.ifElse (Equality.equal (Lists.length typeArgs) 2) (Right (Core.TypePair (Core.PairType {
Core.pairTypeFirst = (Optionals.fromOptional fallback (Lists.maybeAt 0 typeArgs)),
Core.pairTypeSecond = (Optionals.fromOptional fallback (Lists.maybeAt 1 typeArgs))}))) (Right fallback)
_ -> Right fallback
correctTypeApps :: t0 -> Core.Name -> [Core.Term] -> [Core.Type] -> t1 -> Graph.Graph -> Either Errors.Error [Core.Type]
correctTypeApps gr name args fallbackTypeApps cx g =
Eithers.bind (Right (Lexical.lookupBinding g name)) (\mel -> Optionals.cases mel (Right fallbackTypeApps) (\el -> Optionals.cases (Core.bindingTypeScheme el) (Right fallbackTypeApps) (\ts ->
let schemeType = Core.typeSchemeBody ts
allSchemeVars = Lists.filter (\v -> isSimpleName v) (Core.typeSchemeVariables ts)
schemeTypeVars = collectTypeVars schemeType
usedFlags = Lists.map (\v -> Sets.member v schemeTypeVars) allSchemeVars
usedSchemeVars = filterByFlags allSchemeVars usedFlags
nParams = countFunctionParams schemeType
peeled = peelDomainTypes nParams schemeType
calleeDoms = Pairs.first peeled
calleeCod = Pairs.second peeled
overgenSubst = detectAccumulatorUnification calleeDoms calleeCod usedSchemeVars
keepFlags =
Lists.map (\v -> Logic.and (Sets.member v schemeTypeVars) (Logic.not (Maps.member v overgenSubst))) allSchemeVars
schemeVars = filterByFlags allSchemeVars keepFlags
filteredFallback0 =
Logic.ifElse (Equality.equal (Lists.length allSchemeVars) (Lists.length fallbackTypeApps)) (filterByFlags fallbackTypeApps keepFlags) fallbackTypeApps
filteredFallback =
Logic.ifElse (Maps.null overgenSubst) filteredFallback0 (Lists.map (\t -> substituteTypeVarsWithTypes overgenSubst t) filteredFallback0)
in (Logic.ifElse (Logic.or (Lists.null schemeVars) (Logic.not (Equality.equal (Lists.length schemeVars) (Lists.length filteredFallback)))) (Right filteredFallback) (correctTypeAppsWithArgs schemeVars filteredFallback schemeType args cx g)))))
correctTypeAppsWithArgs :: [Core.Name] -> [Core.Type] -> Core.Type -> [Core.Term] -> t0 -> Graph.Graph -> Either Errors.Error [Core.Type]
correctTypeAppsWithArgs schemeVars fallbackTypeApps schemeType args cx g =
let schemeVarSet = Sets.fromList schemeVars
irSubst = Maps.fromList (Lists.zip schemeVars fallbackTypeApps)
peeled = peelDomainTypes (Lists.length args) schemeType
schemeDoms = Pairs.first peeled
in (Eithers.bind (Eithers.mapList (\arg -> Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g (Annotations.termAnnotationInternal arg))) args) (\mArgTypes -> Logic.ifElse (Logic.not (Lists.null (Lists.filter (\m -> Optionals.isNone m) mArgTypes))) (Right fallbackTypeApps) (
let argTypes = Lists.bind mArgTypes (\m -> Optionals.cases m [] (\x -> Lists.pure x))
irDoms = Lists.map (\d -> applySubstSimple irSubst d) schemeDoms
domsMatch =
Lists.null (Lists.filter (\p -> Logic.not (typesMatch (Strip.deannotateType (Pairs.first p)) (Strip.deannotateType (Pairs.second p)))) (Lists.zip irDoms argTypes))
in (Logic.ifElse domsMatch (Right fallbackTypeApps) (Right (resolveTypeApps schemeVars fallbackTypeApps (buildArgSubst schemeVarSet schemeDoms argTypes)))))))
countFunctionParams :: Core.Type -> Int
countFunctionParams t =
case (Strip.deannotateType t) of
Core.TypeFunction v0 -> Math.add 1 (countFunctionParams (Core.functionTypeCodomain v0))
_ -> 0
declarationForRecordType :: Bool -> Bool -> JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> [Core.FieldType] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassDeclaration
declarationForRecordType isInner isSer aliases tparams elName fields cx g =
declarationForRecordType_ isInner isSer aliases tparams elName Nothing fields cx g
declarationForRecordType_ :: Bool -> Bool -> JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> Maybe Core.Name -> [Core.FieldType] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassDeclaration
declarationForRecordType_ isInner isSer aliases tparams elName parentName fields cx g =
Eithers.bind (Eithers.mapList (\f -> recordMemberVar aliases f cx g) fields) (\memberVars -> Eithers.bind (Eithers.mapList (\p -> addComment (Pairs.first p) (Pairs.second p) cx g) (Lists.zip memberVars fields)) (\memberVars_ ->
let elNameStr = Syntax.unIdentifier (Utils.nameToJavaName aliases elName)
linkTargetStr =
Optionals.cases parentName elNameStr (\pn -> Strings.cat2 (Strings.cat2 (Syntax.unIdentifier (Utils.nameToJavaName aliases pn)) ".") (Utils.sanitizeJavaName (Util.qualifiedNameLocal (Names.qualifyName elName))))
in (Eithers.bind (Logic.ifElse (Equality.gt (Lists.length fields) 1) (Eithers.mapList (\f -> Eithers.bind (recordWithMethod aliases elName fields f cx g) (\decl ->
let fname = Core.unName (Core.fieldTypeName f)
comment =
Strings.cat [
"Returns a copy of this {@link ",
linkTargetStr,
"} with {@code ",
fname,
"} replaced."]
in (Right (withCommentString comment decl)))) fields) (Right [])) (\withMethods -> Eithers.bind (recordConstructor aliases elName fields cx g) (\cons -> Eithers.bind (Eithers.mapList (\f ->
let fname = Utils.sanitizeJavaName (Core.unName (Core.fieldTypeName f))
in (Eithers.bind (Annotations.commentsFromFieldType cx g f) (\mDoc -> Right (Optionals.cases mDoc "" (\d -> Strings.cat [
"@param ",
fname,
" ",
d]))))) fields) (\paramLines ->
let nonEmptyParamLines = Lists.filter (\l -> Logic.not (Equality.equal l "")) paramLines
consBaseComment =
Strings.cat [
"Constructs an immutable {@link ",
linkTargetStr,
"}."]
consComment =
Logic.ifElse (Lists.null nonEmptyParamLines) consBaseComment (Strings.cat [
consBaseComment,
"\n\n",
(Strings.intercalate "\n" nonEmptyParamLines)])
consWithComment = withCommentString consComment cons
in (Eithers.bind (Logic.ifElse isInner (Right []) (Eithers.bind (constantDeclForTypeName aliases elName cx g) (\d -> Eithers.bind (Eithers.mapList (\f -> constantDeclForFieldType elName aliases f cx g) fields) (\dfields -> Right (Lists.cons d dfields))))) (\tn -> Eithers.bind (Logic.ifElse isInner (Right []) (recordBuilderClass aliases tparams elName fields cx g)) (\builderDecls ->
let comparableMethods =
Optionals.cases parentName (Logic.ifElse (Logic.and (Logic.not isInner) isSer) [
recordCompareToMethod aliases tparams elName fields] []) (\pn -> Logic.ifElse isSer [
variantCompareToMethod aliases tparams pn elName fields] [])
noCommentMethods =
Lists.map (\x -> noComment x) (Lists.concat2 [
recordEqualsMethod aliases elName fields,
(recordHashCodeMethod fields)] comparableMethods)
bodyDecls =
Lists.concat [
tn,
memberVars_,
[
consWithComment],
noCommentMethods,
withMethods,
builderDecls]
ifaces = Logic.ifElse isInner (serializableTypes isSer) (interfaceTypes isSer aliases tparams elName)
in (Right (Utils.javaClassDeclaration aliases tparams elName classModsPublic Nothing ifaces bodyDecls)))))))))))
declarationForUnionType :: Bool -> JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> [Core.FieldType] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassDeclaration
declarationForUnionType isSer aliases tparams elName fields cx g =
Eithers.bind (Eithers.mapList (\ft ->
let fname = Core.fieldTypeName ft
ftype = Core.fieldTypeType ft
rfields =
Logic.ifElse (Predicates.isUnitType (Strip.deannotateType ftype)) [] [
Core.FieldType {
Core.fieldTypeName = (Core.Name "value"),
Core.fieldTypeType = (Strip.deannotateType ftype)}]
varName = Utils.variantClassName False elName fname
in (Eithers.bind (declarationForRecordType_ True isSer aliases [] varName (Logic.ifElse isSer (Just elName) Nothing) rfields cx g) (\innerDecl -> Right (augmentVariantClass aliases tparams elName innerDecl)))) fields) (\variantClasses ->
let variantDecls =
Lists.map (\vc -> Syntax.ClassBodyDeclarationClassMember (Syntax.ClassMemberDeclarationClass vc)) variantClasses
in (Eithers.bind (Eithers.mapList (\pair -> addComment (Pairs.first pair) (Pairs.second pair) cx g) (Lists.zip variantDecls fields)) (\variantDecls_ ->
let privateConst = Utils.makeConstructor aliases elName True [] []
acceptDecl = Utils.toAcceptMethod True tparams
vtparams = Lists.concat2 tparams [
Utils.javaTypeParameter JavaNames.visitorReturnParameter]
elNameStr = Syntax.unIdentifier (Utils.nameToJavaName aliases elName)
visitorMethods =
Lists.map (\ft ->
let fname = Core.fieldTypeName ft
fnameStr = Core.unName fname
typeArgs = Lists.map (\tp -> Utils.typeParameterToTypeArgument tp) tparams
varName = Utils.variantClassName False elName fname
varNameStr = Syntax.unIdentifier (Utils.nameToJavaName aliases varName)
varLocalStr = Utils.sanitizeJavaName (Util.qualifiedNameLocal (Names.qualifyName varName))
linkVarNameStr = Strings.cat2 (Strings.cat2 elNameStr ".") varLocalStr
varRef = Utils.javaClassTypeToJavaType (Utils.nameToJavaClassType aliases False typeArgs varName Nothing)
param = Utils.javaTypeToJavaFormalParameter varRef (Core.Name "instance")
resultR = Utils.javaTypeToJavaResult (Syntax.TypeReference Utils.visitorTypeVariable)
comment =
Strings.cat [
"Visit the {@link ",
linkVarNameStr,
"} case."]
in (comment, (Utils.interfaceMethodDeclaration [] [] JavaNames.visitMethodName [
param] resultR Nothing))) fields
visitorBody =
Syntax.InterfaceBody (Lists.map (\p -> withInterfaceCommentString (Pairs.first p) (Pairs.second p)) visitorMethods)
visitor =
Utils.javaInterfaceDeclarationToJavaClassBodyDeclaration (Syntax.NormalInterfaceDeclaration {
Syntax.normalInterfaceDeclarationModifiers = [
Syntax.InterfaceModifierPublic],
Syntax.normalInterfaceDeclarationIdentifier = (Syntax.TypeIdentifier (Syntax.Identifier JavaNames.visitorName)),
Syntax.normalInterfaceDeclarationParameters = vtparams,
Syntax.normalInterfaceDeclarationExtends = [],
Syntax.normalInterfaceDeclarationPermits = [],
Syntax.normalInterfaceDeclarationBody = visitorBody})
typeArgs = Lists.map (\tp -> Utils.typeParameterToTypeArgument tp) tparams
visitorClassType =
Utils.javaClassType (Lists.concat2 (Lists.map (\tp -> Utils.typeParameterToReferenceType tp) tparams) [
Utils.visitorTypeVariable]) Nothing JavaNames.visitorName
mainInstanceParam =
Utils.javaTypeToJavaFormalParameter (Utils.javaClassTypeToJavaType (Utils.nameToJavaClassType aliases False typeArgs elName Nothing)) (Core.Name "instance")
resultR = Utils.javaTypeToJavaResult (Syntax.TypeReference Utils.visitorTypeVariable)
throwStmt =
Syntax.BlockStatementStatement (Utils.javaThrowIllegalStateException [
Utils.javaAdditiveExpressionToJavaExpression (Utils.addExpressions [
Utils.javaStringMultiplicativeExpression "Non-exhaustive patterns when matching: ",
(Syntax.MultiplicativeExpressionUnary (Utils.javaIdentifierToJavaUnaryExpression (Syntax.Identifier "instance")))])])
defaultMod = [
Syntax.InterfaceMethodModifierDefault]
otherwiseDecl =
Utils.interfaceMethodDeclaration defaultMod [] JavaNames.otherwiseMethodName [
mainInstanceParam] resultR (Just [
throwStmt])
otherwiseComment = "Default branch for unhandled cases."
pvVisitMethods =
Lists.map (\ft ->
let fname = Core.fieldTypeName ft
varName = Utils.variantClassName False elName fname
varNameStr = Syntax.unIdentifier (Utils.nameToJavaName aliases varName)
varLocalStr = Utils.sanitizeJavaName (Util.qualifiedNameLocal (Names.qualifyName varName))
linkVarNameStr = Strings.cat2 (Strings.cat2 elNameStr ".") varLocalStr
varRef = Utils.javaClassTypeToJavaType (Utils.nameToJavaClassType aliases False typeArgs varName Nothing)
param = Utils.javaTypeToJavaFormalParameter varRef (Core.Name "instance")
mi =
Utils.methodInvocation Nothing (Syntax.Identifier JavaNames.otherwiseMethodName) [
Utils.javaIdentifierToJavaExpression (Syntax.Identifier "instance")]
returnOtherwise =
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaPrimaryToJavaExpression (Utils.javaMethodInvocationToJavaPrimary mi))))
comment =
Strings.cat [
"Visit the {@link ",
linkVarNameStr,
"} case."]
in (
comment,
(Utils.interfaceMethodDeclaration defaultMod [] JavaNames.visitMethodName [
param] resultR (Just [
returnOtherwise])))) fields
pvBody =
Syntax.InterfaceBody (Lists.cons (withInterfaceCommentString otherwiseComment otherwiseDecl) (Lists.map (\p -> withInterfaceCommentString (Pairs.first p) (Pairs.second p)) pvVisitMethods))
partialVisitor =
Utils.javaInterfaceDeclarationToJavaClassBodyDeclaration (Syntax.NormalInterfaceDeclaration {
Syntax.normalInterfaceDeclarationModifiers = [
Syntax.InterfaceModifierPublic],
Syntax.normalInterfaceDeclarationIdentifier = (Syntax.TypeIdentifier (Syntax.Identifier JavaNames.partialVisitorName)),
Syntax.normalInterfaceDeclarationParameters = vtparams,
Syntax.normalInterfaceDeclarationExtends = [
Syntax.InterfaceType visitorClassType],
Syntax.normalInterfaceDeclarationPermits = [],
Syntax.normalInterfaceDeclarationBody = pvBody})
in (Eithers.bind (constantDeclForTypeName aliases elName cx g) (\tn0 -> Eithers.bind (Eithers.mapList (\ft -> constantDeclForFieldType elName aliases ft cx g) fields) (\tn1 ->
let tn = Lists.concat2 [
tn0] tn1
privateConstComment =
Strings.cat [
"Constructs an immutable {@link ",
elNameStr,
"}."]
acceptComment = "Dispatch to {@code visitor}."
visitorIfaceComment =
Strings.cat [
"Visitor over {@link ",
elNameStr,
"}."]
partialVisitorIfaceComment =
Strings.cat [
"Partial visitor over {@link ",
elNameStr,
"} with a default {@link #otherwise} branch."]
otherDecls =
[
withCommentString privateConstComment privateConst,
(withCommentString acceptComment acceptDecl),
(withCommentString visitorIfaceComment visitor),
(withCommentString partialVisitorIfaceComment partialVisitor)]
bodyDecls =
Lists.concat [
tn,
otherDecls,
variantDecls_]
mods = Lists.concat2 classModsPublic [
Syntax.ClassModifierAbstract]
in (Right (Utils.javaClassDeclaration aliases tparams elName mods Nothing (interfaceTypes isSer aliases tparams elName) bodyDecls))))))))
decodeTypeFromTerm :: Core.Term -> Maybe Core.Type
decodeTypeFromTerm term =
case (Strip.deannotateTerm term) of
Core.TermInject v0 -> Logic.ifElse (Equality.equal (Core.injectionTypeName v0) (Core.Name "hydra.core.Type")) (
let fname = Core.unName (Core.fieldName (Core.injectionField v0))
fterm = Core.fieldTerm (Core.injectionField v0)
in (Logic.ifElse (Equality.equal fname "variable") (case fterm of
Core.TermWrap v1 -> case (Core.wrappedTermBody v1) of
Core.TermLiteral v2 -> case v2 of
Core.LiteralString v3 -> Just (Core.TypeVariable (Core.Name v3))
_ -> Nothing
_ -> Nothing
_ -> Nothing) (Logic.ifElse (Equality.equal fname "annotated") (case fterm of
Core.TermRecord v1 -> Optionals.bind (Lists.maybeHead (Lists.filter (\f -> Equality.equal (Core.fieldName f) (Core.Name "body")) (Core.recordFields v1))) (\bodyField -> decodeTypeFromTerm (Core.fieldTerm bodyField))
_ -> Nothing) (Logic.ifElse (Equality.equal fname "application") (case fterm of
Core.TermRecord v1 -> Optionals.bind (Lists.maybeHead (Lists.filter (\f -> Equality.equal (Core.fieldName f) (Core.Name "function")) (Core.recordFields v1))) (\funcField -> Optionals.bind (decodeTypeFromTerm (Core.fieldTerm funcField)) (\func -> Optionals.bind (Lists.maybeHead (Lists.filter (\f -> Equality.equal (Core.fieldName f) (Core.Name "argument")) (Core.recordFields v1))) (\argField -> Optionals.map (\arg -> Core.TypeApplication (Core.ApplicationType {
Core.applicationTypeFunction = func,
Core.applicationTypeArgument = arg})) (decodeTypeFromTerm (Core.fieldTerm argField)))))
_ -> Nothing) (Logic.ifElse (Equality.equal fname "function") (case fterm of
Core.TermRecord v1 -> Optionals.bind (Lists.maybeHead (Lists.filter (\f -> Equality.equal (Core.fieldName f) (Core.Name "domain")) (Core.recordFields v1))) (\domField -> Optionals.bind (decodeTypeFromTerm (Core.fieldTerm domField)) (\dom -> Optionals.bind (Lists.maybeHead (Lists.filter (\f -> Equality.equal (Core.fieldName f) (Core.Name "codomain")) (Core.recordFields v1))) (\codField -> Optionals.map (\cod -> Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod})) (decodeTypeFromTerm (Core.fieldTerm codField)))))
_ -> Nothing) (Logic.ifElse (Equality.equal fname "literal") (case fterm of
Core.TermInject v1 -> Logic.ifElse (Equality.equal (Core.unName (Core.fieldName (Core.injectionField v1))) "string") (Just (Core.TypeLiteral Core.LiteralTypeString)) Nothing
_ -> Nothing) Nothing)))))) Nothing
_ -> Nothing
dedupBindings :: S.Set Core.Name -> [Core.Binding] -> [Core.Binding]
dedupBindings inScope bs =
Optionals.fromOptional [] (Optionals.map (\p ->
let b = Pairs.first p
rest = Pairs.second p
name = Core.bindingName b
in (Logic.ifElse (Sets.member name inScope) (
let newName = freshJavaName name inScope
subst = Maps.singleton name newName
rest2 =
Lists.map (\b2 -> Core.Binding {
Core.bindingName = (Core.bindingName b2),
Core.bindingTerm = (Variables.substituteVariables subst (Core.bindingTerm b2)),
Core.bindingTypeScheme = (Core.bindingTypeScheme b2)}) rest
in (Lists.cons (Core.Binding {
Core.bindingName = newName,
Core.bindingTerm = (Core.bindingTerm b),
Core.bindingTypeScheme = (Core.bindingTypeScheme b)}) (dedupBindings (Sets.insert newName inScope) rest2))) (Lists.cons b (dedupBindings (Sets.insert name inScope) rest)))) (Lists.uncons bs))
detectAccumulatorUnification :: [Core.Type] -> Core.Type -> [Core.Name] -> M.Map Core.Name Core.Type
detectAccumulatorUnification doms cod tparams =
let tparamSet = Sets.fromList tparams
allPairs = Lists.bind doms (\d -> extractInOutPair d)
groupedByInput = groupPairsByFirst allPairs
selfRefSubst = selfRefSubstitution groupedByInput
directPairs = Lists.bind doms (\d -> extractDirectReturn tparamSet d)
groupedDirect = groupPairsByFirst directPairs
directInputVars = Sets.fromList (Lists.map (\p -> Pairs.first p) directPairs)
codVar =
case (Strip.deannotateType cod) of
Core.TypeVariable v0 -> Just v0
_ -> Nothing
directRefSubst = directRefSubstitution directInputVars codVar groupedDirect
codSubst =
Optionals.cases (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Maps.member cv selfRefSubst) Maps.empty (Optionals.cases (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Logic.ifElse (Equality.equal cv refVar) Maps.empty (Maps.singleton cv refVar))))
domVars = Sets.fromList (Lists.bind doms (\d -> Sets.toList (collectTypeVars d)))
danglingSubst =
Optionals.cases (findPairFirst cod) Maps.empty (\cv -> Logic.ifElse (Sets.member cv domVars) Maps.empty (Optionals.cases (findSelfRefVar groupedByInput) Maps.empty (\refVar -> Maps.singleton cv (Core.TypeVariable refVar))))
in (Maps.union (Maps.union (Maps.union (nameMapToTypeMap selfRefSubst) (nameMapToTypeMap codSubst)) danglingSubst) (nameMapToTypeMap directRefSubst))
directRefSubstitution :: (Eq t0, Ord t0) => (S.Set t0 -> Maybe t0 -> M.Map t0 [t0] -> M.Map t0 t0)
directRefSubstitution directInputVars codVar grouped =
Lists.foldl (\subst -> \entry -> directRefSubstitution_processGroup directInputVars codVar subst (Pairs.first entry) (Pairs.second entry)) Maps.empty (Maps.toList grouped)
directRefSubstitution_processGroup :: (Eq t0, Ord t0) => (S.Set t0 -> Maybe t0 -> M.Map t0 t0 -> t0 -> [t0] -> M.Map t0 t0)
directRefSubstitution_processGroup directInputVars codVar subst inVar outVars =
let selfRefCount = Lists.length (Lists.filter (\v -> Equality.equal v inVar) outVars)
nonSelfVars = Lists.filter (\v -> Logic.not (Equality.equal v inVar)) outVars
safeNonSelfVars =
Lists.filter (\v -> Logic.and (Logic.not (Sets.member v directInputVars)) (Logic.not (Equality.equal (Just v) codVar))) nonSelfVars
in (Logic.ifElse (Logic.and (Equality.gte selfRefCount 2) (Logic.not (Lists.null safeNonSelfVars))) (Lists.foldl (\s -> \v -> Maps.insert v inVar s) subst safeNonSelfVars) subst)
domTypeArgs :: JavaEnvironment.Aliases -> Core.Type -> t0 -> Graph.Graph -> Either Errors.Error [Syntax.TypeArgument]
domTypeArgs aliases d cx g =
let args = extractTypeApplicationArgs (Strip.deannotateType d)
in (Logic.ifElse (Logic.not (Lists.null args)) (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt)))) args) (Right (javaTypeArgumentsForType d)))
elementJavaIdentifier :: Bool -> Bool -> JavaEnvironment.Aliases -> Core.Name -> Syntax.Identifier
elementJavaIdentifier isPrim isMethod aliases name =
let qn = Names.qualifyName name
ns_ = Util.qualifiedNameModuleName qn
local = Util.qualifiedNameLocal qn
sep = Logic.ifElse isMethod "::" "."
in (Logic.ifElse isPrim (Syntax.Identifier (Strings.cat2 (Strings.cat2 (elementJavaIdentifier_qualify aliases ns_ (Formatting.capitalize local)) ".") JavaNames.applyMethodName)) (Optionals.cases ns_ (Syntax.Identifier (Utils.sanitizeJavaName local)) (\n -> Syntax.Identifier (Strings.cat2 (Strings.cat2 (elementJavaIdentifier_qualify aliases (namespaceParent n) (elementsClassName n)) sep) (Utils.sanitizeJavaName local)))))
elementJavaIdentifier_qualify :: JavaEnvironment.Aliases -> Maybe Packaging.ModuleName -> String -> String
elementJavaIdentifier_qualify aliases mns s =
Syntax.unIdentifier (Utils.nameToJavaName aliases (Names.unqualifyName (Util.QualifiedName {
Util.qualifiedNameModuleName = mns,
Util.qualifiedNameLocal = s})))
elementsClassName :: Packaging.ModuleName -> String
elementsClassName ns =
let nsStr = Packaging.unModuleName ns
parts = Strings.splitOn "." nsStr
in (Formatting.sanitizeWithUnderscores Language.reservedWords (Formatting.capitalize (Optionals.fromOptional nsStr (Lists.maybeLast parts))))
elementsQualifiedName :: Packaging.ModuleName -> Core.Name
elementsQualifiedName ns =
Names.unqualifyName (Util.QualifiedName {
Util.qualifiedNameModuleName = (namespaceParent ns),
Util.qualifiedNameLocal = (elementsClassName ns)})
encodeApplication :: JavaEnvironment.JavaEnvironment -> Core.Application -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeApplication env app cx g0 =
let aliases = JavaEnvironment.javaEnvironmentAliases env
g = JavaEnvironment.javaEnvironmentGraph env
gathered = Analysis.gatherArgsWithTypeApps (Core.TermApplication app) [] []
fun = Pairs.first gathered
args = Pairs.first (Pairs.second gathered)
typeApps = Pairs.second (Pairs.second gathered)
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g (Annotations.termAnnotationInternal fun))) (\mfunTyp -> Eithers.bind (Optionals.cases mfunTyp (Checking.typeOfTerm cx g fun) (\t -> Right t)) (\funTyp ->
let arity = Arity.typeArity funTyp
deannotatedFun = Strip.deannotateTerm fun
calleeName =
case deannotatedFun of
Core.TermVariable v0 -> Just v0
_ -> Nothing
in (Eithers.bind (Optionals.cases calleeName (Right args) (\cname -> annotateLambdaArgs cname typeApps args cx g)) (\annotatedArgs -> case deannotatedFun of
Core.TermVariable v0 -> Logic.ifElse (Optionals.isGiven (Maps.lookup v0 (Graph.graphPrimitives g))) (
let hargs = Lists.take arity annotatedArgs
rargs = Lists.drop arity annotatedArgs
in (Eithers.bind (functionCall env True v0 hargs [] cx g) (\initialCall -> Eithers.foldl (\acc -> \h -> Eithers.bind (encodeTerm env h cx g) (\jarg -> Right (applyJavaArg acc jarg))) initialCall rargs))) (Logic.ifElse (Logic.and (isRecursiveVariable aliases v0) (Logic.not (isLambdaBoundIn v0 (JavaEnvironment.aliasesLambdaVars aliases)))) (encodeApplication_fallback env aliases g typeApps (Core.applicationFunction app) (Core.applicationArgument app) cx g) (Eithers.bind (classifyDataReference v0 cx g) (\symClass ->
let methodArity =
case symClass of
JavaEnvironment.JavaSymbolClassHoistedLambda v1 -> v1
_ -> arity
hargs = Lists.take methodArity annotatedArgs
rargs = Lists.drop methodArity annotatedArgs
trusted = JavaEnvironment.aliasesTrustedTypeVars aliases
inScope = JavaEnvironment.aliasesInScopeTypeParams aliases
filteredTypeApps =
Logic.ifElse (Logic.or (Sets.null trusted) (Sets.null inScope)) [] (
let allVars = Sets.unions (Lists.map (\t -> collectTypeVars t) typeApps)
in (Logic.ifElse (Logic.not (Sets.null (Sets.difference allVars inScope))) [] (Logic.ifElse (Sets.null (Sets.difference allVars trusted)) typeApps [])))
in (Eithers.bind (Logic.ifElse (Lists.null filteredTypeApps) (Right []) (correctTypeApps g v0 hargs filteredTypeApps cx g)) (\safeTypeApps -> Eithers.bind (filterPhantomTypeArgs v0 safeTypeApps cx g) (\finalTypeApps -> Eithers.bind (functionCall env False v0 hargs finalTypeApps cx g) (\initialCall -> Eithers.foldl (\acc -> \h -> Eithers.bind (encodeTerm env h cx g) (\jarg -> Right (applyJavaArg acc jarg))) initialCall rargs)))))))
_ -> encodeApplication_fallback env aliases g typeApps (Core.applicationFunction app) (Core.applicationArgument app) cx g)))))
encodeApplication_fallback :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> Graph.Graph -> [Core.Type] -> Core.Term -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeApplication_fallback env aliases gr typeApps lhs rhs cx g =
Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g (Annotations.termAnnotationInternal lhs))) (\mt -> Eithers.bind (Optionals.cases mt (Checking.typeOfTerm cx g lhs) (\typ -> Right typ)) (\t -> case (Strip.deannotateTypeParameters (Strip.deannotateType t)) of
Core.TypeFunction v0 ->
let dom = Core.functionTypeDomain v0
cod = Core.functionTypeCodomain v0
defaultExpr =
\_bug438_dflt -> Eithers.bind (encodeTerm env lhs cx g) (\jfun -> Eithers.bind (encodeTerm env rhs cx g) (\jarg -> Right (applyJavaArg jfun jarg)))
elimBranch =
\_bug438_elim -> Eithers.bind (encodeTerm env rhs cx g) (\jarg -> Eithers.bind (Logic.ifElse (Logic.not (Lists.null (javaTypeArgumentsForType dom))) (Right dom) (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g (Annotations.termAnnotationInternal rhs))) (\mrt -> Optionals.cases mrt (Eithers.bind (Checking.typeOfTerm cx g rhs) (\rt -> Right (Logic.ifElse (Logic.not (Lists.null (javaTypeArgumentsForType rt))) rt dom))) (\rt -> Right (Logic.ifElse (Logic.not (Lists.null (javaTypeArgumentsForType rt))) rt dom))))) (\enrichedDom -> encodeElimination env (Just jarg) enrichedDom cod (Strip.deannotateTerm lhs) cx g))
in case (Strip.deannotateAndDetypeTerm lhs) of
Core.TermProject _ -> elimBranch ()
Core.TermCases _ -> elimBranch ()
Core.TermUnwrap _ -> elimBranch ()
_ -> defaultExpr ()
_ -> Eithers.bind (encodeTerm env lhs cx g) (\jfun -> Eithers.bind (encodeTerm env rhs cx g) (\jarg -> Right (applyJavaArg jfun jarg)))))
encodeDefinitions :: Packaging.Module -> [Packaging.Definition] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error (M.Map Core.Name Syntax.CompilationUnit)
encodeDefinitions mod defs cx g =
let aliases = Utils.importAliasesForModule mod
env =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = aliases,
JavaEnvironment.javaEnvironmentGraph = g}
pkg = Utils.javaPackageDeclaration (Packaging.moduleName mod)
partitioned = Environment.partitionDefinitions defs
typeDefs = Pairs.first partitioned
termDefs = Pairs.second partitioned
nonTypedefDefs =
Lists.filter (\td ->
let typ = Core.typeSchemeBody (Packaging.typeDefinitionBody td)
in (isSerializableJavaType typ)) typeDefs
in (Eithers.bind (Eithers.mapList (\td -> encodeTypeDefinition pkg aliases td cx g) nonTypedefDefs) (\typeUnits -> Eithers.bind (Logic.ifElse (Lists.null termDefs) (Right []) (Eithers.bind (Eithers.mapList (\td -> encodeTermDefinition env td cx g) termDefs) (\dataMembers -> Right [
constructElementsInterface mod dataMembers]))) (\termUnits -> Right (Maps.fromList (Lists.concat2 typeUnits termUnits)))))
encodeElimination :: JavaEnvironment.JavaEnvironment -> Maybe Syntax.Expression -> Core.Type -> Core.Type -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeElimination env marg dom cod elimTerm cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
in case (Strip.deannotateAndDetypeTerm elimTerm) of
Core.TermProject v0 ->
let fname = Core.projectionFieldName v0
in (Eithers.bind (encodeType aliases Sets.empty dom cx g) (\jdom0 -> Eithers.bind (Utils.javaTypeToJavaReferenceType jdom0 cx) (\_ -> Optionals.cases marg (
let projVar = Core.Name "projected"
jbody =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.variableToJavaIdentifier projVar) (Utils.javaIdentifier (Core.unName fname)))
in (Right (Utils.javaLambda projVar jbody))) (\jarg ->
let qual = Syntax.FieldAccess_QualifierPrimary (Utils.javaExpressionToJavaPrimary jarg)
in (Right (Utils.javaFieldAccessToJavaExpression (Syntax.FieldAccess {
Syntax.fieldAccessQualifier = qual,
Syntax.fieldAccessIdentifier = (Utils.javaIdentifier (Core.unName fname))})))))))
Core.TermCases v0 ->
let tname = Core.caseStatementTypeName v0
def_ = Core.caseStatementDefault v0
fields = Core.caseStatementCases v0
in (Optionals.cases marg (
let uVar = Core.Name "u"
domTypeArgs0 =
\ty -> \acc -> case (Strip.deannotateType ty) of
Core.TypeApplication v1 -> domTypeArgs0 (Core.applicationTypeFunction v1) (Lists.cons (Core.applicationTypeArgument v1) acc)
_ -> acc
domTypeArgs = domTypeArgs0 dom []
bareElim = Strip.deannotateAndDetypeTerm elimTerm
wrappedElimTerm =
Lists.foldl (\trm -> \t -> Core.TermTypeApplication (Core.TypeApplicationTerm {
Core.typeApplicationTermBody = trm,
Core.typeApplicationTermType = t})) bareElim domTypeArgs
typedLambda =
Core.TermLambda (Core.Lambda {
Core.lambdaParameter = uVar,
Core.lambdaDomain = (Just dom),
Core.lambdaBody = (Core.TermApplication (Core.Application {
Core.applicationFunction = wrappedElimTerm,
Core.applicationArgument = (Core.TermVariable uVar)}))})
in (encodeTerm env typedLambda cx g)) (\jarg ->
let prim = Utils.javaExpressionToJavaPrimary jarg
consId = innerClassRef aliases tname JavaNames.partialVisitorName
effectiveCod = cod
in (Eithers.bind (encodeType aliases Sets.empty effectiveCod cx g) (\jcod -> Eithers.bind (Utils.javaTypeToJavaReferenceType jcod cx) (\rt -> Eithers.bind (domTypeArgs aliases dom cx g) (\domArgs ->
let targs = typeArgsOrDiamond (Lists.concat2 domArgs [
Syntax.TypeArgumentReference rt])
in (Eithers.bind (Optionals.cases def_ (Right []) (\d -> Eithers.bind (otherwiseBranch env aliases dom cod tname jcod domArgs d cx g) (\b -> Right [
b]))) (\otherwiseBranches -> Eithers.bind (Eithers.mapList (\f -> visitBranch env aliases dom tname jcod domArgs f cx g) fields) (\visitBranches ->
let body = Syntax.ClassBody (Lists.concat2 otherwiseBranches visitBranches)
visitor = Utils.javaConstructorCall (Utils.javaConstructorName consId (Just targs)) [] (Just body)
in (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation (Just (Right prim)) (Syntax.Identifier JavaNames.acceptMethodName) [
visitor]))))))))))))
Core.TermUnwrap _ ->
let withArg =
\ja -> Utils.javaFieldAccessToJavaExpression (Syntax.FieldAccess {
Syntax.fieldAccessQualifier = (Syntax.FieldAccess_QualifierPrimary (Utils.javaExpressionToJavaPrimary ja)),
Syntax.fieldAccessIdentifier = (Utils.javaIdentifier JavaNames.valueFieldName)})
in (Right (Optionals.cases marg (
let wVar = Core.Name "wrapped"
wArg = Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier wVar)
in (Utils.javaLambda wVar (withArg wArg))) (\jarg -> withArg jarg)))
_ -> Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "unexpected " (Strings.cat2 "elimination case" (Strings.cat2 " in " "encodeElimination")))))
encodeFunction :: JavaEnvironment.JavaEnvironment -> Core.Type -> Core.Type -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeFunction env dom cod funTerm cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
encodeLambdaFallback =
\env2 -> \lam ->
let lambdaVar = Core.lambdaParameter lam
body = Core.lambdaBody lam
in (Eithers.bind (analyzeJavaFunction env2 body cx g) (\fs ->
let bindings = Typing.functionStructureBindings fs
innerBody = Typing.functionStructureBody fs
env3 = Typing.functionStructureEnvironment fs
in (Eithers.bind (bindingsToStatements env3 bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env4 = Pairs.second bindResult
in (Eithers.bind (encodeTerm env4 innerBody cx g) (\jbody ->
let lam1 =
Logic.ifElse (Lists.null bindings) (Utils.javaLambda lambdaVar jbody) (
let returnSt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jbody))
in (Utils.javaLambdaFromBlock lambdaVar (Syntax.Block (Lists.concat2 bindingStmts [
returnSt]))))
in (applyCastIfSafe aliases (Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod})) lam1 cx g)))))))
in case (Strip.deannotateTerm funTerm) of
Core.TermProject _ -> encodeElimination env Nothing dom cod (Strip.deannotateTerm funTerm) cx g
Core.TermCases _ -> encodeElimination env Nothing dom cod (Strip.deannotateTerm funTerm) cx g
Core.TermUnwrap _ -> encodeElimination env Nothing dom cod (Strip.deannotateTerm funTerm) cx g
Core.TermLambda v0 -> withLambda env v0 (\env2 ->
let lambdaVar = Core.lambdaParameter v0
body = Core.lambdaBody v0
in case (Strip.deannotateTerm body) of
Core.TermLambda v1 -> case (Strip.deannotateType cod) of
Core.TypeFunction v2 ->
let dom2 = Core.functionTypeDomain v2
cod2 = Core.functionTypeCodomain v2
in (Eithers.bind (encodeFunction env2 dom2 cod2 (Core.TermLambda v1) cx g) (\innerJavaLambda ->
let lam1 = Utils.javaLambda lambdaVar innerJavaLambda
in (applyCastIfSafe aliases (Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod})) lam1 cx g)))
_ -> Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "expected function type for lambda body, but got: " (ShowCore.type_ cod))))
_ -> encodeLambdaFallback env2 v0)
_ -> Right (encodeLiteral (Core.LiteralString (Strings.cat2 "Unimplemented function variant: " (ShowCore.term funTerm))))
encodeFunctionFormTerm :: JavaEnvironment.JavaEnvironment -> [M.Map Core.Name Core.Term] -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeFunctionFormTerm env anns term cx g =
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mt -> Eithers.bind (Optionals.cases mt (Optionals.cases (tryInferFunctionType term) (Checking.typeOfTerm cx g term) (\inferredType -> Right inferredType)) (\t -> Right t)) (\typ -> case (Strip.deannotateType typ) of
Core.TypeFunction v0 -> encodeFunction env (Core.functionTypeDomain v0) (Core.functionTypeCodomain v0) term cx g
_ -> encodeNullaryConstant env typ term cx g)))
encodeFunctionPrimitiveByName :: JavaEnvironment.JavaEnvironment -> Core.Type -> Core.Type -> Core.Name -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeFunctionPrimitiveByName env dom cod name cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
classWithApply = Syntax.unIdentifier (elementJavaIdentifier True False aliases name)
suffix = Strings.cat2 "." JavaNames.applyMethodName
className =
Strings.fromList (Lists.take (Math.sub (Strings.length classWithApply) (Strings.length suffix)) (Strings.toList classWithApply))
arity =
Arity.typeArity (Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod}))
in (Logic.ifElse (Equality.lte arity 1) (Right (Utils.javaIdentifierToJavaExpression (Syntax.Identifier (Strings.cat [
className,
"::",
JavaNames.applyMethodName])))) (
let paramNames = Lists.map (\i -> Core.Name (Strings.cat2 "p" (Literals.showInt32 i))) (Math.range 0 (Math.sub arity 1))
paramExprs = Lists.map (\p -> Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier p)) paramNames
classId = Syntax.Identifier className
call =
Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic classId (Syntax.Identifier JavaNames.applyMethodName) paramExprs)
curried = buildCurriedLambda paramNames call
in (Eithers.bind (encodeType aliases Sets.empty (Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod})) cx g) (\jtype -> Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt -> Right (Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression rt (Utils.javaExpressionToJavaUnaryExpression curried))))))))
encodeLiteral :: Core.Literal -> Syntax.Expression
encodeLiteral lit =
case lit of
Core.LiteralBinary v0 ->
let byteValues = Literals.binaryToBytes v0
in (Utils.javaArrayCreation Utils.javaBytePrimitiveType (Just (Utils.javaArrayInitializer (Lists.map (\w -> Utils.javaLiteralToJavaExpression (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.int32ToBigint w)))) byteValues))))
Core.LiteralBoolean v0 -> encodeLiteral_litExp (Utils.javaBoolean v0)
Core.LiteralDecimal v0 -> Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "java.math.BigDecimal") Nothing) [
encodeLiteral (Core.LiteralString (Literals.showDecimal v0))] Nothing
Core.LiteralFloat v0 -> encodeLiteral_encodeFloat v0
Core.LiteralInteger v0 -> encodeLiteral_encodeInteger v0
Core.LiteralString v0 -> encodeLiteral_litExp (Utils.javaString v0)
encodeLiteralType :: Core.LiteralType -> t0 -> t1 -> Either t2 Syntax.Type
encodeLiteralType lt cx g =
case lt of
Core.LiteralTypeBinary -> Right (Syntax.TypeReference (Syntax.ReferenceTypeArray (Syntax.ArrayType {
Syntax.arrayTypeDims = (Syntax.Dims [
[]]),
Syntax.arrayTypeVariant = (Syntax.ArrayType_VariantPrimitive (Syntax.PrimitiveTypeWithAnnotations {
Syntax.primitiveTypeWithAnnotationsType = (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeByte)),
Syntax.primitiveTypeWithAnnotationsAnnotations = []}))})))
Core.LiteralTypeBoolean -> encodeLiteralType_simple "Boolean" cx g
Core.LiteralTypeDecimal -> Right (Utils.javaRefType [] (Just (JavaNames.javaPackageName [
"java",
"math"])) "BigDecimal")
Core.LiteralTypeFloat v0 -> case v0 of
Core.FloatTypeFloat32 -> encodeLiteralType_simple "Float" cx g
Core.FloatTypeFloat64 -> encodeLiteralType_simple "Double" cx g
Core.LiteralTypeInteger v0 -> case v0 of
Core.IntegerTypeBigint -> Right (Utils.javaRefType [] (Just (JavaNames.javaPackageName [
"java",
"math"])) "BigInteger")
Core.IntegerTypeInt8 -> encodeLiteralType_simple "Byte" cx g
Core.IntegerTypeInt16 -> encodeLiteralType_simple "Short" cx g
Core.IntegerTypeInt32 -> encodeLiteralType_simple "Integer" cx g
Core.IntegerTypeInt64 -> encodeLiteralType_simple "Long" cx g
Core.IntegerTypeUint8 -> encodeLiteralType_simple "Short" cx g
Core.IntegerTypeUint16 -> encodeLiteralType_simple "Character" cx g
Core.IntegerTypeUint32 -> encodeLiteralType_simple "Long" cx g
Core.IntegerTypeUint64 -> Right (Utils.javaRefType [] (Just (JavaNames.javaPackageName [
"java",
"math"])) "BigInteger")
Core.LiteralTypeString -> encodeLiteralType_simple "String" cx g
encodeLiteralType_simple :: String -> t0 -> t1 -> Either t2 Syntax.Type
encodeLiteralType_simple n cx g = Right (Utils.javaRefType [] Nothing n)
encodeLiteral_encodeFloat :: Core.FloatValue -> Syntax.Expression
encodeLiteral_encodeFloat f =
case f of
Core.FloatValueFloat32 v0 -> encodeLiteral_encodeFloat32 v0
Core.FloatValueFloat64 v0 -> encodeLiteral_encodeFloat64 v0
encodeLiteral_encodeFloat32 :: Float -> Syntax.Expression
encodeLiteral_encodeFloat32 v =
let s = Literals.showFloat32 v
in (Logic.ifElse (Equality.equal s "NaN") (encodeLiteral_javaSpecialFloatExpr "Float" "NaN") (Logic.ifElse (Equality.equal s "Infinity") (encodeLiteral_javaSpecialFloatExpr "Float" "POSITIVE_INFINITY") (Logic.ifElse (Equality.equal s "-Infinity") (encodeLiteral_javaSpecialFloatExpr "Float" "NEGATIVE_INFINITY") (encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeFloatingPoint Syntax.FloatingPointTypeFloat)) (encodeLiteral_litExp (Syntax.LiteralFloatingPoint (Syntax.FloatingPointLiteral (Literals.float32ToFloat64 v))))))))
encodeLiteral_encodeFloat64 :: Double -> Syntax.Expression
encodeLiteral_encodeFloat64 v =
let s = Literals.showFloat64 v
in (Logic.ifElse (Equality.equal s "NaN") (encodeLiteral_javaSpecialFloatExpr "Double" "NaN") (Logic.ifElse (Equality.equal s "Infinity") (encodeLiteral_javaSpecialFloatExpr "Double" "POSITIVE_INFINITY") (Logic.ifElse (Equality.equal s "-Infinity") (encodeLiteral_javaSpecialFloatExpr "Double" "NEGATIVE_INFINITY") (Logic.ifElse (Equality.equal s "-0.0") (encodeLiteral_javaParseDouble "-0.0") (encodeLiteral_litExp (Syntax.LiteralFloatingPoint (Syntax.FloatingPointLiteral v)))))))
encodeLiteral_encodeInteger :: Core.IntegerValue -> Syntax.Expression
encodeLiteral_encodeInteger i =
case i of
Core.IntegerValueBigint v0 -> Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "java.math.BigInteger") Nothing) [
encodeLiteral (Core.LiteralString (Literals.showBigint v0))] Nothing
Core.IntegerValueInt8 v0 -> encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeByte)) (encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.int8ToBigint v0))))
Core.IntegerValueInt16 v0 -> encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeShort)) (encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.int16ToBigint v0))))
Core.IntegerValueInt32 v0 -> encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.int32ToBigint v0)))
Core.IntegerValueInt64 v0 -> encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeLong)) (encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.int64ToBigint v0))))
Core.IntegerValueUint8 v0 -> encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeShort)) (encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.uint8ToBigint v0))))
Core.IntegerValueUint16 v0 -> encodeLiteral_litExp (Syntax.LiteralCharacter v0)
Core.IntegerValueUint32 v0 -> encodeLiteral_primCast (Syntax.PrimitiveTypeNumeric (Syntax.NumericTypeIntegral Syntax.IntegralTypeLong)) (encodeLiteral_litExp (Syntax.LiteralInteger (Syntax.IntegerLiteral (Literals.uint32ToBigint v0))))
Core.IntegerValueUint64 v0 -> Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "java.math.BigInteger") Nothing) [
encodeLiteral (Core.LiteralString (Literals.showBigint (Literals.uint64ToBigint v0)))] Nothing
encodeLiteral_javaParseDouble :: String -> Syntax.Expression
encodeLiteral_javaParseDouble value =
Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "Double") (Syntax.Identifier "parseDouble") [
encodeLiteral (Core.LiteralString value)])
encodeLiteral_javaSpecialFloatExpr :: String -> String -> Syntax.Expression
encodeLiteral_javaSpecialFloatExpr className fieldName =
Utils.javaExpressionNameToJavaExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = (Just (Syntax.AmbiguousName [
Syntax.Identifier className])),
Syntax.expressionNameIdentifier = (Syntax.Identifier fieldName)})
encodeLiteral_litExp :: Syntax.Literal -> Syntax.Expression
encodeLiteral_litExp l = Utils.javaLiteralToJavaExpression l
encodeLiteral_primCast :: Syntax.PrimitiveType -> Syntax.Expression -> Syntax.Expression
encodeLiteral_primCast pt expr =
Utils.javaCastExpressionToJavaExpression (Utils.javaCastPrimitive pt (Utils.javaExpressionToJavaUnaryExpression expr))
encodeNullaryConstant :: t0 -> t1 -> Core.Term -> t2 -> t3 -> Either Errors.Error t4
encodeNullaryConstant env typ funTerm cx g =
Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "unexpected " (Strings.cat2 "nullary function" (Strings.cat2 " in " (ShowCore.term funTerm))))))
encodeNullaryConstant_typeArgsFromReturnType :: JavaEnvironment.Aliases -> Core.Type -> t0 -> Graph.Graph -> Either Errors.Error [Syntax.TypeArgument]
encodeNullaryConstant_typeArgsFromReturnType aliases t cx g =
case (Strip.deannotateType t) of
Core.TypeSet v0 -> Eithers.bind (encodeType aliases Sets.empty v0 cx g) (\jst -> Eithers.bind (Utils.javaTypeToJavaReferenceType jst cx) (\rt -> Right [
Syntax.TypeArgumentReference rt]))
Core.TypeList v0 -> Eithers.bind (encodeType aliases Sets.empty v0 cx g) (\jlt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jlt cx) (\rt -> Right [
Syntax.TypeArgumentReference rt]))
Core.TypeOptional v0 -> Eithers.bind (encodeType aliases Sets.empty v0 cx g) (\jmt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jmt cx) (\rt -> Right [
Syntax.TypeArgumentReference rt]))
Core.TypeMap v0 -> Eithers.bind (encodeType aliases Sets.empty (Core.mapTypeKeys v0) cx g) (\jkt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jkt cx) (\rk -> Eithers.bind (encodeType aliases Sets.empty (Core.mapTypeValues v0) cx g) (\jvt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jvt cx) (\rv -> Right [
Syntax.TypeArgumentReference rk,
(Syntax.TypeArgumentReference rv)]))))
_ -> Right []
encodeNullaryPrimitiveByName :: JavaEnvironment.JavaEnvironment -> Core.Type -> Core.Name -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeNullaryPrimitiveByName env typ name cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
in (Eithers.bind (encodeNullaryConstant_typeArgsFromReturnType aliases typ cx g) (\targs -> Logic.ifElse (Lists.null targs) (
let header = Syntax.MethodInvocation_HeaderSimple (Syntax.MethodName (elementJavaIdentifier True False aliases name))
in (Right (Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = []})))) (
let fullName = Syntax.unIdentifier (elementJavaIdentifier True False aliases name)
parts = Strings.splitOn "." fullName
className = Syntax.Identifier (Strings.intercalate "." (Optionals.fromOptional [] (Lists.maybeInit parts)))
methodName = Syntax.Identifier (Optionals.fromOptional fullName (Lists.maybeLast parts))
in (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs className methodName targs []))))))
encodeTerm :: JavaEnvironment.JavaEnvironment -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeTerm env term cx g = encodeTermInternal env [] [] term cx g
encodeTermDefinition :: JavaEnvironment.JavaEnvironment -> Packaging.TermDefinition -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.InterfaceMemberDeclarationWithComments
encodeTermDefinition env tdef cx g =
let name = Packaging.termDefinitionName tdef
term0 = Packaging.termDefinitionBody tdef
in (Eithers.bind (Annotations.getTermDescription cx g term0) (\mDoc ->
let ts =
Optionals.cases (Packaging.termDefinitionSignature tdef) (Core.TypeScheme {
Core.typeSchemeVariables = [],
Core.typeSchemeBody = (Core.TypeVariable (Core.Name "hydra.core.Unit")),
Core.typeSchemeConstraints = Nothing}) (\sig -> Scoping.termSignatureToTypeScheme sig)
term = Variables.unshadowVariables term0
in (Eithers.bind (analyzeJavaFunction env term cx g) (\fs ->
let schemeVars = Lists.filter (\v -> isSimpleName v) (Core.typeSchemeVariables ts)
termVars = Typing.functionStructureTypeParams fs
schemeTypeVars = collectTypeVars (Core.typeSchemeBody ts)
usedSchemeVars = Lists.filter (\v -> Sets.member v schemeTypeVars) schemeVars
tparams = Logic.ifElse (Lists.null usedSchemeVars) termVars usedSchemeVars
params = Typing.functionStructureParams fs
bindings = Typing.functionStructureBindings fs
body = Typing.functionStructureBody fs
doms = Typing.functionStructureDomains fs
env2 = Typing.functionStructureEnvironment fs
schemeType = Core.typeSchemeBody ts
numParams = Lists.length params
peelResult = peelDomainsAndCod numParams schemeType
schemeDoms = Pairs.first peelResult
cod = Pairs.second peelResult
schemeVarSet = Sets.fromList tparams
in (Eithers.bind (Logic.ifElse (Lists.null tparams) (Right Maps.empty) (buildSubstFromAnnotations schemeVarSet term cx g)) (\typeVarSubst ->
let overgenSubst = detectAccumulatorUnification schemeDoms cod tparams
overgenVarSubst =
Maps.fromList (Optionals.cat (Lists.map (\entry ->
let k = Pairs.first entry
v = Pairs.second entry
in case v of
Core.TypeVariable v0 -> Just (k, v0)
_ -> Nothing) (Maps.toList overgenSubst)))
fixedCod = Logic.ifElse (Maps.null overgenSubst) cod (substituteTypeVarsWithTypes overgenSubst cod)
fixedDoms =
Logic.ifElse (Maps.null overgenSubst) schemeDoms (Lists.map (\d -> substituteTypeVarsWithTypes overgenSubst d) schemeDoms)
fixedTparams =
Logic.ifElse (Maps.null overgenSubst) tparams (Lists.filter (\v -> Logic.not (Maps.member v overgenSubst)) tparams)
constraints = Optionals.fromOptional Maps.empty (Core.typeSchemeConstraints ts)
jparams = Lists.map (\v -> Utils.javaTypeParameter (Formatting.capitalize (Core.unName v))) fixedTparams
aliases2base = JavaEnvironment.javaEnvironmentAliases env2
trustedVars = Sets.unions (Lists.map (\d -> collectTypeVars d) (Lists.concat2 fixedDoms [
fixedCod]))
fixedSchemeVarSet = Sets.fromList fixedTparams
aliases2 =
JavaEnvironment.Aliases {
JavaEnvironment.aliasesCurrentNamespace = (JavaEnvironment.aliasesCurrentNamespace aliases2base),
JavaEnvironment.aliasesPackages = (JavaEnvironment.aliasesPackages aliases2base),
JavaEnvironment.aliasesBranchVars = (JavaEnvironment.aliasesBranchVars aliases2base),
JavaEnvironment.aliasesRecursiveVars = (JavaEnvironment.aliasesRecursiveVars aliases2base),
JavaEnvironment.aliasesInScopeTypeParams = fixedSchemeVarSet,
JavaEnvironment.aliasesPolymorphicLocals = (JavaEnvironment.aliasesPolymorphicLocals aliases2base),
JavaEnvironment.aliasesInScopeJavaVars = (JavaEnvironment.aliasesInScopeJavaVars aliases2base),
JavaEnvironment.aliasesVarRenames = (JavaEnvironment.aliasesVarRenames aliases2base),
JavaEnvironment.aliasesLambdaVars = (Sets.union (JavaEnvironment.aliasesLambdaVars aliases2base) (Sets.fromList params)),
JavaEnvironment.aliasesTypeVarSubst = (Maps.union overgenVarSubst typeVarSubst),
JavaEnvironment.aliasesTrustedTypeVars = (Sets.intersection trustedVars fixedSchemeVarSet),
JavaEnvironment.aliasesMethodCodomain = (Just fixedCod),
JavaEnvironment.aliasesThunkedVars = (JavaEnvironment.aliasesThunkedVars aliases2base)}
env2WithTypeParams =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = aliases2,
JavaEnvironment.javaEnvironmentGraph = (JavaEnvironment.javaEnvironmentGraph env2)}
in (Eithers.bind (bindingsToStatements env2WithTypeParams bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env3 = Pairs.second bindResult
in (Eithers.bind (Logic.ifElse (Maps.null overgenSubst) (Right body) (applyOvergenSubstToTermAnnotations overgenSubst body cx g)) (\body_ ->
let annotatedBody = propagateTypesInAppChain fixedCod fixedCod body_
in (Eithers.bind (Eithers.mapList (\pair -> Eithers.bind (encodeType aliases2 Sets.empty (Pairs.first pair) cx g) (\jdom -> Right (Utils.javaTypeToJavaFormalParameter jdom (Pairs.second pair)))) (Lists.zip fixedDoms params)) (\jformalParams -> Eithers.bind (encodeType aliases2 Sets.empty fixedCod cx g) (\jcod ->
let result = Utils.javaTypeToJavaResult jcod
mods = [
Syntax.InterfaceMethodModifierStatic]
jname = Utils.sanitizeJavaName (Formatting.decapitalize (Names.localNameOf name))
isTCO = False
in (Eithers.bind (Logic.ifElse isTCO (
let tcoSuffix = "_tco"
snapshotNames = Lists.map (\p -> Core.Name (Strings.cat2 (Core.unName p) tcoSuffix)) params
tcoVarRenames = Maps.fromList (Lists.zip params snapshotNames)
snapshotDecls =
Lists.map (\pair -> Utils.finalVarDeclarationStatement (Utils.variableToJavaIdentifier (Pairs.second pair)) (Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier (Pairs.first pair)))) (Lists.zip params snapshotNames)
tcoBody =
Logic.ifElse (Lists.null bindings) annotatedBody (Core.TermLet (Core.Let {
Core.letBindings = bindings,
Core.letBody = annotatedBody}))
in (Eithers.bind (encodeTermTCO env2WithTypeParams name params tcoVarRenames 0 tcoBody cx g) (\tcoStmts ->
let whileBodyStmts = Lists.concat2 snapshotDecls tcoStmts
whileBodyBlock =
Syntax.StatementWithoutTrailing (Syntax.StatementWithoutTrailingSubstatementBlock (Syntax.Block whileBodyStmts))
noCond = Nothing
whileStmt =
Syntax.BlockStatementStatement (Syntax.StatementWhile (Syntax.WhileStatement {
Syntax.whileStatementCond = noCond,
Syntax.whileStatementBody = whileBodyBlock}))
in (Right [
whileStmt])))) (Eithers.bind (encodeTerm env3 annotatedBody cx g) (\jbody ->
let returnSt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jbody))
in (Right (Lists.concat2 bindingStmts [
returnSt]))))) (\methodBody ->
let imdMember = Utils.interfaceMethodDeclaration mods jparams jname jformalParams result (Just methodBody)
in (Right (Optionals.cases mDoc (noInterfaceComment imdMember) (\doc -> withInterfaceCommentString doc imdMember))))))))))))))))))
encodeTermInternal :: JavaEnvironment.JavaEnvironment -> [M.Map Core.Name Core.Term] -> [Syntax.Type] -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeTermInternal env anns tyapps term cx g0 =
let aliases = JavaEnvironment.javaEnvironmentAliases env
g = JavaEnvironment.javaEnvironmentGraph env
encode = \t -> encodeTerm env t cx g
in case term of
Core.TermAnnotated v0 -> encodeTermInternal env (Lists.cons (Annotations.getAnnotationMap (Core.annotatedTermAnnotation v0)) anns) tyapps (Core.annotatedTermBody v0) cx g
Core.TermApplication v0 -> encodeApplication env v0 cx g
Core.TermEither v0 -> Eithers.bind (Logic.ifElse (Lists.null tyapps) (Right Nothing) (Eithers.bind (takeTypeArgs "either" 2 tyapps cx g) (\ta -> Right (Just ta)))) (\mtargs ->
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mEitherType ->
let branchTypes =
Optionals.bind mEitherType (\etyp -> case (Strip.deannotateType etyp) of
Core.TypeEither v1 -> Just (Core.eitherTypeLeft v1, (Core.eitherTypeRight v1))
_ -> Nothing)
encodeWithType =
\branchType -> \t1 ->
let annotated = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ branchType)) t1
in (encodeTermInternal env anns [] annotated cx g)
eitherCall =
\methodName -> \expr -> Optionals.cases mtargs (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.Either") (Syntax.Identifier methodName) [
expr])) (\targs -> Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.Either") (Syntax.Identifier methodName) targs [
expr]))
in (Eithers.either (\term1 -> Eithers.bind (Optionals.cases branchTypes (encode term1) (\bt -> encodeWithType (Pairs.first bt) term1)) (\expr -> Right (eitherCall "left" expr))) (\term1 -> Eithers.bind (Optionals.cases branchTypes (encode term1) (\bt -> encodeWithType (Pairs.second bt) term1)) (\expr -> Right (eitherCall "right" expr))) v0))))
Core.TermLambda _ -> encodeFunctionFormTerm env anns term cx g
Core.TermProject _ -> encodeFunctionFormTerm env anns term cx g
Core.TermCases _ -> encodeFunctionFormTerm env anns term cx g
Core.TermUnwrap _ -> encodeFunctionFormTerm env anns term cx g
Core.TermLet v0 ->
let bindings = Core.letBindings v0
body = Core.letBody v0
in (Logic.ifElse (Lists.null bindings) (encodeTermInternal env anns [] body cx g) (Eithers.bind (bindingsToStatements env bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env2 = Pairs.second bindResult
in (Eithers.bind (encodeTermInternal env2 anns [] body cx g) (\jbody ->
let returnSt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jbody))
block = Syntax.Block (Lists.concat2 bindingStmts [
returnSt])
nullaryLambda =
Syntax.ExpressionLambda (Syntax.LambdaExpression {
Syntax.lambdaExpressionParameters = (Syntax.LambdaParametersTuple []),
Syntax.lambdaExpressionBody = (Syntax.LambdaBodyBlock block)})
combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
g2 = JavaEnvironment.javaEnvironmentGraph env2
aliases2 = JavaEnvironment.javaEnvironmentAliases env2
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mt -> Eithers.bind (Optionals.cases mt (Checking.typeOfTerm cx g2 body) (\t -> Right t)) (\letType -> Eithers.bind (encodeType aliases2 Sets.empty letType cx g) (\jLetType -> Eithers.bind (Utils.javaTypeToJavaReferenceType jLetType cx) (\rt ->
let supplierRt =
Syntax.ReferenceTypeClassOrInterface (Syntax.ClassOrInterfaceTypeClass (Utils.javaClassType [
rt] JavaNames.javaUtilFunctionPackageName "Supplier"))
castExpr =
Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression supplierRt (Utils.javaExpressionToJavaUnaryExpression nullaryLambda))
in (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation (Just (Right (Utils.javaExpressionToJavaPrimary castExpr))) (Syntax.Identifier "get") [])))))))))))))
Core.TermList v0 -> Logic.ifElse (Lists.null v0) (Logic.ifElse (Lists.null tyapps) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.ConsList") (Syntax.Identifier "empty") []))) (Eithers.bind (takeTypeArgs "list" 1 tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.ConsList") (Syntax.Identifier "empty") targs []))))) (Eithers.bind (Eithers.mapList encode v0) (\jels -> Eithers.bind (collectionTypeArgs "list" 1 aliases anns tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.ConsList") (Syntax.Identifier "of") targs jels)))))
Core.TermLiteral v0 -> Right (encodeLiteral v0)
Core.TermMap v0 -> Logic.ifElse (Maps.null v0) (Logic.ifElse (Lists.null tyapps) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.PersistentMap") (Syntax.Identifier "empty") []))) (Eithers.bind (takeTypeArgs "map" 2 tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.PersistentMap") (Syntax.Identifier "empty") targs []))))) (Eithers.bind (Eithers.mapList encode (Maps.keys v0)) (\jkeys -> Eithers.bind (Eithers.mapList encode (Maps.elems v0)) (\jvals ->
let pairExprs =
Lists.map (\kv -> Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "java.util.Map") (Syntax.Identifier "entry") [
Pairs.first kv,
(Pairs.second kv)])) (Lists.zip jkeys jvals)
in (Eithers.bind (collectionTypeArgs "map" 2 aliases anns tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.PersistentMap") (Syntax.Identifier "ofEntries") targs pairExprs)))))))
Core.TermOptional v0 -> Optionals.cases v0 (Logic.ifElse (Lists.null tyapps) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.Optional") (Syntax.Identifier "none") []))) (Eithers.bind (takeTypeArgs "optional" 1 tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.Optional") (Syntax.Identifier "none") targs []))))) (\term1 -> Eithers.bind (encode term1) (\expr -> Eithers.bind (collectionTypeArgs "optional" 1 aliases anns tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.Optional") (Syntax.Identifier "given") targs [
expr])))))
Core.TermPair v0 -> Eithers.bind (encode (Pairs.first v0)) (\jterm1 -> Eithers.bind (encode (Pairs.second v0)) (\jterm2 -> Eithers.bind (Logic.ifElse (Lists.null tyapps) (Right Nothing) (Eithers.bind (Eithers.mapList (\jt -> Utils.javaTypeToJavaReferenceType jt cx) tyapps) (\rts -> Right (Just (Syntax.TypeArgumentsOrDiamondArguments (Lists.map (\rt -> Syntax.TypeArgumentReference rt) rts)))))) (\mtargs -> Right (Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "hydra.overlay.java.util.Pair") mtargs) [
jterm1,
jterm2] Nothing))))
Core.TermRecord v0 ->
let recName = Core.recordTypeName v0
mRecordType = Eithers.either (\_ -> Nothing) (\t -> Just t) (Resolution.requireType cx g recName)
strippedRecTyp = Optionals.map (\recTyp -> stripForalls (Strip.deannotateType recTyp)) mRecordType
mFieldTypeMap =
Optionals.bind strippedRecTyp (\bodyTyp -> case bodyTyp of
Core.TypeRecord v1 -> Just (Maps.fromList (Lists.map (\ft -> (Core.fieldTypeName ft, (Core.fieldTypeType ft))) v1))
_ -> Nothing)
combinedAnnsRec = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnnsRec)) (\mAnnotType ->
let mTypeSubst =
Optionals.bind mAnnotType (\annTyp -> Optionals.bind mRecordType (\recTyp ->
let args = extractTypeApplicationArgs (Strip.deannotateType annTyp)
params = collectForallParams (Strip.deannotateType recTyp)
in (Logic.ifElse (Logic.or (Lists.null args) (Logic.not (Equality.equal (Lists.length args) (Lists.length params)))) Nothing (Just (Maps.fromList (Lists.zip params args))))))
encodeField =
\fld -> Optionals.cases mFieldTypeMap (encode (Core.fieldTerm fld)) (\ftmap ->
let mftyp = Maps.lookup (Core.fieldName fld) ftmap
in (Optionals.cases mftyp (encode (Core.fieldTerm fld)) (\ftyp ->
let resolvedType = Optionals.cases mTypeSubst ftyp (\subst -> applySubstFull subst ftyp)
annotatedFieldTerm =
Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ resolvedType)) (Core.fieldTerm fld)
in (encodeTermInternal env anns [] annotatedFieldTerm cx g))))
in (Eithers.bind (Eithers.mapList encodeField (Core.recordFields v0)) (\fieldExprs ->
let consId = Utils.nameToJavaName aliases recName
in (Eithers.bind (Logic.ifElse (Logic.not (Lists.null tyapps)) (Eithers.bind (Eithers.mapList (\jt -> Utils.javaTypeToJavaReferenceType jt cx) tyapps) (\rts -> Right (Just (Syntax.TypeArgumentsOrDiamondArguments (Lists.map (\rt -> Syntax.TypeArgumentReference rt) rts))))) (
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mtyp -> Optionals.cases mtyp (Right Nothing) (\annTyp ->
let typeArgs = extractTypeApplicationArgs (Strip.deannotateType annTyp)
in (Logic.ifElse (Lists.null typeArgs) (Right Nothing) (Eithers.bind (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Utils.javaTypeToJavaReferenceType jt cx)) typeArgs) (\jTypeArgs -> Right (Just (Syntax.TypeArgumentsOrDiamondArguments (Lists.map (\rt -> Syntax.TypeArgumentReference rt) jTypeArgs))))))))))) (\mtargs -> Right (Utils.javaConstructorCall (Utils.javaConstructorName consId mtargs) fieldExprs Nothing)))))))
Core.TermSet v0 -> Logic.ifElse (Sets.null v0) (Logic.ifElse (Lists.null tyapps) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStatic (Syntax.Identifier "hydra.overlay.java.util.PersistentSet") (Syntax.Identifier "empty") []))) (Eithers.bind (takeTypeArgs "set" 1 tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.PersistentSet") (Syntax.Identifier "empty") targs []))))) (
let slist = Sets.toList v0
in (Eithers.bind (Eithers.mapList encode slist) (\jels -> Eithers.bind (collectionTypeArgs "set" 1 aliases anns tyapps cx g) (\targs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.PersistentSet") (Syntax.Identifier "of") targs jels))))))
Core.TermTypeLambda v0 -> withTypeLambda env v0 (\env2 ->
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mtyp ->
let annotatedBody =
Optionals.cases mtyp (Core.typeLambdaBody v0) (\t -> case t of
Core.TypeForall v1 -> Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ (Core.forallTypeBody v1))) (Core.typeLambdaBody v0)
_ -> Core.typeLambdaBody v0)
in (encodeTerm env2 annotatedBody cx g))))
Core.TermInject v0 ->
let injTypeName = Core.injectionTypeName v0
injField = Core.injectionField v0
injFieldName = Core.fieldName injField
injFieldTerm = Core.fieldTerm injField
typeId = Syntax.unIdentifier (Utils.nameToJavaName aliases injTypeName)
consId =
Syntax.Identifier (Strings.cat [
typeId,
".",
(Utils.sanitizeJavaName (Formatting.capitalize (Core.unName injFieldName)))])
in (Eithers.bind (isFieldUnitType injTypeName injFieldName cx g) (\fieldIsUnit -> Eithers.bind (Logic.ifElse (Logic.or (Predicates.isUnitTerm (Strip.deannotateTerm injFieldTerm)) fieldIsUnit) (Right []) (Eithers.bind (encode injFieldTerm) (\ex -> Right [
ex]))) (\args -> Right (Utils.javaConstructorCall (Utils.javaConstructorName consId Nothing) args Nothing))))
Core.TermVariable v0 -> Optionals.cases (Maps.lookup v0 (Graph.graphPrimitives g)) (encodeVariable env v0 cx g) (\_ ->
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mt -> Eithers.bind (Optionals.cases mt (Checking.typeOfTerm cx g term) (\t -> Right t)) (\typ -> case (Strip.deannotateType typ) of
Core.TypeFunction v1 -> encodeFunctionPrimitiveByName env (Core.functionTypeDomain v1) (Core.functionTypeCodomain v1) v0 cx g
_ -> encodeNullaryPrimitiveByName env typ v0 cx g))))
Core.TermUnit -> Right (Utils.javaLiteralToJavaExpression Syntax.LiteralNull)
Core.TermWrap v0 -> Eithers.bind (encode (Core.wrappedTermBody v0)) (\jarg -> Right (Utils.javaConstructorCall (Utils.javaConstructorName (Utils.nameToJavaName aliases (Core.wrappedTermTypeName v0)) Nothing) [
jarg] Nothing))
Core.TermTypeApplication v0 ->
let atyp = Core.typeApplicationTermType v0
body = Core.typeApplicationTermBody v0
in (Eithers.bind (encodeType aliases Sets.empty atyp cx g) (\jatyp ->
let combinedAnns = Lists.foldl (\acc -> \m -> Maps.union acc m) Maps.empty anns
in (Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g combinedAnns)) (\mtyp -> Eithers.bind (Optionals.cases mtyp (Checking.typeOfTerm cx g term) (\t -> Right t)) (\typ ->
let collected0 = collectTypeApps0 body [
atyp]
innermostBody0 = Pairs.first collected0
allTypeArgs0 = Pairs.second collected0
in (Eithers.bind (correctCastType innermostBody0 allTypeArgs0 typ cx g) (\correctedTyp ->
let collected = collectTypeApps body [
atyp]
innermostBody = Pairs.first collected
allTypeArgs = Pairs.second collected
in case innermostBody of
Core.TermVariable v1 -> Eithers.bind (classifyDataReference v1 cx g) (\cls -> typeAppNullaryOrHoisted env aliases anns tyapps jatyp body correctedTyp v1 cls allTypeArgs cx g)
Core.TermEither v1 -> Logic.ifElse (Equality.equal (Lists.length allTypeArgs) 2) (
let eitherBranchTypes =
(
Optionals.fromOptional correctedTyp (Lists.maybeAt 0 allTypeArgs),
(Optionals.fromOptional correctedTyp (Lists.maybeAt 1 allTypeArgs)))
in (Eithers.bind (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Utils.javaTypeToJavaReferenceType jt cx)) allTypeArgs) (\jTypeArgs ->
let eitherTargs = Lists.map (\rt -> Syntax.TypeArgumentReference rt) jTypeArgs
encodeEitherBranch =
\branchType -> \t1 ->
let annotated = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ branchType)) t1
in (encodeTermInternal env anns [] annotated cx g)
in (Eithers.either (\term1 -> Eithers.bind (encodeEitherBranch (Pairs.first eitherBranchTypes) term1) (\expr -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.Either") (Syntax.Identifier "left") eitherTargs [
expr])))) (\term1 -> Eithers.bind (encodeEitherBranch (Pairs.second eitherBranchTypes) term1) (\expr -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs (Syntax.Identifier "hydra.overlay.java.util.Either") (Syntax.Identifier "right") eitherTargs [
expr])))) v1)))) (typeAppFallbackCast env aliases anns tyapps jatyp body correctedTyp cx g)
_ -> typeAppFallbackCast env aliases anns tyapps jatyp body correctedTyp cx g)))))))
_ -> Right (encodeLiteral (Core.LiteralString "Unimplemented term variant"))
encodeTermTCO :: JavaEnvironment.JavaEnvironment -> Core.Name -> [Core.Name] -> M.Map Core.Name Core.Name -> Int -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error [Syntax.BlockStatement]
encodeTermTCO env0 funcName paramNames tcoVarRenames tcoDepth term cx g =
let aliases0 = JavaEnvironment.javaEnvironmentAliases env0
env =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = JavaEnvironment.Aliases {
JavaEnvironment.aliasesCurrentNamespace = (JavaEnvironment.aliasesCurrentNamespace aliases0),
JavaEnvironment.aliasesPackages = (JavaEnvironment.aliasesPackages aliases0),
JavaEnvironment.aliasesBranchVars = (JavaEnvironment.aliasesBranchVars aliases0),
JavaEnvironment.aliasesRecursiveVars = (JavaEnvironment.aliasesRecursiveVars aliases0),
JavaEnvironment.aliasesInScopeTypeParams = (JavaEnvironment.aliasesInScopeTypeParams aliases0),
JavaEnvironment.aliasesPolymorphicLocals = (JavaEnvironment.aliasesPolymorphicLocals aliases0),
JavaEnvironment.aliasesInScopeJavaVars = (JavaEnvironment.aliasesInScopeJavaVars aliases0),
JavaEnvironment.aliasesVarRenames = (Maps.union tcoVarRenames (JavaEnvironment.aliasesVarRenames aliases0)),
JavaEnvironment.aliasesLambdaVars = (JavaEnvironment.aliasesLambdaVars aliases0),
JavaEnvironment.aliasesTypeVarSubst = (JavaEnvironment.aliasesTypeVarSubst aliases0),
JavaEnvironment.aliasesTrustedTypeVars = (JavaEnvironment.aliasesTrustedTypeVars aliases0),
JavaEnvironment.aliasesMethodCodomain = (JavaEnvironment.aliasesMethodCodomain aliases0),
JavaEnvironment.aliasesThunkedVars = (JavaEnvironment.aliasesThunkedVars aliases0)},
JavaEnvironment.javaEnvironmentGraph = (JavaEnvironment.javaEnvironmentGraph env0)}
stripped = Strip.deannotateAndDetypeTerm term
gathered = Analysis.gatherApplications stripped
gatherArgs = Pairs.first gathered
gatherFun = Pairs.second gathered
strippedFun = Strip.deannotateAndDetypeTerm gatherFun
isSelfCall =
case strippedFun of
Core.TermVariable v0 -> Equality.equal v0 funcName
_ -> False
in (Logic.ifElse (Logic.and isSelfCall (Equality.equal (Lists.length gatherArgs) (Lists.length paramNames))) (
let changePairs =
Lists.filter (\pair -> Logic.not (case (Strip.deannotateAndDetypeTerm (Pairs.second pair)) of
Core.TermVariable v0 -> Equality.equal v0 (Pairs.first pair)
_ -> False)) (Lists.zip paramNames gatherArgs)
changedParams = Lists.map Pairs.first changePairs
in (Eithers.bind (Eithers.mapList (\pair -> encodeTerm env (Pairs.second pair) cx g) changePairs) (\jChangedArgs ->
let assignments =
Lists.map (\pair ->
let paramName = Pairs.first pair
jArg = Pairs.second pair
in (Syntax.BlockStatementStatement (Utils.javaAssignmentStatement (Syntax.LeftHandSideExpressionName (Utils.javaIdentifierToJavaExpressionName (Utils.variableToJavaIdentifier paramName))) jArg))) (Lists.zip changedParams jChangedArgs)
continueStmt =
Syntax.BlockStatementStatement (Syntax.StatementWithoutTrailing (Syntax.StatementWithoutTrailingSubstatementContinue (Syntax.ContinueStatement Nothing)))
in (Right (Lists.concat2 assignments [
continueStmt]))))) (case stripped of
Core.TermLet v0 ->
let letBindings = Core.letBindings v0
letBody = Core.letBody v0
in (Eithers.bind (bindingsToStatements env letBindings cx g) (\bindResult ->
let letStmts = Pairs.first bindResult
envAfterLet = Pairs.second bindResult
in (Eithers.bind (encodeTermTCO envAfterLet funcName paramNames tcoVarRenames tcoDepth letBody cx g) (\tcoBodyStmts -> Right (Lists.concat2 letStmts tcoBodyStmts)))))
_ ->
let gathered2 = Analysis.gatherApplications term
args2 = Pairs.first gathered2
body2 = Pairs.second gathered2
in (Logic.ifElse (Equality.equal (Lists.length args2) 1) (
let arg = Optionals.fromOptional Core.TermUnit (Lists.maybeHead args2)
in case (Strip.deannotateAndDetypeTerm body2) of
Core.TermCases v0 ->
let aliases = JavaEnvironment.javaEnvironmentAliases env
tname = Core.caseStatementTypeName v0
dflt = Core.caseStatementDefault v0
cases_ = Core.caseStatementCases v0
in (Eithers.bind (domTypeArgs aliases (Resolution.nominalApplication tname []) cx g) (\domArgs -> Eithers.bind (encodeTerm env arg cx g) (\jArgRaw ->
let depthSuffix = Logic.ifElse (Equality.equal tcoDepth 0) "" (Literals.showInt32 tcoDepth)
matchVarId =
Utils.javaIdentifier (Strings.cat [
"_tco_match_",
(Formatting.decapitalize (Names.localNameOf tname)),
depthSuffix])
matchDecl = Utils.varDeclarationStatement matchVarId jArgRaw
jArg = Utils.javaIdentifierToJavaExpression matchVarId
in (Eithers.bind (Eithers.mapList (\field ->
let fieldName = Core.caseAlternativeName field
variantRefType =
Utils.nameToJavaReferenceType aliases True domArgs tname (Just (Formatting.capitalize (Core.unName fieldName)))
in case (Strip.deannotateTerm (Core.caseAlternativeHandler field)) of
Core.TermLambda v1 -> withLambda env v1 (\env2 ->
let lambdaParam = Core.lambdaParameter v1
branchBody = Core.lambdaBody v1
env3 = insertBranchVar lambdaParam env2
varId = Utils.variableToJavaIdentifier lambdaParam
castExpr =
Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression variantRefType (Utils.javaExpressionToJavaUnaryExpression jArg))
localDecl = Utils.varDeclarationStatement varId castExpr
isBranchTailCall = Analysis.isTailRecursiveInTailPosition funcName branchBody
in (Eithers.bind (Logic.ifElse isBranchTailCall (encodeTermTCO env3 funcName paramNames tcoVarRenames (Math.add tcoDepth 1) branchBody cx g) (Eithers.bind (analyzeJavaFunction env3 branchBody cx g) (\fs ->
let bindings = Typing.functionStructureBindings fs
innerBody = Typing.functionStructureBody fs
env4 = Typing.functionStructureEnvironment fs
in (Eithers.bind (bindingsToStatements env4 bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env5 = Pairs.second bindResult
in (Eithers.bind (encodeTerm env5 innerBody cx g) (\jret ->
let returnStmt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jret))
in (Right (Lists.concat2 bindingStmts [
returnStmt]))))))))) (\bodyStmts ->
let relExpr =
Utils.javaInstanceOf (Utils.javaUnaryExpressionToJavaRelationalExpression (Utils.javaExpressionToJavaUnaryExpression jArg)) variantRefType
condExpr = Utils.javaRelationalExpressionToJavaExpression relExpr
blockStmts = Lists.cons localDecl bodyStmts
ifBody = Syntax.StatementWithoutTrailing (Syntax.StatementWithoutTrailingSubstatementBlock (Syntax.Block blockStmts))
in (Right (Syntax.BlockStatementStatement (Syntax.StatementIfThen (Syntax.IfThenStatement {
Syntax.ifThenStatementExpression = condExpr,
Syntax.ifThenStatementStatement = ifBody})))))))
_ -> Left (Errors.ErrorOther (Errors.OtherError "TCO: case branch is not a lambda"))) cases_) (\ifBlocks -> Eithers.bind (Optionals.cases dflt (Right [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jArg))]) (\d -> Eithers.bind (encodeTerm env d cx g) (\dExpr -> Right [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just dExpr))]))) (\defaultStmt -> Right (Lists.concat [
[
matchDecl],
ifBlocks,
defaultStmt])))))))
_ -> Eithers.bind (encodeTerm env term cx g) (\expr -> Right [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just expr))])) (Eithers.bind (encodeTerm env term cx g) (\expr -> Right [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just expr))])))))
encodeType :: JavaEnvironment.Aliases -> S.Set Core.Name -> Core.Type -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Type
encodeType aliases boundVars t cx g =
let inScopeTypeParams = JavaEnvironment.aliasesInScopeTypeParams aliases
typeVarSubst = JavaEnvironment.aliasesTypeVarSubst aliases
in case (Strip.deannotateType t) of
Core.TypeApplication v0 -> Eithers.bind (encodeType aliases boundVars (Core.applicationTypeFunction v0) cx g) (\jlhs -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.applicationTypeArgument v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jrhs -> Utils.addJavaTypeParameter jrhs jlhs cx))
Core.TypeFunction v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.functionTypeDomain v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jdom -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.functionTypeCodomain v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jcod -> Right (Utils.javaRefType [
jdom,
jcod] JavaNames.javaUtilFunctionPackageName "Function")))
Core.TypeForall v0 -> Eithers.bind (encodeType aliases (Sets.insert (Core.forallTypeParameter v0) boundVars) (Core.forallTypeBody v0) cx g) (\jbody -> Utils.addJavaTypeParameter (Utils.javaTypeVariable (Core.unName (Core.forallTypeParameter v0))) jbody cx)
Core.TypeList v0 -> Eithers.bind (encodeType aliases boundVars v0 cx g) (\jet -> Eithers.bind (Eithers.bind (Right jet) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\rt -> Right (Utils.javaRefType [
rt] JavaNames.javaUtilPackageName "List")))
Core.TypeEffect v0 -> encodeType aliases boundVars v0 cx g
Core.TypeLiteral v0 -> encodeLiteralType v0 cx g
Core.TypeEither v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.eitherTypeLeft v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jlt -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.eitherTypeRight v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jrt -> Right (Utils.javaRefType [
jlt,
jrt] JavaNames.hydraUtilPackageName "Either")))
Core.TypeMap v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.mapTypeKeys v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jkt -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.mapTypeValues v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jvt -> Right (Utils.javaRefType [
jkt,
jvt] JavaNames.javaUtilPackageName "Map")))
Core.TypePair v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.pairTypeFirst v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jfirst -> Eithers.bind (Eithers.bind (encodeType aliases boundVars (Core.pairTypeSecond v0) cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jsecond -> Right (Utils.javaRefType [
jfirst,
jsecond] JavaNames.hydraUtilPackageName "Pair")))
Core.TypeUnit -> Right (Utils.javaRefType [] JavaNames.javaLangPackageName "Void")
Core.TypeRecord v0 -> Logic.ifElse (Lists.null v0) (Right (Utils.javaRefType [] JavaNames.javaLangPackageName "Void")) (Left (Errors.ErrorOther (Errors.OtherError "unexpected anonymous record type")))
Core.TypeOptional v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars v0 cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jot -> Right (Utils.javaRefType [
jot] JavaNames.hydraUtilPackageName "Optional"))
Core.TypeSet v0 -> Eithers.bind (Eithers.bind (encodeType aliases boundVars v0 cx g) (\jt_ -> Utils.javaTypeToJavaReferenceType jt_ cx)) (\jst -> Right (Utils.javaRefType [
jst] JavaNames.javaUtilPackageName "Set"))
Core.TypeUnion _ -> Left (Errors.ErrorOther (Errors.OtherError "unexpected anonymous union type"))
Core.TypeVariable v0 ->
let name = Optionals.fromOptional v0 (Maps.lookup v0 typeVarSubst)
in (Eithers.bind (encodeType_resolveIfTypedef aliases boundVars inScopeTypeParams name cx g) (\resolved -> Optionals.cases resolved (Right (Logic.ifElse (Logic.or (Sets.member name boundVars) (Sets.member name inScopeTypeParams)) (Syntax.TypeReference (Utils.javaTypeVariable (Core.unName name))) (Logic.ifElse (isLambdaBoundVariable name) (Syntax.TypeReference (Utils.javaTypeVariable (Core.unName name))) (Logic.ifElse (isUnresolvedInferenceVar name) (Syntax.TypeReference (Syntax.ReferenceTypeClassOrInterface (Syntax.ClassOrInterfaceTypeClass (Utils.javaClassType [] JavaNames.javaLangPackageName "Object")))) (Syntax.TypeReference (Utils.nameToJavaReferenceType aliases True [] name Nothing)))))) (\resolvedType -> encodeType aliases boundVars resolvedType cx g)))
Core.TypeWrap _ -> Left (Errors.ErrorOther (Errors.OtherError "unexpected anonymous wrap type"))
_ -> Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "can't encode unsupported type in Java: " (ShowCore.type_ t))))
encodeTypeDefinition :: Syntax.PackageDeclaration -> JavaEnvironment.Aliases -> Packaging.TypeDefinition -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error (Core.Name, Syntax.CompilationUnit)
encodeTypeDefinition pkg aliases tdef cx g =
let name = Packaging.typeDefinitionName tdef
typ = Core.typeSchemeBody (Packaging.typeDefinitionBody tdef)
serializable = isSerializableJavaType typ
imports =
Logic.ifElse serializable [
Syntax.ImportDeclarationSingleType (Syntax.SingleTypeImportDeclaration (Utils.javaTypeName (Syntax.Identifier "java.io.Serializable")))] []
in (Eithers.bind (toClassDecl False serializable aliases [] name typ cx g) (\decl -> Eithers.bind (Annotations.getTypeDescription cx g typ) (\comment ->
let tdecl =
Syntax.TopLevelClassOrInterfaceDeclarationWithComments {
Syntax.topLevelClassOrInterfaceDeclarationWithCommentsValue = (Syntax.TopLevelClassOrInterfaceDeclarationClass decl),
Syntax.topLevelClassOrInterfaceDeclarationWithCommentsComments = comment}
in (Right (
name,
(Syntax.CompilationUnitOrdinary (Syntax.OrdinaryCompilationUnit {
Syntax.ordinaryCompilationUnitPackage = (Just pkg),
Syntax.ordinaryCompilationUnitImports = imports,
Syntax.ordinaryCompilationUnitTypes = [
tdecl]})))))))
encodeType_resolveIfTypedef :: t0 -> S.Set Core.Name -> S.Set Core.Name -> Core.Name -> t1 -> Graph.Graph -> Either t2 (Maybe Core.Type)
encodeType_resolveIfTypedef aliases boundVars inScopeTypeParams name cx g =
Logic.ifElse (Logic.or (Sets.member name boundVars) (Sets.member name inScopeTypeParams)) (Right Nothing) (Logic.ifElse (isLambdaBoundVariable name) (Right Nothing) (
let schemaTypes = Graph.graphSchemaTypes g
in (Optionals.cases (Maps.lookup name schemaTypes) (Right Nothing) (\ts -> Logic.ifElse (Logic.not (Lists.null (Core.typeSchemeVariables ts))) (Right Nothing) (case (Strip.deannotateType (Core.typeSchemeBody ts)) of
Core.TypeRecord _ -> Right Nothing
Core.TypeUnion _ -> Right Nothing
Core.TypeWrap _ -> Right Nothing
_ -> Right (Just (Core.typeSchemeBody ts)))))))
encodeVariable :: JavaEnvironment.JavaEnvironment -> Core.Name -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeVariable env name cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
resolvedName = Utils.lookupJavaVarName aliases name
jid = Utils.javaIdentifier (Core.unName resolvedName)
in (Logic.ifElse (Sets.member name (JavaEnvironment.aliasesBranchVars aliases)) (Right (Utils.javaFieldAccessToJavaExpression (Syntax.FieldAccess {
Syntax.fieldAccessQualifier = (Syntax.FieldAccess_QualifierPrimary (Utils.javaExpressionToJavaPrimary (Utils.javaIdentifierToJavaExpression jid))),
Syntax.fieldAccessIdentifier = (Utils.javaIdentifier JavaNames.valueFieldName)}))) (Logic.ifElse (Logic.and (Equality.equal name (Core.Name (Strings.cat [
JavaNames.instanceName,
"_",
JavaNames.valueFieldName]))) (isRecursiveVariable aliases name)) (
let instanceExpr = Utils.javaIdentifierToJavaExpression (Utils.javaIdentifier JavaNames.instanceName)
in (Right (Utils.javaFieldAccessToJavaExpression (Syntax.FieldAccess {
Syntax.fieldAccessQualifier = (Syntax.FieldAccess_QualifierPrimary (Utils.javaExpressionToJavaPrimary instanceExpr)),
Syntax.fieldAccessIdentifier = (Utils.javaIdentifier JavaNames.valueFieldName)})))) (Logic.ifElse (Logic.and (isRecursiveVariable aliases name) (Logic.not (isLambdaBoundIn name (JavaEnvironment.aliasesLambdaVars aliases)))) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation (Just (Left (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = jid}))) (Syntax.Identifier JavaNames.getMethodName) []))) (Logic.ifElse (Logic.and (Sets.member name (JavaEnvironment.aliasesThunkedVars aliases)) (Logic.not (isLambdaBoundIn name (JavaEnvironment.aliasesLambdaVars aliases)))) (Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation (Just (Left (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = jid}))) (Syntax.Identifier JavaNames.getMethodName) []))) (Logic.ifElse (isLambdaBoundIn name (JavaEnvironment.aliasesLambdaVars aliases)) (
let actualName = findMatchingLambdaVar name (JavaEnvironment.aliasesLambdaVars aliases)
resolvedActual = Utils.lookupJavaVarName aliases actualName
in (Right (Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier resolvedActual)))) (Logic.ifElse (Sets.member name (JavaEnvironment.aliasesInScopeJavaVars aliases)) (Right (Utils.javaIdentifierToJavaExpression (elementJavaIdentifier False False aliases resolvedName))) (Eithers.bind (classifyDataReference name cx g) (\cls -> case cls of
JavaEnvironment.JavaSymbolClassHoistedLambda v0 -> encodeVariable_hoistedLambdaCase aliases name v0 cx g
JavaEnvironment.JavaSymbolClassLocalVariable -> Right (Utils.javaIdentifierToJavaExpression (elementJavaIdentifier False False aliases resolvedName))
JavaEnvironment.JavaSymbolClassConstant -> Right (Utils.javaIdentifierToJavaExpression (elementJavaIdentifier False False aliases name))
JavaEnvironment.JavaSymbolClassNullaryFunction -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation Nothing (elementJavaIdentifier False False aliases name) []))
JavaEnvironment.JavaSymbolClassUnaryFunction -> Right (Utils.javaIdentifierToJavaExpression (elementJavaIdentifier False True aliases name))))))))))
encodeVariable_buildCurried :: [Core.Name] -> Syntax.Expression -> Syntax.Expression
encodeVariable_buildCurried params inner =
Optionals.fromOptional inner (Optionals.map (\p -> Utils.javaLambda (Pairs.first p) (encodeVariable_buildCurried (Pairs.second p) inner)) (Lists.uncons params))
encodeVariable_hoistedLambdaCase :: JavaEnvironment.Aliases -> Core.Name -> Int -> t0 -> Graph.Graph -> Either Errors.Error Syntax.Expression
encodeVariable_hoistedLambdaCase aliases name arity cx g =
let paramNames = Lists.map (\i -> Core.Name (Strings.cat2 "p" (Literals.showInt32 i))) (Math.range 0 (Math.sub arity 1))
paramExprs = Lists.map (\pn -> Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier pn)) paramNames
call =
Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation Nothing (elementJavaIdentifier False False aliases name) paramExprs)
lam = encodeVariable_buildCurried paramNames call
in (Eithers.bind (Right (Lexical.lookupBinding g name)) (\mel -> Optionals.cases mel (Right lam) (\el -> Optionals.cases (Core.bindingTypeScheme el) (Right lam) (\ts ->
let typ = Core.typeSchemeBody ts
in (Eithers.bind (encodeType aliases Sets.empty typ cx g) (\jtype -> Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt -> Right (Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression rt (Utils.javaExpressionToJavaUnaryExpression lam))))))))))
eqClause :: String -> Core.FieldType -> Syntax.InclusiveOrExpression
eqClause tmpName ft =
let fname = Core.unName (Core.fieldTypeName ft)
ftype = Core.fieldTypeType ft
in (Logic.ifElse (isBinaryType ftype) (arraysEqualsClause tmpName fname) (Logic.ifElse (isBigNumericType ftype) (compareToZeroClause tmpName fname) (equalsClause tmpName fname)))
equalsClause :: String -> String -> Syntax.InclusiveOrExpression
equalsClause tmpName fname =
let thisArg =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Syntax.Identifier "this") (Utils.javaIdentifier fname))
otherArg =
Utils.javaExpressionNameToJavaExpression (Utils.fieldExpression (Utils.javaIdentifier tmpName) (Utils.javaIdentifier fname))
header =
Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantType (Utils.javaTypeName (Syntax.Identifier "java.util.Objects"))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.equalsMethodName)})
in (Utils.javaPostfixExpressionToJavaInclusiveOrExpression (Utils.javaMethodInvocationToJavaPostfixExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = [
thisArg,
otherArg]})))
extractArgType :: t0 -> Core.Type -> Core.Type
extractArgType _lhs typ =
case typ of
Core.TypeApplication v0 -> case (Core.applicationTypeFunction v0) of
Core.TypeApplication _ -> Core.applicationTypeArgument v0
_ -> typ
_ -> typ
extractDirectReturn :: S.Set Core.Name -> Core.Type -> [(Core.Name, Core.Name)]
extractDirectReturn tparamSet t = extractDirectReturn_go tparamSet t
extractDirectReturn_go :: S.Set Core.Name -> Core.Type -> [(Core.Name, Core.Name)]
extractDirectReturn_go tparamSet t =
case (Strip.deannotateType t) of
Core.TypeFunction v0 ->
let dom = Strip.deannotateType (Core.functionTypeDomain v0)
cod = Core.functionTypeCodomain v0
in case dom of
Core.TypeVariable v1 -> Logic.ifElse (Sets.member v1 tparamSet) (case (Strip.deannotateType cod) of
Core.TypeFunction v2 ->
let midArg = Strip.deannotateType (Core.functionTypeDomain v2)
retPart = Strip.deannotateType (Core.functionTypeCodomain v2)
in case midArg of
Core.TypeVariable v3 -> Logic.ifElse (Sets.member v3 tparamSet) [] (case retPart of
Core.TypeVariable v4 -> Logic.ifElse (Sets.member v4 tparamSet) [
(v1, v4)] []
_ -> [])
_ -> case retPart of
Core.TypeVariable v3 -> Logic.ifElse (Sets.member v3 tparamSet) [
(v1, v3)] []
_ -> []
_ -> []) (extractDirectReturn_go tparamSet cod)
_ -> extractDirectReturn_go tparamSet cod
_ -> []
extractInOutPair :: Core.Type -> [(Core.Name, Core.Name)]
extractInOutPair t =
case (Strip.deannotateType t) of
Core.TypeFunction v0 -> case (Strip.deannotateType (Core.functionTypeDomain v0)) of
Core.TypeVariable v1 ->
let retType = unwrapReturnType (Core.functionTypeCodomain v0)
in case (Strip.deannotateType retType) of
Core.TypePair v2 -> case (Strip.deannotateType (Core.pairTypeFirst v2)) of
Core.TypeVariable v3 -> [
(v1, v3)]
_ -> []
_ -> []
_ -> []
_ -> []
extractTypeApplicationArgs :: Core.Type -> [Core.Type]
extractTypeApplicationArgs typ = Lists.reverse (extractTypeApplicationArgs_go typ)
extractTypeApplicationArgs_go :: Core.Type -> [Core.Type]
extractTypeApplicationArgs_go t =
case t of
Core.TypeApplication v0 -> Lists.cons (Core.applicationTypeArgument v0) (extractTypeApplicationArgs_go (Core.applicationTypeFunction v0))
_ -> []
fieldTypeToFormalParam :: JavaEnvironment.Aliases -> Core.FieldType -> t0 -> Graph.Graph -> Either Errors.Error Syntax.FormalParameter
fieldTypeToFormalParam aliases ft cx g =
Eithers.bind (encodeType aliases Sets.empty (Core.fieldTypeType ft) cx g) (\jt -> Right (Utils.javaTypeToJavaFormalParameter jt (Core.fieldTypeName ft)))
filterByFlags :: [t0] -> [Bool] -> [t0]
filterByFlags xs flags = Lists.map (\p -> Pairs.first p) (Lists.filter (\p -> Pairs.second p) (Lists.zip xs flags))
filterPhantomTypeArgs :: Core.Name -> [Core.Type] -> t0 -> Graph.Graph -> Either t1 [Core.Type]
filterPhantomTypeArgs calleeName allTypeArgs cx g =
Eithers.bind (Right (Lexical.lookupBinding g calleeName)) (\mel -> Optionals.cases mel (Right allTypeArgs) (\el -> Optionals.cases (Core.bindingTypeScheme el) (Right allTypeArgs) (\ts ->
let schemeVars = Lists.filter (\v -> isSimpleName v) (Core.typeSchemeVariables ts)
schemeTypeVars = collectTypeVars (Core.typeSchemeBody ts)
schemeType = Core.typeSchemeBody ts
nParams = countFunctionParams schemeType
peeled = peelDomainTypes nParams schemeType
calleeDoms = Pairs.first peeled
calleeCod = Pairs.second peeled
overgenSubst = detectAccumulatorUnification calleeDoms calleeCod schemeVars
keepFlags = Lists.map (\v -> Logic.and (Sets.member v schemeTypeVars) (Logic.not (Maps.member v overgenSubst))) schemeVars
in (Logic.ifElse (Logic.not (Equality.equal (Lists.length schemeVars) (Lists.length allTypeArgs))) (Right allTypeArgs) (Right (filterPhantomTypeArgs_filterAndApply allTypeArgs keepFlags overgenSubst))))))
filterPhantomTypeArgs_filterAndApply :: [Core.Type] -> [Bool] -> M.Map Core.Name Core.Type -> [Core.Type]
filterPhantomTypeArgs_filterAndApply allTypeArgs keepFlags overgenSubst =
let filtered = Lists.map (\p -> Pairs.first p) (Lists.filter (\p -> Pairs.second p) (Lists.zip allTypeArgs keepFlags))
in (Logic.ifElse (Logic.not (Maps.null overgenSubst)) (Lists.map (\t -> substituteTypeVarsWithTypes overgenSubst t) filtered) filtered)
findMatchingLambdaVar :: Core.Name -> S.Set Core.Name -> Core.Name
findMatchingLambdaVar name lambdaVars =
Logic.ifElse (Sets.member name lambdaVars) name (Logic.ifElse (isLambdaBoundIn_isQualified name) (Optionals.fromOptional name (Lists.find (\lv -> Logic.and (isLambdaBoundIn_isQualified lv) (Equality.equal (Names.localNameOf lv) (Names.localNameOf name))) (Sets.toList lambdaVars))) (Logic.ifElse (Sets.member (Core.Name (Names.localNameOf name)) lambdaVars) (Core.Name (Names.localNameOf name)) name))
findPairFirst :: Core.Type -> Maybe Core.Name
findPairFirst t =
case (Strip.deannotateType t) of
Core.TypePair v0 -> case (Strip.deannotateType (Core.pairTypeFirst v0)) of
Core.TypeVariable v1 -> Just v1
_ -> Nothing
_ -> Nothing
findSelfRefVar :: (Eq t0, Ord t0) => (M.Map t0 [t0] -> Maybe t0)
findSelfRefVar grouped =
let selfRefs = Lists.filter (\entry -> Lists.elem (Pairs.first entry) (Pairs.second entry)) (Maps.toList grouped)
in (Optionals.map (\entry -> Pairs.first entry) (Lists.maybeHead selfRefs))
first20Primes :: [Integer]
first20Primes =
[
2,
3,
5,
7,
11,
13,
17,
19,
23,
29,
31,
37,
41,
43,
47,
53,
59,
61,
67,
71]
flattenApps :: Core.Term -> [Core.Term] -> ([Core.Term], Core.Term)
flattenApps t acc =
case (Strip.deannotateTerm t) of
Core.TermApplication v0 -> flattenApps (Core.applicationFunction v0) (Lists.cons (Core.applicationArgument v0) acc)
_ -> (acc, t)
flattenBindings :: [Core.Binding] -> [Core.Binding]
flattenBindings bindings =
Lists.bind bindings (\b -> case (Strip.deannotateTerm (Core.bindingTerm b)) of
Core.TermLet v0 -> Lists.concat2 (flattenBindings (Core.letBindings v0)) [
Core.Binding {
Core.bindingName = (Core.bindingName b),
Core.bindingTerm = (Core.letBody v0),
Core.bindingTypeScheme = (Core.bindingTypeScheme b)}]
_ -> [
b])
freshJavaName :: Core.Name -> S.Set Core.Name -> Core.Name
freshJavaName base avoid = freshJavaName_go base avoid 2
freshJavaName_go :: Core.Name -> S.Set Core.Name -> Int -> Core.Name
freshJavaName_go base avoid i =
let candidate = Core.Name (Strings.cat2 (Core.unName base) (Literals.showInt32 i))
in (Logic.ifElse (Sets.member candidate avoid) (freshJavaName_go base avoid (Math.add i 1)) candidate)
functionCall :: JavaEnvironment.JavaEnvironment -> Bool -> Core.Name -> [Core.Term] -> [Core.Type] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
functionCall env isPrim name args typeApps cx g =
let aliases = JavaEnvironment.javaEnvironmentAliases env
isLambdaBound = isLambdaBoundIn name (JavaEnvironment.aliasesLambdaVars aliases)
in (Eithers.bind (Eithers.mapList (\arg -> encodeTerm env arg cx g) args) (\jargs0 ->
let wrapResult = wrapLazyArguments g name jargs0
jargs = Pairs.first wrapResult
mMethodOverride = Pairs.second wrapResult
in (Logic.ifElse (Logic.or (isLocalVariable name) isLambdaBound) (Eithers.bind (encodeVariable env name cx g) (\baseExpr -> Right (Lists.foldl (\acc -> \jarg -> applyJavaArg acc jarg) baseExpr jargs))) (
let overrideMethodName =
\jid -> Optionals.cases mMethodOverride jid (\m ->
let s = Syntax.unIdentifier jid
in (Syntax.Identifier (Strings.cat2 (Strings.fromList (Lists.take (Math.sub (Strings.length s) (Strings.length JavaNames.applyMethodName)) (Strings.toList s))) m)))
in (Logic.ifElse (Lists.null typeApps) (
let header =
Syntax.MethodInvocation_HeaderSimple (Syntax.MethodName (overrideMethodName (elementJavaIdentifier isPrim False aliases name)))
in (Right (Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = jargs})))) (
let qn = Names.qualifyName name
mns = Util.qualifiedNameModuleName qn
localName = Util.qualifiedNameLocal qn
in (Optionals.cases mns (
let header =
Syntax.MethodInvocation_HeaderSimple (Syntax.MethodName (overrideMethodName (elementJavaIdentifier isPrim False aliases name)))
in (Right (Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = jargs})))) (\ns_ ->
let classId = Utils.nameToJavaName aliases (elementsQualifiedName ns_)
methodId =
Logic.ifElse isPrim (overrideMethodName (Syntax.Identifier (Strings.cat2 (Syntax.unIdentifier (Utils.nameToJavaName aliases (Names.unqualifyName (Util.QualifiedName {
Util.qualifiedNameModuleName = (Just ns_),
Util.qualifiedNameLocal = (Formatting.capitalize localName)})))) (Strings.cat2 "." JavaNames.applyMethodName)))) (Syntax.Identifier (Utils.sanitizeJavaName localName))
in (Eithers.bind (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt)))) typeApps) (\jTypeArgs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs classId methodId jTypeArgs jargs))))))))))))
getCodomain :: M.Map Core.Name Core.Term -> t0 -> Graph.Graph -> Either Errors.Error Core.Type
getCodomain ann cx g = Eithers.map (\ft -> Core.functionTypeCodomain ft) (getFunctionType ann cx g)
getFunctionType :: M.Map Core.Name Core.Term -> t0 -> Graph.Graph -> Either Errors.Error Core.FunctionType
getFunctionType ann cx g =
Eithers.bind (Eithers.bimap (\_de -> Errors.ErrorOther (Errors.OtherError (Errors.unDecodingError _de))) (\_a -> _a) (Annotations.getType g ann)) (\mt -> Optionals.cases mt (Left (Errors.ErrorOther (Errors.OtherError "type annotation is required for function and elimination terms in Java"))) (\t -> case t of
Core.TypeFunction v0 -> Right v0
_ -> Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "expected function type, got: " (ShowCore.type_ t))))))
groupPairsByFirst :: Ord t0 => ([(t0, t1)] -> M.Map t0 [t1])
groupPairsByFirst pairs =
Lists.foldl (\m -> \p ->
let k = Pairs.first p
v = Pairs.second p
in (Maps.alter (\mv -> Optionals.cases mv (Just [
v]) (\vs -> Just (Lists.concat2 vs [
v]))) k m)) Maps.empty pairs
hashCodeCompareExpr :: String -> String -> Syntax.Expression
hashCodeCompareExpr otherVar fname =
let header =
Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantType (Utils.javaTypeName (Syntax.Identifier "Integer"))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "compare")})
thisHashCode =
Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Syntax.Identifier (Utils.sanitizeJavaName fname))})),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.hashCodeMethodName)})),
Syntax.methodInvocationArguments = []})
otherHashCode =
Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantExpression (Utils.fieldExpression (Utils.javaIdentifier otherVar) (Utils.javaIdentifier fname))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.hashCodeMethodName)})),
Syntax.methodInvocationArguments = []})
in (Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = header,
Syntax.methodInvocationArguments = [
thisHashCode,
otherHashCode]}))
hashCodeMultPair :: Integer -> Core.Name -> Syntax.MultiplicativeExpression
hashCodeMultPair i fname =
let fnameStr = Core.unName fname
lhs =
Syntax.MultiplicativeExpressionUnary (Utils.javaPrimaryToJavaUnaryExpression (Utils.javaLiteralToJavaPrimary (Utils.javaInt i)))
rhs =
Utils.javaPostfixExpressionToJavaUnaryExpression (Utils.javaMethodInvocationToJavaPostfixExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantType (Utils.javaTypeName (Syntax.Identifier "java.util.Objects"))),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.hashCodeMethodName)})),
Syntax.methodInvocationArguments = [
Utils.javaExpressionNameToJavaExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Syntax.Identifier (Utils.sanitizeJavaName fnameStr))})]}))
in (Syntax.MultiplicativeExpressionTimes (Syntax.MultiplicativeExpression_Binary {
Syntax.multiplicativeExpression_BinaryLhs = lhs,
Syntax.multiplicativeExpression_BinaryRhs = rhs}))
innerClassRef :: JavaEnvironment.Aliases -> Core.Name -> String -> Syntax.Identifier
innerClassRef aliases name local =
let id = Syntax.unIdentifier (Utils.nameToJavaName aliases name)
in (Syntax.Identifier (Strings.cat2 (Strings.cat2 id ".") local))
insertBranchVar :: Core.Name -> JavaEnvironment.JavaEnvironment -> JavaEnvironment.JavaEnvironment
insertBranchVar name env =
let aliases = JavaEnvironment.javaEnvironmentAliases env
in JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = JavaEnvironment.Aliases {
JavaEnvironment.aliasesCurrentNamespace = (JavaEnvironment.aliasesCurrentNamespace aliases),
JavaEnvironment.aliasesPackages = (JavaEnvironment.aliasesPackages aliases),
JavaEnvironment.aliasesBranchVars = (Sets.insert name (JavaEnvironment.aliasesBranchVars aliases)),
JavaEnvironment.aliasesRecursiveVars = (JavaEnvironment.aliasesRecursiveVars aliases),
JavaEnvironment.aliasesInScopeTypeParams = (JavaEnvironment.aliasesInScopeTypeParams aliases),
JavaEnvironment.aliasesPolymorphicLocals = (JavaEnvironment.aliasesPolymorphicLocals aliases),
JavaEnvironment.aliasesInScopeJavaVars = (JavaEnvironment.aliasesInScopeJavaVars aliases),
JavaEnvironment.aliasesVarRenames = (JavaEnvironment.aliasesVarRenames aliases),
JavaEnvironment.aliasesLambdaVars = (JavaEnvironment.aliasesLambdaVars aliases),
JavaEnvironment.aliasesTypeVarSubst = (JavaEnvironment.aliasesTypeVarSubst aliases),
JavaEnvironment.aliasesTrustedTypeVars = (JavaEnvironment.aliasesTrustedTypeVars aliases),
JavaEnvironment.aliasesMethodCodomain = Nothing,
JavaEnvironment.aliasesThunkedVars = (JavaEnvironment.aliasesThunkedVars aliases)},
JavaEnvironment.javaEnvironmentGraph = (JavaEnvironment.javaEnvironmentGraph env)}
interfaceTypes :: Bool -> JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> [Syntax.InterfaceType]
interfaceTypes isSer aliases tparams elName =
let javaSerializableType =
Syntax.InterfaceType (Syntax.ClassType {
Syntax.classTypeAnnotations = [],
Syntax.classTypeQualifier = Syntax.ClassTypeQualifierNone,
Syntax.classTypeIdentifier = (Utils.javaTypeIdentifier "Serializable"),
Syntax.classTypeArguments = []})
selfTypeArg =
Syntax.TypeArgumentReference (Utils.nameToJavaReferenceType aliases False (Lists.map (\tp_ -> Utils.typeParameterToTypeArgument tp_) tparams) elName Nothing)
javaComparableType =
Syntax.InterfaceType (Syntax.ClassType {
Syntax.classTypeAnnotations = [],
Syntax.classTypeQualifier = Syntax.ClassTypeQualifierNone,
Syntax.classTypeIdentifier = (Utils.javaTypeIdentifier "Comparable"),
Syntax.classTypeArguments = [
selfTypeArg]})
in (Logic.ifElse isSer [
javaSerializableType,
javaComparableType] [])
isBigNumericType :: Core.Type -> Bool
isBigNumericType typ =
case (Strip.deannotateType typ) of
Core.TypeLiteral v0 -> case v0 of
Core.LiteralTypeDecimal -> True
Core.LiteralTypeInteger v1 -> case v1 of
Core.IntegerTypeBigint -> True
_ -> False
_ -> False
_ -> False
isBinaryType :: Core.Type -> Bool
isBinaryType typ =
case (Strip.deannotateType typ) of
Core.TypeLiteral v0 -> case v0 of
Core.LiteralTypeBinary -> True
_ -> False
_ -> False
isFieldUnitType :: Core.Name -> Core.Name -> t0 -> Graph.Graph -> Either t1 Bool
isFieldUnitType typeName fieldName cx g =
let schemaTypes = Graph.graphSchemaTypes g
in (Optionals.cases (Maps.lookup typeName schemaTypes) (Right False) (\ts -> case (Strip.deannotateType (Core.typeSchemeBody ts)) of
Core.TypeUnion v0 -> Right (Optionals.cases (Lists.find (\ft -> Equality.equal (Core.fieldTypeName ft) fieldName) v0) False (\ft -> Predicates.isUnitType (Strip.deannotateType (Core.fieldTypeType ft))))
_ -> Right False))
isLambdaBoundIn :: Core.Name -> S.Set Core.Name -> Bool
isLambdaBoundIn name lambdaVars =
Logic.or (Sets.member name lambdaVars) (Logic.or (Logic.and (isLambdaBoundIn_isQualified name) (Optionals.isGiven (Lists.find (\lv -> Logic.and (isLambdaBoundIn_isQualified lv) (Equality.equal (Names.localNameOf lv) (Names.localNameOf name))) (Sets.toList lambdaVars)))) (Logic.and (Logic.not (isLambdaBoundIn_isQualified name)) (Sets.member (Core.Name (Names.localNameOf name)) lambdaVars)))
isLambdaBoundIn_isQualified :: Core.Name -> Bool
isLambdaBoundIn_isQualified n = Optionals.isGiven (Util.qualifiedNameModuleName (Names.qualifyName n))
isLambdaBoundVariable :: Core.Name -> Bool
isLambdaBoundVariable name =
let v = Core.unName name
in (Equality.lte (Strings.length v) 4)
isLocalVariable :: Core.Name -> Bool
isLocalVariable name = Optionals.isNone (Util.qualifiedNameModuleName (Names.qualifyName name))
isNonComparableType :: Core.Type -> Bool
isNonComparableType typ =
case (Strip.deannotateType typ) of
Core.TypeEither _ -> True
Core.TypeFunction _ -> True
Core.TypeUnit -> True
Core.TypeLiteral v0 -> case v0 of
Core.LiteralTypeBinary -> True
_ -> False
Core.TypeForall v0 -> isNonComparableType (Core.forallTypeBody v0)
_ -> False
isRecursiveVariable :: JavaEnvironment.Aliases -> Core.Name -> Bool
isRecursiveVariable aliases name = Sets.member name (JavaEnvironment.aliasesRecursiveVars aliases)
isSerializableJavaType :: Core.Type -> Bool
isSerializableJavaType typ = Predicates.isNominalType typ
isSimpleName :: Core.Name -> Bool
isSimpleName name = Equality.equal (Lists.length (Strings.splitOn "." (Core.unName name))) 1
isUnresolvedInferenceVar :: Core.Name -> Bool
isUnresolvedInferenceVar name =
let chars = Strings.toList (Core.unName name)
in (Optionals.fromOptional False (Optionals.map (\p ->
let firstCh = Pairs.first p
rest = Pairs.second p
in (Logic.ifElse (Logic.not (Equality.equal firstCh 116)) False (Logic.and (Logic.not (Lists.null rest)) (Lists.null (Lists.filter (\c -> Logic.not (isUnresolvedInferenceVar_isDigit c)) rest))))) (Lists.uncons chars)))
isUnresolvedInferenceVar_isDigit :: Int -> Bool
isUnresolvedInferenceVar_isDigit c = Logic.and (Equality.gte c 48) (Equality.lte c 57)
java11Features :: JavaEnvironment.JavaFeatures
java11Features = JavaEnvironment.JavaFeatures {
JavaEnvironment.javaFeaturesSupportsDiamondOperator = True}
java8Features :: JavaEnvironment.JavaFeatures
java8Features = JavaEnvironment.JavaFeatures {
JavaEnvironment.javaFeaturesSupportsDiamondOperator = False}
javaComparableRefType :: Syntax.ReferenceType
javaComparableRefType =
Syntax.ReferenceTypeClassOrInterface (Syntax.ClassOrInterfaceTypeClass (Syntax.ClassType {
Syntax.classTypeAnnotations = [],
Syntax.classTypeQualifier = Syntax.ClassTypeQualifierNone,
Syntax.classTypeIdentifier = (Utils.javaTypeIdentifier "Comparable"),
Syntax.classTypeArguments = []}))
javaEnvGetGraph :: JavaEnvironment.JavaEnvironment -> Graph.Graph
javaEnvGetGraph env = JavaEnvironment.javaEnvironmentGraph env
javaEnvSetGraph :: Graph.Graph -> JavaEnvironment.JavaEnvironment -> JavaEnvironment.JavaEnvironment
javaEnvSetGraph g env =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = (JavaEnvironment.javaEnvironmentAliases env),
JavaEnvironment.javaEnvironmentGraph = g}
javaFeatures :: JavaEnvironment.JavaFeatures
javaFeatures = java11Features
javaIdentifierToString :: Syntax.Identifier -> String
javaIdentifierToString id = Syntax.unIdentifier id
javaTypeArgumentsForNamedType :: Core.Name -> t0 -> Graph.Graph -> Either Errors.Error [Syntax.TypeArgument]
javaTypeArgumentsForNamedType tname cx g =
Eithers.bind (Resolution.requireType cx g tname) (\typ -> Right (Lists.map (\tp_ -> Utils.typeParameterToTypeArgument tp_) (javaTypeParametersForType typ)))
javaTypeArgumentsForType :: Core.Type -> [Syntax.TypeArgument]
javaTypeArgumentsForType typ = Lists.reverse (Lists.map Utils.typeParameterToTypeArgument (javaTypeParametersForType typ))
javaTypeParametersForType :: Core.Type -> [Syntax.TypeParameter]
javaTypeParametersForType typ =
let toParam = \name -> Utils.javaTypeParameter (Formatting.capitalize (Core.unName name))
boundVars = javaTypeParametersForType_bvars typ
freeVars = Lists.filter (\v -> isLambdaBoundVariable v) (Sets.toList (Variables.freeVariablesInType typ))
vars = Lists.nub (Lists.concat2 boundVars freeVars)
in (Lists.map toParam vars)
javaTypeParametersForType_bvars :: Core.Type -> [Core.Name]
javaTypeParametersForType_bvars t =
case t of
Core.TypeForall v0 -> Lists.cons (Core.forallTypeParameter v0) (javaTypeParametersForType_bvars (Core.forallTypeBody v0))
_ -> []
lazyFlagsForPrimitive :: Graph.Graph -> Core.Name -> [Bool]
lazyFlagsForPrimitive g name =
Optionals.cases (Maps.lookup name (Graph.graphPrimitives g)) [] (\prim -> Lists.map (\p -> Typing.parameterIsLazy p) (Typing.termSignatureParameters (Packaging.primitiveDefinitionSignature (Graph.primitiveDefinition prim))))
moduleToJava :: Packaging.Module -> [Packaging.Definition] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error (M.Map String String)
moduleToJava mod defs cx g =
Eithers.bind (encodeDefinitions mod defs cx g) (\units -> Right (Maps.fromList (Lists.map (\entry ->
let name = Pairs.first entry
unit = Pairs.second entry
in (bindingNameToFilePath name, (Serialization.printExpr (Serialization.parenthesize (Serde.compilationUnitToExpr unit))))) (Maps.toList units))))
nameMapToTypeMap :: Ord t0 => (M.Map t0 Core.Name -> M.Map t0 Core.Type)
nameMapToTypeMap m = Maps.map (\v -> Core.TypeVariable v) m
namespaceParent :: Packaging.ModuleName -> Maybe Packaging.ModuleName
namespaceParent ns =
let parts = Strings.splitOn "." (Packaging.unModuleName ns)
initParts = Optionals.fromOptional [] (Lists.maybeInit parts)
in (Logic.ifElse (Lists.null initParts) Nothing (Just (Packaging.ModuleName (Strings.intercalate "." initParts))))
noComment :: Syntax.ClassBodyDeclaration -> Syntax.ClassBodyDeclarationWithComments
noComment decl =
Syntax.ClassBodyDeclarationWithComments {
Syntax.classBodyDeclarationWithCommentsValue = decl,
Syntax.classBodyDeclarationWithCommentsComments = Nothing}
noInterfaceComment :: Syntax.InterfaceMemberDeclaration -> Syntax.InterfaceMemberDeclarationWithComments
noInterfaceComment decl =
Syntax.InterfaceMemberDeclarationWithComments {
Syntax.interfaceMemberDeclarationWithCommentsValue = decl,
Syntax.interfaceMemberDeclarationWithCommentsComments = Nothing}
otherwiseBranch :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> Core.Type -> Core.Type -> Core.Name -> Syntax.Type -> [Syntax.TypeArgument] -> Core.Term -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
otherwiseBranch env aliases dom cod tname jcod targs d cx g =
let jdom = Syntax.TypeReference (Utils.nameToJavaReferenceType aliases True targs tname Nothing)
mods = [
Syntax.MethodModifierPublic]
anns = [
Utils.overrideAnnotation]
param = Utils.javaTypeToJavaFormalParameter jdom (Core.Name "instance")
result = Syntax.ResultType (Syntax.UnannType jcod)
in (Eithers.bind (analyzeJavaFunction env d cx g) (\fs ->
let bindings = Typing.functionStructureBindings fs
rawBody = Typing.functionStructureBody fs
innerBody = annotateBodyWithCod cod rawBody
env2 = Typing.functionStructureEnvironment fs
in (Eithers.bind (bindingsToStatements env2 bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env3 = Pairs.second bindResult
in (Eithers.bind (encodeTerm env3 innerBody cx g) (\jret ->
let returnStmt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jret))
allStmts = Lists.concat2 bindingStmts [
returnStmt]
in (Right (noComment (Utils.methodDeclaration mods [] anns JavaNames.otherwiseMethodName [
param] result (Just allStmts))))))))))
peelDomainTypes :: Int -> Core.Type -> ([Core.Type], Core.Type)
peelDomainTypes n t =
Logic.ifElse (Equality.lte n 0) ([], t) (case (Strip.deannotateType t) of
Core.TypeFunction v0 ->
let rest = peelDomainTypes (Math.sub n 1) (Core.functionTypeCodomain v0)
in (Lists.cons (Core.functionTypeDomain v0) (Pairs.first rest), (Pairs.second rest))
_ -> ([], t))
peelDomainsAndCod :: Int -> Core.Type -> ([Core.Type], Core.Type)
peelDomainsAndCod n t =
Logic.ifElse (Equality.lte n 0) ([], t) (case (Strip.deannotateType t) of
Core.TypeFunction v0 ->
let rest = peelDomainsAndCod (Math.sub n 1) (Core.functionTypeCodomain v0)
in (Lists.cons (Core.functionTypeDomain v0) (Pairs.first rest), (Pairs.second rest))
_ -> ([], t))
peelExpectedTypes :: M.Map Core.Name Core.Type -> Int -> Core.Type -> [Core.Type]
peelExpectedTypes subst n t =
Logic.ifElse (Equality.equal n 0) [] (case (Strip.deannotateType t) of
Core.TypeFunction v0 -> Lists.cons (applySubstFull subst (Core.functionTypeDomain v0)) (peelExpectedTypes subst (Math.sub n 1) (Core.functionTypeCodomain v0))
_ -> [])
propagateType :: Core.Type -> Core.Term -> Core.Term
propagateType typ term =
let setTypeAnn = \t -> Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ typ)) t
in case (Strip.deannotateTerm term) of
Core.TermLambda _ ->
let annotated = setTypeAnn term
in case (Strip.deannotateType typ) of
Core.TypeFunction v1 -> propagateType_propagateIntoLambda (Core.functionTypeCodomain v1) annotated
_ -> annotated
Core.TermLet v0 ->
let propagatedBindings =
Lists.map (\b -> Optionals.cases (Core.bindingTypeScheme b) b (\ts -> Core.Binding {
Core.bindingName = (Core.bindingName b),
Core.bindingTerm = (propagateType (Core.typeSchemeBody ts) (Core.bindingTerm b)),
Core.bindingTypeScheme = (Core.bindingTypeScheme b)})) (Core.letBindings v0)
in (setTypeAnn (propagateType_rebuildLet term propagatedBindings (propagateType typ (Core.letBody v0))))
Core.TermApplication v0 ->
let fun = Core.applicationFunction v0
arg = Core.applicationArgument v0
annotatedFun =
case (Strip.deannotateTerm fun) of
Core.TermCases v1 ->
let dom = Resolution.nominalApplication (Core.caseStatementTypeName v1) []
ft =
Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = typ})
in (Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ ft)) fun)
_ -> fun
in (setTypeAnn (Core.TermApplication (Core.Application {
Core.applicationFunction = annotatedFun,
Core.applicationArgument = arg})))
_ -> setTypeAnn term
propagateType_propagateIntoLambda :: Core.Type -> Core.Term -> Core.Term
propagateType_propagateIntoLambda cod t =
case t of
Core.TermAnnotated v0 -> Core.TermAnnotated (Core.AnnotatedTerm {
Core.annotatedTermBody = (propagateType_propagateIntoLambda cod (Core.annotatedTermBody v0)),
Core.annotatedTermAnnotation = (Core.annotatedTermAnnotation v0)})
Core.TermLambda v0 -> Core.TermLambda (Core.Lambda {
Core.lambdaParameter = (Core.lambdaParameter v0),
Core.lambdaDomain = (Core.lambdaDomain v0),
Core.lambdaBody = (propagateType cod (Core.lambdaBody v0))})
_ -> t
propagateType_rebuildLet :: Core.Term -> [Core.Binding] -> Core.Term -> Core.Term
propagateType_rebuildLet t bindings newBody =
case t of
Core.TermAnnotated v0 -> Core.TermAnnotated (Core.AnnotatedTerm {
Core.annotatedTermBody = (propagateType_rebuildLet (Core.annotatedTermBody v0) bindings newBody),
Core.annotatedTermAnnotation = (Core.annotatedTermAnnotation v0)})
Core.TermLet _ -> Core.TermLet (Core.Let {
Core.letBindings = bindings,
Core.letBody = newBody})
_ -> t
propagateTypesInAppChain :: Core.Type -> Core.Type -> Core.Term -> Core.Term
propagateTypesInAppChain fixedCod resultType t =
let flattened = flattenApps t []
args = Pairs.first flattened
fun = Pairs.second flattened
lambdaDomsResult = collectLambdaDomains fun
lambdaDoms = Pairs.first lambdaDomsResult
nArgs = Lists.length args
nLambdaDoms = Lists.length lambdaDoms
in (Logic.ifElse (Logic.and (Equality.gt nLambdaDoms 0) (Equality.gt nArgs 0)) (
let bodyRetType = Pairs.second (peelDomainsAndCod (Math.sub nLambdaDoms nArgs) resultType)
funType =
Lists.foldl (\c -> \d -> Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = d,
Core.functionTypeCodomain = c})) bodyRetType (Lists.reverse lambdaDoms)
annotatedFun = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ funType)) fun
in (rebuildApps annotatedFun args funType)) (case (Strip.deannotateTerm t) of
Core.TermApplication v0 ->
let lhs = Core.applicationFunction v0
rhs = Core.applicationArgument v0
annotatedLhs =
case (Strip.deannotateTerm lhs) of
Core.TermCases v1 ->
let dom = Resolution.nominalApplication (Core.caseStatementTypeName v1) []
ft =
Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = fixedCod})
in (Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ ft)) lhs)
_ -> lhs
in (Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ resultType)) (Core.TermApplication (Core.Application {
Core.applicationFunction = annotatedLhs,
Core.applicationArgument = rhs})))
_ -> Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ resultType)) t))
rebuildApps :: Core.Term -> [Core.Term] -> Core.Type -> Core.Term
rebuildApps f args fType =
Logic.ifElse (Lists.null args) f (case (Strip.deannotateType fType) of
Core.TypeFunction v0 -> Optionals.fromOptional f (Optionals.map (\p ->
let arg = Pairs.first p
rest = Pairs.second p
remainingType = Core.functionTypeCodomain v0
app =
Core.TermApplication (Core.Application {
Core.applicationFunction = f,
Core.applicationArgument = arg})
annotatedApp = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ remainingType)) app
in (rebuildApps annotatedApp rest remainingType)) (Lists.uncons args))
_ -> Lists.foldl (\acc -> \a -> Core.TermApplication (Core.Application {
Core.applicationFunction = acc,
Core.applicationArgument = a})) f args)
recordBuilderClass :: JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> [Core.FieldType] -> t0 -> Graph.Graph -> Either Errors.Error [Syntax.ClassBodyDeclarationWithComments]
recordBuilderClass aliases tparams elName fields cx g =
let typeArgRefs = Lists.map Utils.typeParameterToReferenceType tparams
typeArgs = Lists.map (\rt -> Syntax.TypeArgumentReference rt) typeArgRefs
mTypeArgs = Logic.ifElse (Lists.null tparams) Nothing (Just (Syntax.TypeArgumentsOrDiamondArguments typeArgs))
recordLocalName = Utils.sanitizeJavaName (Names.localNameOf elName)
builderType = Utils.javaRefType typeArgRefs Nothing "Builder"
builderResult = Utils.javaTypeToJavaResult builderType
recordType = Utils.javaRefType typeArgRefs Nothing recordLocalName
recordResult = Utils.javaTypeToJavaResult recordType
returnThisStmt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just Utils.javaThis))
in (Eithers.bind (Eithers.mapList (\f ->
let mods = [
Syntax.FieldModifierPrivate]
ftype = Core.fieldTypeType f
fname = Core.fieldTypeName f
in (Eithers.bind (encodeType aliases Sets.empty ftype cx g) (\jt -> Right (noComment (Utils.javaMemberField mods jt (Utils.fieldNameToJavaVariableDeclarator fname)))))) fields) (\builderFields -> Eithers.bind (Eithers.mapList (\f ->
let mods = [
Syntax.MethodModifierPublic]
fname = Core.fieldTypeName f
assignStmt = Syntax.BlockStatementStatement (Utils.toAssignStmt fname)
in (Eithers.bind (fieldTypeToFormalParam aliases f cx g) (\param -> Right (noComment (Utils.methodDeclaration mods [] [] (builderSetterName fname) [
param] builderResult (Just [
assignStmt,
returnThisStmt])))))) fields) (\setterMethods ->
let buildMods = [
Syntax.MethodModifierPublic]
buildArgs = Lists.map (\f -> Utils.fieldNameToJavaExpression (Core.fieldTypeName f)) fields
buildReturnStmt =
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier recordLocalName) mTypeArgs) buildArgs Nothing)))
buildMethod =
withCommentString (Strings.cat2 "Builds an immutable {@link " (Strings.cat2 recordLocalName "}.")) (Utils.methodDeclaration buildMods [] [] "build" [] recordResult (Just [
buildReturnStmt]))
builderClassDecl =
Utils.javaClassDeclaration aliases tparams (Core.Name "Builder") [
Syntax.ClassModifierPublic,
Syntax.ClassModifierStatic,
Syntax.ClassModifierFinal] Nothing [] (Lists.concat [
builderFields,
setterMethods,
[
buildMethod]])
builderClassMember =
withCommentString (Strings.cat2 "A fluent builder for {@link " (Strings.cat2 recordLocalName "}.")) (Syntax.ClassBodyDeclarationClassMember (Syntax.ClassMemberDeclarationClass builderClassDecl))
factoryMods =
[
Syntax.MethodModifierPublic,
Syntax.MethodModifierStatic]
factoryReturnStmt =
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "Builder") mTypeArgs) [] Nothing)))
factoryMethod =
withCommentString (Strings.cat2 "Creates a new fluent builder for {@link " (Strings.cat2 recordLocalName "}.")) (Utils.methodDeclaration factoryMods tparams [] "builder" [] builderResult (Just [
factoryReturnStmt]))
in (Right [
factoryMethod,
builderClassMember]))))
recordCompareToMethod :: JavaEnvironment.Aliases -> t0 -> Core.Name -> [Core.FieldType] -> Syntax.ClassBodyDeclaration
recordCompareToMethod aliases tparams elName fields =
let anns =
[
Utils.overrideAnnotation,
Utils.suppressWarningsUncheckedAnnotation]
mods = [
Syntax.MethodModifierPublic]
param =
Utils.javaTypeToJavaFormalParameter (Utils.javaTypeFromTypeName aliases elName) (Core.Name JavaNames.otherInstanceName)
result = Utils.javaTypeToJavaResult Utils.javaIntType
in (Utils.methodDeclaration mods [] anns JavaNames.compareToMethodName [
param] result (Just (compareToBody aliases JavaNames.otherInstanceName fields)))
recordConstructor :: JavaEnvironment.Aliases -> Core.Name -> [Core.FieldType] -> t0 -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclaration
recordConstructor aliases elName fields cx g =
let assignStmts = Lists.map (\f -> Syntax.BlockStatementStatement (Utils.toAssignStmt (Core.fieldTypeName f))) fields
in (Eithers.bind (Eithers.mapList (\f -> fieldTypeToFormalParam aliases f cx g) fields) (\params -> Right (Utils.makeConstructor aliases elName False params assignStmts)))
recordEqualsMethod :: JavaEnvironment.Aliases -> Core.Name -> [Core.FieldType] -> Syntax.ClassBodyDeclaration
recordEqualsMethod aliases elName fields =
let anns = [
Utils.overrideAnnotation]
mods = [
Syntax.MethodModifierPublic]
param = Utils.javaTypeToJavaFormalParameter (Utils.javaRefType [] Nothing "Object") (Core.Name JavaNames.otherInstanceName)
result = Utils.javaTypeToJavaResult Utils.javaBooleanType
tmpName = "o"
instanceOfStmt =
Syntax.BlockStatementStatement (Syntax.StatementIfThen (Syntax.IfThenStatement {
Syntax.ifThenStatementExpression = (Utils.javaUnaryExpressionToJavaExpression (Syntax.UnaryExpressionOther (Syntax.UnaryExpressionNotPlusMinusNot (Utils.javaRelationalExpressionToJavaUnaryExpression (Utils.javaInstanceOf (Utils.javaIdentifierToJavaRelationalExpression (Utils.javaIdentifier JavaNames.otherInstanceName)) (Utils.nameToJavaReferenceType aliases False [] elName Nothing)))))),
Syntax.ifThenStatementStatement = (Utils.javaReturnStatement (Just (Utils.javaBooleanExpression False)))}))
castStmt =
Utils.variableDeclarationStatement aliases (Utils.javaTypeFromTypeName aliases elName) (Utils.javaIdentifier tmpName) (Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression (Utils.nameToJavaReferenceType aliases False [] elName Nothing) (Utils.javaIdentifierToJavaUnaryExpression (Syntax.Identifier (Utils.sanitizeJavaName JavaNames.otherInstanceName)))))
returnAllFieldsEqual =
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Logic.ifElse (Lists.null fields) (Utils.javaBooleanExpression True) (Utils.javaConditionalAndExpressionToJavaExpression (Syntax.ConditionalAndExpression (Lists.map (\f -> eqClause tmpName f) fields))))))
in (Utils.methodDeclaration mods [] anns JavaNames.equalsMethodName [
param] result (Just [
instanceOfStmt,
castStmt,
returnAllFieldsEqual]))
recordHashCodeMethod :: [Core.FieldType] -> Syntax.ClassBodyDeclaration
recordHashCodeMethod fields =
let anns = [
Utils.overrideAnnotation]
mods = [
Syntax.MethodModifierPublic]
result = Utils.javaTypeToJavaResult Utils.javaIntType
returnSum =
Syntax.BlockStatementStatement (Logic.ifElse (Lists.null fields) (Utils.javaReturnStatement (Just (Utils.javaIntExpression 0))) (Utils.javaReturnStatement (Just (Utils.javaAdditiveExpressionToJavaExpression (Utils.addExpressions (Lists.zipWith hashCodeMultPair first20Primes (Lists.map (\f -> Core.fieldTypeName f) fields)))))))
in (Utils.methodDeclaration mods [] anns JavaNames.hashCodeMethodName [] result (Just [
returnSum]))
recordMemberVar :: JavaEnvironment.Aliases -> Core.FieldType -> t0 -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclaration
recordMemberVar aliases ft cx g =
let mods =
[
Syntax.FieldModifierPublic,
Syntax.FieldModifierFinal]
fname = Core.fieldTypeName ft
ftype = Core.fieldTypeType ft
in (Eithers.bind (encodeType aliases Sets.empty ftype cx g) (\jt -> Right (Utils.javaMemberField mods jt (Utils.fieldNameToJavaVariableDeclarator fname))))
recordWithMethod :: JavaEnvironment.Aliases -> Core.Name -> [Core.FieldType] -> Core.FieldType -> t0 -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclaration
recordWithMethod aliases elName fields field cx g =
let mods = [
Syntax.MethodModifierPublic]
anns = []
methodName =
Strings.cat2 "with" (Formatting.nonAlnumToUnderscores (Formatting.capitalize (Core.unName (Core.fieldTypeName field))))
result = Utils.referenceTypeToResult (Utils.nameToJavaReferenceType aliases False [] elName Nothing)
consId = Syntax.Identifier (Utils.sanitizeJavaName (Names.localNameOf elName))
fieldArgs = Lists.map (\f -> Utils.fieldNameToJavaExpression (Core.fieldTypeName f)) fields
returnStmt =
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaConstructorCall (Utils.javaConstructorName consId Nothing) fieldArgs Nothing)))
in (Eithers.bind (fieldTypeToFormalParam aliases field cx g) (\param -> Right (Utils.methodDeclaration mods [] anns methodName [
param] result (Just [
returnStmt]))))
resolveTypeApps :: [Core.Name] -> [Core.Type] -> M.Map Core.Name Core.Type -> [Core.Type]
resolveTypeApps schemeVars fallbackTypeApps argSubst =
let resolvedVars = Sets.fromList (Maps.keys argSubst)
unresolvedVars = Lists.filter (\v -> Logic.not (Sets.member v resolvedVars)) schemeVars
usedTypes = Sets.fromList (Maps.elems argSubst)
unusedIrTypes = Lists.filter (\t -> Logic.not (Sets.member t usedTypes)) fallbackTypeApps
remainingSubst = Maps.fromList (Lists.zip unresolvedVars unusedIrTypes)
fullSubst = Maps.union argSubst remainingSubst
in (Lists.map (\v -> Maps.findWithDefault (Core.TypeVariable v) v fullSubst) schemeVars)
selfRefSubstitution :: (Eq t0, Ord t0) => (M.Map t0 [t0] -> M.Map t0 t0)
selfRefSubstitution grouped =
Lists.foldl (\subst -> \entry -> selfRefSubstitution_processGroup subst (Pairs.first entry) (Pairs.second entry)) Maps.empty (Maps.toList grouped)
selfRefSubstitution_processGroup :: (Eq t0, Ord t0) => (M.Map t0 t0 -> t0 -> [t0] -> M.Map t0 t0)
selfRefSubstitution_processGroup subst inVar outVars =
Logic.ifElse (Lists.elem inVar outVars) (Lists.foldl (\s -> \v -> Logic.ifElse (Equality.equal v inVar) s (Maps.insert v inVar s)) subst outVars) subst
serializableTypes :: Bool -> [Syntax.InterfaceType]
serializableTypes isSer =
let javaSerializableType =
Syntax.InterfaceType (Syntax.ClassType {
Syntax.classTypeAnnotations = [],
Syntax.classTypeQualifier = Syntax.ClassTypeQualifierNone,
Syntax.classTypeIdentifier = (Utils.javaTypeIdentifier "Serializable"),
Syntax.classTypeArguments = []})
in (Logic.ifElse isSer [
javaSerializableType] [])
splitConstantInitializer :: Syntax.InterfaceMemberDeclaration -> [Syntax.InterfaceMemberDeclaration]
splitConstantInitializer member =
case member of
Syntax.InterfaceMemberDeclarationConstant v0 -> Lists.bind (Syntax.constantDeclarationVariables v0) (splitConstantInitializer_splitVar (Syntax.constantDeclarationModifiers v0) (Syntax.constantDeclarationType v0))
_ -> [
member]
splitConstantInitializer_splitVar :: [Syntax.ConstantModifier] -> Syntax.UnannType -> Syntax.VariableDeclarator -> [Syntax.InterfaceMemberDeclaration]
splitConstantInitializer_splitVar mods utype vd =
let vid = Syntax.variableDeclaratorId vd
mInit = Syntax.variableDeclaratorInitializer vd
in (Optionals.cases mInit [
Syntax.InterfaceMemberDeclarationConstant (Syntax.ConstantDeclaration {
Syntax.constantDeclarationModifiers = mods,
Syntax.constantDeclarationType = utype,
Syntax.constantDeclarationVariables = [
vd]})] (\init_ -> case init_ of
Syntax.VariableInitializerExpression v0 ->
let varName = javaIdentifierToString (Syntax.variableDeclaratorIdIdentifier vid)
helperName = Strings.cat2 "_init_" varName
callExpr = Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocation Nothing (Syntax.Identifier helperName) [])
field =
Syntax.InterfaceMemberDeclarationConstant (Syntax.ConstantDeclaration {
Syntax.constantDeclarationModifiers = mods,
Syntax.constantDeclarationType = utype,
Syntax.constantDeclarationVariables = [
Syntax.VariableDeclarator {
Syntax.variableDeclaratorId = vid,
Syntax.variableDeclaratorInitializer = (Just (Syntax.VariableInitializerExpression callExpr))}]})
returnSt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just v0))
resultType = Syntax.ResultType utype
helper =
Utils.interfaceMethodDeclaration [
Syntax.InterfaceMethodModifierStatic,
Syntax.InterfaceMethodModifierPrivate] [] helperName [] resultType (Just [
returnSt])
in [
field,
helper]
_ -> [
Syntax.InterfaceMemberDeclarationConstant (Syntax.ConstantDeclaration {
Syntax.constantDeclarationModifiers = mods,
Syntax.constantDeclarationType = utype,
Syntax.constantDeclarationVariables = [
vd]})]))
stripForalls :: Core.Type -> Core.Type
stripForalls t =
case (Strip.deannotateType t) of
Core.TypeForall v0 -> stripForalls (Core.forallTypeBody v0)
_ -> t
substituteTypeVarsWithTypes :: M.Map Core.Name Core.Type -> Core.Type -> Core.Type
substituteTypeVarsWithTypes subst t = substituteTypeVarsWithTypes_go subst (Strip.deannotateType t)
substituteTypeVarsWithTypes_go :: M.Map Core.Name Core.Type -> Core.Type -> Core.Type
substituteTypeVarsWithTypes_go subst t =
case (Strip.deannotateType t) of
Core.TypeVariable v0 -> Optionals.cases (Maps.lookup v0 subst) t (\rep -> rep)
Core.TypeFunction v0 -> Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = (substituteTypeVarsWithTypes_go subst (Core.functionTypeDomain v0)),
Core.functionTypeCodomain = (substituteTypeVarsWithTypes_go subst (Core.functionTypeCodomain v0))})
Core.TypeApplication v0 -> Core.TypeApplication (Core.ApplicationType {
Core.applicationTypeFunction = (substituteTypeVarsWithTypes_go subst (Core.applicationTypeFunction v0)),
Core.applicationTypeArgument = (substituteTypeVarsWithTypes_go subst (Core.applicationTypeArgument v0))})
Core.TypeList v0 -> Core.TypeList (substituteTypeVarsWithTypes_go subst v0)
Core.TypeSet v0 -> Core.TypeSet (substituteTypeVarsWithTypes_go subst v0)
Core.TypeOptional v0 -> Core.TypeOptional (substituteTypeVarsWithTypes_go subst v0)
Core.TypeEffect v0 -> Core.TypeEffect (substituteTypeVarsWithTypes_go subst v0)
Core.TypeMap v0 -> Core.TypeMap (Core.MapType {
Core.mapTypeKeys = (substituteTypeVarsWithTypes_go subst (Core.mapTypeKeys v0)),
Core.mapTypeValues = (substituteTypeVarsWithTypes_go subst (Core.mapTypeValues v0))})
Core.TypePair v0 -> Core.TypePair (Core.PairType {
Core.pairTypeFirst = (substituteTypeVarsWithTypes_go subst (Core.pairTypeFirst v0)),
Core.pairTypeSecond = (substituteTypeVarsWithTypes_go subst (Core.pairTypeSecond v0))})
Core.TypeEither v0 -> Core.TypeEither (Core.EitherType {
Core.eitherTypeLeft = (substituteTypeVarsWithTypes_go subst (Core.eitherTypeLeft v0)),
Core.eitherTypeRight = (substituteTypeVarsWithTypes_go subst (Core.eitherTypeRight v0))})
Core.TypeForall v0 -> Core.TypeForall (Core.ForallType {
Core.forallTypeParameter = (Core.forallTypeParameter v0),
Core.forallTypeBody = (substituteTypeVarsWithTypes_go subst (Core.forallTypeBody v0))})
_ -> t
tagCmpNotZeroExpr :: Syntax.Expression
tagCmpNotZeroExpr =
Utils.javaEqualityExpressionToJavaExpression (Syntax.EqualityExpressionNotEqual (Syntax.EqualityExpression_Binary {
Syntax.equalityExpression_BinaryLhs = lhs,
Syntax.equalityExpression_BinaryRhs = rhs}))
where
lhs =
Utils.javaRelationalExpressionToJavaEqualityExpression (Utils.javaPostfixExpressionToJavaRelationalExpression (Syntax.PostfixExpressionName (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Utils.javaIdentifier "tagCmp")})))
rhs =
Utils.javaPostfixExpressionToJavaRelationalExpression (Syntax.PostfixExpressionPrimary (Utils.javaLiteralToJavaPrimary (Utils.javaInt 0)))
tagCompareExpr :: Syntax.Expression
tagCompareExpr =
Utils.javaMethodInvocationToJavaExpression (Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantPrimary (Utils.javaMethodInvocationToJavaPrimary thisGetName)),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier JavaNames.compareToMethodName)})),
Syntax.methodInvocationArguments = [
Utils.javaMethodInvocationToJavaExpression otherGetName]})
where
thisGetClass =
Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantPrimary (Utils.javaExpressionToJavaPrimary Utils.javaThis)),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "getClass")})),
Syntax.methodInvocationArguments = []}
thisGetName =
Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantPrimary (Utils.javaMethodInvocationToJavaPrimary thisGetClass)),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "getName")})),
Syntax.methodInvocationArguments = []}
otherGetClass =
Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Syntax.Identifier JavaNames.otherInstanceName)})),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "getClass")})),
Syntax.methodInvocationArguments = []}
otherGetName =
Syntax.MethodInvocation {
Syntax.methodInvocationHeader = (Syntax.MethodInvocation_HeaderComplex (Syntax.MethodInvocation_Complex {
Syntax.methodInvocation_ComplexVariant = (Syntax.MethodInvocation_VariantPrimary (Utils.javaMethodInvocationToJavaPrimary otherGetClass)),
Syntax.methodInvocation_ComplexTypeArguments = [],
Syntax.methodInvocation_ComplexIdentifier = (Syntax.Identifier "getName")})),
Syntax.methodInvocationArguments = []}
takeTypeArgs :: String -> Int -> [Syntax.Type] -> t0 -> t1 -> Either Errors.Error [Syntax.TypeArgument]
takeTypeArgs label n tyapps cx g =
Logic.ifElse (Equality.lt (Lists.length tyapps) n) (Left (Errors.ErrorOther (Errors.OtherError (Strings.cat [
"needed type arguments for ",
label,
", found too few"])))) (Eithers.mapList (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt))) (Lists.take n tyapps))
toClassDecl :: Bool -> Bool -> JavaEnvironment.Aliases -> [Syntax.TypeParameter] -> Core.Name -> Core.Type -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassDeclaration
toClassDecl isInner isSer aliases tparams elName t cx g =
let wrap =
\t_ -> declarationForRecordType isInner isSer aliases tparams elName [
Core.FieldType {
Core.fieldTypeName = (Core.Name "value"),
Core.fieldTypeType = (Strip.deannotateType t_)}] cx g
in case (Strip.deannotateType t) of
Core.TypeRecord v0 -> declarationForRecordType isInner isSer aliases tparams elName v0 cx g
Core.TypeUnion v0 -> declarationForUnionType isSer aliases tparams elName v0 cx g
Core.TypeForall v0 ->
let v = Core.forallTypeParameter v0
body = Core.forallTypeBody v0
param = Utils.javaTypeParameter (Formatting.capitalize (Core.unName v))
in (toClassDecl False isSer aliases (Lists.concat2 tparams [
param]) elName body cx g)
Core.TypeWrap v0 -> declarationForRecordType isInner isSer aliases tparams elName [
Core.FieldType {
Core.fieldTypeName = (Core.Name "value"),
Core.fieldTypeType = v0}] cx g
_ -> wrap t
toDeclInit :: JavaEnvironment.Aliases -> Graph.Graph -> S.Set Core.Name -> [Core.Binding] -> Core.Name -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error (Maybe Syntax.BlockStatement)
toDeclInit aliasesExt gExt recursiveVars flatBindings name cx g =
Logic.ifElse (Sets.member name recursiveVars) (
let binding =
Optionals.fromOptional (Core.Binding {
Core.bindingName = name,
Core.bindingTerm = Core.TermUnit,
Core.bindingTypeScheme = Nothing}) (Lists.maybeHead (Lists.filter (\b -> Equality.equal (Core.bindingName b) name) flatBindings))
value = Core.bindingTerm binding
in (Eithers.bind (Optionals.cases (Core.bindingTypeScheme binding) (Checking.typeOfTerm cx gExt value) (\ts -> Right (Core.typeSchemeBody ts))) (\typ -> Eithers.bind (encodeType aliasesExt Sets.empty typ cx g) (\jtype ->
let id = Utils.variableToJavaIdentifier name
arid = Syntax.Identifier "java.util.concurrent.atomic.AtomicReference"
aid =
Syntax.AnnotatedIdentifier {
Syntax.annotatedIdentifierAnnotations = [],
Syntax.annotatedIdentifierIdentifier = arid}
in (Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt ->
let targs = typeArgsOrDiamond [
Syntax.TypeArgumentReference rt]
ci =
Syntax.ClassOrInterfaceTypeToInstantiate {
Syntax.classOrInterfaceTypeToInstantiateIdentifiers = [
aid],
Syntax.classOrInterfaceTypeToInstantiateTypeArguments = (Just targs)}
body = Utils.javaConstructorCall ci [] Nothing
pkg =
JavaNames.javaPackageName [
"java",
"util",
"concurrent",
"atomic"]
artype = Utils.javaRefType [
rt] (Just pkg) "AtomicReference"
in (Right (Just (Utils.variableDeclarationStatement aliasesExt artype id body))))))))) (Right Nothing)
toDeclStatement :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> Graph.Graph -> S.Set Core.Name -> S.Set Core.Name -> [Core.Binding] -> Core.Name -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.BlockStatement
toDeclStatement envExt aliasesExt gExt recursiveVars thunkedVars flatBindings name cx g =
let binding =
Optionals.fromOptional (Core.Binding {
Core.bindingName = name,
Core.bindingTerm = Core.TermUnit,
Core.bindingTypeScheme = Nothing}) (Lists.maybeHead (Lists.filter (\b -> Equality.equal (Core.bindingName b) name) flatBindings))
value = Core.bindingTerm binding
in (Eithers.bind (Optionals.cases (Core.bindingTypeScheme binding) (Checking.typeOfTerm cx gExt value) (\ts -> Right (Core.typeSchemeBody ts))) (\typ -> Eithers.bind (encodeType aliasesExt Sets.empty typ cx g) (\jtype ->
let id = Utils.variableToJavaIdentifier name
annotatedValue = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ typ)) value
in (Eithers.bind (encodeTerm envExt annotatedValue cx g) (\rhs -> Logic.ifElse (Sets.member name recursiveVars) (Right (Syntax.BlockStatementStatement (Utils.javaMethodInvocationToJavaStatement (Utils.methodInvocation (Just (Left (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = id}))) (Syntax.Identifier JavaNames.setMethodName) [
rhs])))) (Logic.ifElse (Sets.member name thunkedVars) (Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt ->
let lazyType = Utils.javaRefType [
rt] JavaNames.hydraUtilPackageName "Lazy"
lambdaBody = Syntax.LambdaBodyExpression rhs
supplierLambda =
Syntax.ExpressionLambda (Syntax.LambdaExpression {
Syntax.lambdaExpressionParameters = (Syntax.LambdaParametersTuple []),
Syntax.lambdaExpressionBody = lambdaBody})
targs = typeArgsOrDiamond [
Syntax.TypeArgumentReference rt]
lazyExpr =
Utils.javaConstructorCall (Utils.javaConstructorName (Syntax.Identifier "hydra.overlay.java.util.Lazy") (Just targs)) [
supplierLambda] Nothing
in (Right (Utils.variableDeclarationStatement aliasesExt lazyType id lazyExpr)))) (Right (Utils.variableDeclarationStatement aliasesExt jtype id rhs))))))))
tryInferFunctionType :: Core.Term -> Maybe Core.Type
tryInferFunctionType funTerm =
case (Strip.deannotateTerm funTerm) of
Core.TermLambda v0 -> Optionals.bind (Core.lambdaDomain v0) (\dom ->
let mCod =
case (Core.lambdaBody v0) of
Core.TermAnnotated v1 -> Optionals.bind (Maps.lookup Constants.keyType (Annotations.getAnnotationMap (Core.annotatedTermAnnotation v1))) (\typeTerm -> decodeTypeFromTerm typeTerm)
Core.TermLambda _ -> tryInferFunctionType (Core.lambdaBody v0)
_ -> Nothing
in (Optionals.map (\cod -> Core.TypeFunction (Core.FunctionType {
Core.functionTypeDomain = dom,
Core.functionTypeCodomain = cod})) mCod))
_ -> Nothing
typeAppFallbackCast :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> [M.Map Core.Name Core.Term] -> [Syntax.Type] -> Syntax.Type -> Core.Term -> Core.Type -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
typeAppFallbackCast env aliases anns tyapps jatyp body typ cx g =
let annotatedBody = Annotations.setTermAnnotation Constants.keyType (Just (EncodeCore.type_ typ)) body
in (Eithers.bind (encodeTermInternal env anns (Lists.cons jatyp tyapps) annotatedBody cx g) (\jbody -> Eithers.bind (encodeType aliases Sets.empty typ cx g) (\jtype -> Eithers.bind (Utils.javaTypeToJavaReferenceType jtype cx) (\rt -> Right (Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression rt (Utils.javaExpressionToJavaUnaryExpression jbody)))))))
typeAppNullaryOrHoisted :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> [M.Map Core.Name Core.Term] -> [Syntax.Type] -> Syntax.Type -> Core.Term -> Core.Type -> Core.Name -> JavaEnvironment.JavaSymbolClass -> [Core.Type] -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.Expression
typeAppNullaryOrHoisted env aliases anns tyapps jatyp body correctedTyp varName cls allTypeArgs cx g =
let qn = Names.qualifyName varName
mns = Util.qualifiedNameModuleName qn
localName = Util.qualifiedNameLocal qn
in case cls of
JavaEnvironment.JavaSymbolClassNullaryFunction -> Optionals.cases mns (typeAppFallbackCast env aliases anns tyapps jatyp body correctedTyp cx g) (\ns_ ->
let classId = Utils.nameToJavaName aliases (elementsQualifiedName ns_)
methodId = Syntax.Identifier (Utils.sanitizeJavaName localName)
in (Eithers.bind (filterPhantomTypeArgs varName allTypeArgs cx g) (\filteredTypeArgs -> Eithers.bind (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt)))) filteredTypeArgs) (\jTypeArgs -> Right (Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs classId methodId jTypeArgs []))))))
JavaEnvironment.JavaSymbolClassHoistedLambda v0 -> Optionals.cases mns (typeAppFallbackCast env aliases anns tyapps jatyp body correctedTyp cx g) (\ns_ ->
let classId = Utils.nameToJavaName aliases (elementsQualifiedName ns_)
methodId = Syntax.Identifier (Utils.sanitizeJavaName localName)
in (Eithers.bind (filterPhantomTypeArgs varName allTypeArgs cx g) (\filteredTypeArgs -> Eithers.bind (Eithers.mapList (\t -> Eithers.bind (encodeType aliases Sets.empty t cx g) (\jt -> Eithers.bind (Utils.javaTypeToJavaReferenceType jt cx) (\rt -> Right (Syntax.TypeArgumentReference rt)))) filteredTypeArgs) (\jTypeArgs ->
let paramNames = Lists.map (\i -> Core.Name (Strings.cat2 "p" (Literals.showInt32 i))) (Math.range 0 (Math.sub v0 1))
paramExprs = Lists.map (\p -> Utils.javaIdentifierToJavaExpression (Utils.variableToJavaIdentifier p)) paramNames
call =
Utils.javaMethodInvocationToJavaExpression (Utils.methodInvocationStaticWithTypeArgs classId methodId jTypeArgs paramExprs)
in (Right (buildCurriedLambda paramNames call))))))
_ -> typeAppFallbackCast env aliases anns tyapps jatyp body correctedTyp cx g
typeArgsOrDiamond :: [Syntax.TypeArgument] -> Syntax.TypeArgumentsOrDiamond
typeArgsOrDiamond args =
Logic.ifElse (JavaEnvironment.javaFeaturesSupportsDiamondOperator javaFeatures) Syntax.TypeArgumentsOrDiamondDiamond (Syntax.TypeArgumentsOrDiamondArguments args)
typesMatch :: Core.Type -> Core.Type -> Bool
typesMatch a b =
case a of
Core.TypeVariable v0 -> case b of
Core.TypeVariable v1 -> Equality.equal v0 v1
_ -> True
Core.TypeWrap v0 -> case b of
Core.TypeWrap v1 -> Equality.equal v0 v1
_ -> True
_ -> True
unwrapReturnType :: Core.Type -> Core.Type
unwrapReturnType t =
case (Strip.deannotateType t) of
Core.TypeFunction v0 -> unwrapReturnType (Core.functionTypeCodomain v0)
Core.TypeApplication v0 -> unwrapReturnType (Core.applicationTypeArgument v0)
_ -> t
variantCompareToMethod :: JavaEnvironment.Aliases -> t0 -> Core.Name -> Core.Name -> [Core.FieldType] -> Syntax.ClassBodyDeclaration
variantCompareToMethod aliases tparams parentName variantName fields =
let anns =
[
Utils.overrideAnnotation,
Utils.suppressWarningsUncheckedAnnotation]
mods = [
Syntax.MethodModifierPublic]
param =
Utils.javaTypeToJavaFormalParameter (Utils.javaTypeFromTypeName aliases parentName) (Core.Name JavaNames.otherInstanceName)
result = Utils.javaTypeToJavaResult Utils.javaIntType
varTmpName = "o"
tagDeclStmt = Utils.variableDeclarationStatement aliases Utils.javaIntType (Utils.javaIdentifier "tagCmp") tagCompareExpr
tagReturnStmt =
Syntax.BlockStatementStatement (Syntax.StatementIfThen (Syntax.IfThenStatement {
Syntax.ifThenStatementExpression = tagCmpNotZeroExpr,
Syntax.ifThenStatementStatement = (Utils.javaReturnStatement (Just (Utils.javaExpressionNameToJavaExpression (Syntax.ExpressionName {
Syntax.expressionNameQualifier = Nothing,
Syntax.expressionNameIdentifier = (Utils.javaIdentifier "tagCmp")}))))}))
variantJavaType = Utils.javaTypeFromTypeName aliases variantName
castOtherExpr =
Utils.javaCastExpressionToJavaExpression (Utils.javaCastExpression (Utils.nameToJavaReferenceType aliases False [] variantName Nothing) (Utils.javaIdentifierToJavaUnaryExpression (Syntax.Identifier JavaNames.otherInstanceName)))
castDeclStmt = Utils.variableDeclarationStatement aliases variantJavaType (Utils.javaIdentifier varTmpName) castOtherExpr
emptyReturn = [
Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just (Utils.javaIntExpression 0)))]
valueCompareStmt =
Logic.ifElse (Lists.null fields) emptyReturn (Lists.concat2 [
castDeclStmt] (compareToBody aliases varTmpName fields))
body =
Lists.concat2 [
tagDeclStmt,
tagReturnStmt] valueCompareStmt
in (Utils.methodDeclaration mods [] anns JavaNames.compareToMethodName [
param] result (Just body))
visitBranch :: JavaEnvironment.JavaEnvironment -> JavaEnvironment.Aliases -> Core.Type -> Core.Name -> Syntax.Type -> [Syntax.TypeArgument] -> Core.CaseAlternative -> Typing.InferenceContext -> Graph.Graph -> Either Errors.Error Syntax.ClassBodyDeclarationWithComments
visitBranch env aliases dom tname jcod targs field cx g =
let jdom =
Syntax.TypeReference (Utils.nameToJavaReferenceType aliases True targs tname (Just (Formatting.capitalize (Core.unName (Core.caseAlternativeName field)))))
mods = [
Syntax.MethodModifierPublic]
anns = [
Utils.overrideAnnotation]
result = Syntax.ResultType (Syntax.UnannType jcod)
in case (Strip.deannotateTerm (Core.caseAlternativeHandler field)) of
Core.TermLambda v0 -> withLambda env v0 (\env2 ->
let lambdaParam = Core.lambdaParameter v0
body = Core.lambdaBody v0
env3 = insertBranchVar lambdaParam env2
in (Eithers.bind (analyzeJavaFunction env3 body cx g) (\fs ->
let bindings = Typing.functionStructureBindings fs
innerBody = Typing.functionStructureBody fs
env4 = Typing.functionStructureEnvironment fs
in (Eithers.bind (bindingsToStatements env4 bindings cx g) (\bindResult ->
let bindingStmts = Pairs.first bindResult
env5 = Pairs.second bindResult
in (Eithers.bind (encodeTerm env5 innerBody cx g) (\jret ->
let param = Utils.javaTypeToJavaFormalParameter jdom lambdaParam
returnStmt = Syntax.BlockStatementStatement (Utils.javaReturnStatement (Just jret))
allStmts = Lists.concat2 bindingStmts [
returnStmt]
in (Right (noComment (Utils.methodDeclaration mods [] anns JavaNames.visitMethodName [
param] result (Just allStmts)))))))))))
_ -> Left (Errors.ErrorOther (Errors.OtherError (Strings.cat2 "visitBranch: field term is not a lambda: " (ShowCore.term (Core.caseAlternativeHandler field)))))
withCommentString :: String -> Syntax.ClassBodyDeclaration -> Syntax.ClassBodyDeclarationWithComments
withCommentString comment decl =
Syntax.ClassBodyDeclarationWithComments {
Syntax.classBodyDeclarationWithCommentsValue = decl,
Syntax.classBodyDeclarationWithCommentsComments = (Just comment)}
withInterfaceCommentString :: String -> Syntax.InterfaceMemberDeclaration -> Syntax.InterfaceMemberDeclarationWithComments
withInterfaceCommentString comment decl =
Syntax.InterfaceMemberDeclarationWithComments {
Syntax.interfaceMemberDeclarationWithCommentsValue = decl,
Syntax.interfaceMemberDeclarationWithCommentsComments = (Just comment)}
withLambda :: JavaEnvironment.JavaEnvironment -> Core.Lambda -> (JavaEnvironment.JavaEnvironment -> t0) -> t0
withLambda env lam k =
Environment.withLambdaContext javaEnvGetGraph javaEnvSetGraph env lam (\env1 ->
let aliases = JavaEnvironment.javaEnvironmentAliases env1
aliases2 =
JavaEnvironment.Aliases {
JavaEnvironment.aliasesCurrentNamespace = (JavaEnvironment.aliasesCurrentNamespace aliases),
JavaEnvironment.aliasesPackages = (JavaEnvironment.aliasesPackages aliases),
JavaEnvironment.aliasesBranchVars = (JavaEnvironment.aliasesBranchVars aliases),
JavaEnvironment.aliasesRecursiveVars = (JavaEnvironment.aliasesRecursiveVars aliases),
JavaEnvironment.aliasesInScopeTypeParams = (JavaEnvironment.aliasesInScopeTypeParams aliases),
JavaEnvironment.aliasesPolymorphicLocals = (JavaEnvironment.aliasesPolymorphicLocals aliases),
JavaEnvironment.aliasesInScopeJavaVars = (JavaEnvironment.aliasesInScopeJavaVars aliases),
JavaEnvironment.aliasesVarRenames = (JavaEnvironment.aliasesVarRenames aliases),
JavaEnvironment.aliasesLambdaVars = (Sets.insert (Core.lambdaParameter lam) (JavaEnvironment.aliasesLambdaVars aliases)),
JavaEnvironment.aliasesTypeVarSubst = (JavaEnvironment.aliasesTypeVarSubst aliases),
JavaEnvironment.aliasesTrustedTypeVars = (JavaEnvironment.aliasesTrustedTypeVars aliases),
JavaEnvironment.aliasesMethodCodomain = (JavaEnvironment.aliasesMethodCodomain aliases),
JavaEnvironment.aliasesThunkedVars = (JavaEnvironment.aliasesThunkedVars aliases)}
env2 =
JavaEnvironment.JavaEnvironment {
JavaEnvironment.javaEnvironmentAliases = aliases2,
JavaEnvironment.javaEnvironmentGraph = (JavaEnvironment.javaEnvironmentGraph env1)}
in (k env2))
withTypeLambda :: JavaEnvironment.JavaEnvironment -> Core.TypeLambda -> (JavaEnvironment.JavaEnvironment -> t0) -> t0
withTypeLambda = Environment.withTypeLambdaContext javaEnvGetGraph javaEnvSetGraph
wrapInSupplierLambda :: Syntax.Expression -> Syntax.Expression
wrapInSupplierLambda expr =
Syntax.ExpressionLambda (Syntax.LambdaExpression {
Syntax.lambdaExpressionParameters = (Syntax.LambdaParametersTuple []),
Syntax.lambdaExpressionBody = (Syntax.LambdaBodyExpression expr)})
wrapLazyArguments :: Graph.Graph -> Core.Name -> [Syntax.Expression] -> ([Syntax.Expression], (Maybe String))
wrapLazyArguments g name args =
let lazyFlags = lazyFlagsForPrimitive g name
anyLazy = Lists.foldl (\b -> \f -> Logic.or b f) False lazyFlags
in (Logic.ifElse (Logic.and anyLazy (Equality.equal (Lists.length args) (Lists.length lazyFlags))) (
Lists.map (\pair -> Logic.ifElse (Pairs.second pair) (wrapInSupplierLambda (Pairs.first pair)) (Pairs.first pair)) (Lists.zip args lazyFlags),
(Just (Logic.ifElse (Equality.equal name (Core.Name "hydra.lib.logic.ifElse")) "lazy" "applyLazy"))) (args, Nothing))