packages feed

project-m36 1.2.0 → 1.2.3

raw patch · 23 files changed

+600/−190 lines, 23 filesdep ~aesondep ~basedep ~base16-bytestringPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: aeson, base, base16-bytestring, cassava, curryer-rpc, megaparsec, scotty, stm-containers, streamly, uuid, winery

API changes (from Hackage documentation)

- ProjectM36.RelationalExpression: addTargetTypeHints :: Attributes -> GraphRefRelationalExpr -> GraphRefRelationalExpr
+ ProjectM36.AtomFunctionError: AtomFunctionMissingReturnTypeError :: AtomFunctionError
+ ProjectM36.Base: LoadModuleWithFunctions :: ModuleBody -> DatabaseContextIOExprBase a
+ ProjectM36.Base: type ModuleBody = StringType
+ ProjectM36.Base: type ModuleBodyScript = StringType
+ ProjectM36.Client: LoadModuleWithFunctions :: ModuleBody -> DatabaseContextIOExprBase a
+ ProjectM36.Error: ModuleLoadError :: ScriptCompilationError
+ ProjectM36.Function: convType :: AtomType -> String
+ ProjectM36.Function: wrapAtomArguments :: [AtomType] -> String
+ ProjectM36.Function: wrapAtomFunction :: [AtomType] -> FunctionName -> Either RelationalError String
+ ProjectM36.Function: wrapDatabaseContextFunction :: [AtomType] -> FunctionName -> String
+ ProjectM36.Module: DatabaseContextFunctionMonadEnv :: DatabaseContextFunctionUtils -> DatabaseContextFunctionMonadEnv
+ ProjectM36.Module: DeclareAtomFunction :: a -> DeclareFunctionBase a
+ ProjectM36.Module: DeclareDatabaseContextFunction :: a -> DBCFunctionAccessControlList -> DeclareFunctionBase a
+ ProjectM36.Module: [utils] :: DatabaseContextFunctionMonadEnv -> DatabaseContextFunctionUtils
+ ProjectM36.Module: data DeclareFunctionBase a
+ ProjectM36.Module: declareAtomFunction :: FunctionName -> EntryPoints ()
+ ProjectM36.Module: declareDatabaseContextFunction :: FunctionName -> DBCFunctionAccessControlList -> EntryPoints ()
+ ProjectM36.Module: executeDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContextFunctionMonad ()
+ ProjectM36.Module: executeRelationalExpr :: RelationalExpr -> DatabaseContextFunctionMonad Relation
+ ProjectM36.Module: instance GHC.Show.Show a => GHC.Show.Show (ProjectM36.Module.DeclareFunctionBase a)
+ ProjectM36.Module: newtype DatabaseContextFunctionMonadEnv
+ ProjectM36.Module: runDatabaseContextFunctionMonad :: DatabaseContextFunctionMonadEnv -> DatabaseContext -> DatabaseContextFunctionMonad () -> Either RelationalError DatabaseContext
+ ProjectM36.Module: runEntryPoints :: EntryPoints () -> [DeclareFunction]
+ ProjectM36.Module: type DatabaseContextFunctionMonad a = RWST DatabaseContextFunctionMonadEnv () DatabaseContext (ExceptT RelationalError Identity) a
+ ProjectM36.Module: type DeclareFunction = DeclareFunctionBase FunctionName
+ ProjectM36.Module: type EntryPoints = Writer [DeclareFunction]
+ ProjectM36.RelationalExpression: MkAtomFunction :: AtomFunction -> MkFunction
+ ProjectM36.RelationalExpression: MkDatabaseContextFunction :: DatabaseContextFunction -> MkFunction
+ ProjectM36.RelationalExpression: data MkFunction
+ ProjectM36.RelationalExpression: importModuleFromPath :: ScriptSession -> ModuleBody -> DatabaseContextIOEvalMonad ()
+ ProjectM36.RelationalExpression: typeForGraphRefRelationalExpr' :: Maybe Attributes -> GraphRefRelationalExpr -> GraphRefRelationalExprM Relation
+ ProjectM36.ScriptSession: UnsupportedTypeConversionError :: String -> TypeConversionError
+ ProjectM36.ScriptSession: convertGhcTypeToDatabaseContextFunctionAtomType :: DynFlags -> [(Type, AtomType)] -> Type -> Type -> Either TypeConversionError [AtomType]
+ ProjectM36.ScriptSession: convertGhcTypeToFunctionAtomType :: DynFlags -> [(Type, AtomType)] -> Type -> Either TypeConversionError [AtomType]
+ ProjectM36.ScriptSession: data TypeConversionError
+ ProjectM36.ScriptSession: findTypeConv :: DynFlags -> Type -> [(Type, AtomType)] -> Either TypeConversionError AtomType
+ ProjectM36.ScriptSession: getHomeUnitId :: ScriptSession -> UnitId
+ ProjectM36.ScriptSession: instance GHC.Show.Show ProjectM36.ScriptSession.TypeConversionError
+ ProjectM36.ScriptSession: mkTypeConversions :: GhcMonad m => m [(Type, AtomType)]
+ ProjectM36.ScriptSession: pprShow :: Outputable a => a -> DynFlags -> String
+ ProjectM36.ScriptSession: safeImportDecl :: String -> Maybe String -> ImportDecl (GhcPass 'Parsed)
- ProjectM36.Base: AddInclusionDependencyF :: Text -> InclusionDependency -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AddInclusionDependencyF :: Text -> InclusionDependency -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: AddNotificationF :: Text -> RelationalExprBase () -> RelationalExprBase () -> RelationalExprBase () -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AddNotificationF :: Text -> RelationalExprBase () -> RelationalExprBase () -> RelationalExprBase () -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: AddRegisteredQueryF :: Text -> RelationalExprBase () -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AddRegisteredQueryF :: Text -> RelationalExprBase () -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: AddTypeConstructorF :: TypeConstructorDef -> [DataConstructorDef] -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AddTypeConstructorF :: TypeConstructorDef -> [DataConstructorDef] -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: AlterACLF :: AlterDBCACLExprBase r_aF1t -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AlterACLF :: AlterDBCACLExprBase r_aFch -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: AssignF :: Text -> RelationalExprBase a_aF1s -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: AssignF :: Text -> RelationalExprBase a_aFcg -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: DefineF :: Text -> [AttributeExprBase a_aF1s] -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: DefineF :: Text -> [AttributeExprBase a_aFcg] -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: DeleteF :: Text -> RestrictionPredicateExprBase a_aF1s -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: DeleteF :: Text -> RestrictionPredicateExprBase a_aFcg -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: DifferenceF :: r_aQAc -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: DifferenceF :: r_aQNe -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: EqualsF :: r_aQAc -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: EqualsF :: r_aQNe -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: ExecuteDatabaseContextFunctionF :: Text -> [AtomExprBase a_aF1s] -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: ExecuteDatabaseContextFunctionF :: Text -> [AtomExprBase a_aFcg] -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: ExistingRelationF :: Relation -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: ExistingRelationF :: Relation -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: ExtendF :: ExtendTupleExprBase a_aF1x -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: ExtendF :: ExtendTupleExprBase a_aFcl -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: GrantAccessExprF :: r_aEXM -> SomePermission -> Bool -> AlterDBCACLExprBaseF (r_aEXM :: Type) r_aRVC
+ ProjectM36.Base: GrantAccessExprF :: r_aF8A -> SomePermission -> Bool -> AlterDBCACLExprBaseF (r_aF8A :: Type) r_aS8E
- ProjectM36.Base: GrantDBCFunctionAccessExprF :: r_aEXM -> Text -> DBCFunctionPermission -> Bool -> AlterDBCACLExprBaseF (r_aEXM :: Type) r_aRVC
+ ProjectM36.Base: GrantDBCFunctionAccessExprF :: r_aF8A -> Text -> DBCFunctionPermission -> Bool -> AlterDBCACLExprBaseF (r_aF8A :: Type) r_aS8E
- ProjectM36.Base: GroupF :: AttributeNamesBase a_aF1x -> Text -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: GroupF :: AttributeNamesBase a_aFcl -> Text -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: InsertF :: Text -> RelationalExprBase a_aF1s -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: InsertF :: Text -> RelationalExprBase a_aFcg -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: JoinF :: r_aQAc -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: JoinF :: r_aQNe -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: MakeRelationFromExprsF :: Maybe [AttributeExprBase a_aF1x] -> TupleExprsBase a_aF1x -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: MakeRelationFromExprsF :: Maybe [AttributeExprBase a_aFcl] -> TupleExprsBase a_aFcl -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: MakeStaticRelationF :: Attributes -> RelationTupleSet -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: MakeStaticRelationF :: Attributes -> RelationTupleSet -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: MultipleExprF :: [r_aRgI] -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: MultipleExprF :: [r_aRtK] -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: NoOperationF :: DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: NoOperationF :: DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: NotEqualsF :: r_aQAc -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: NotEqualsF :: r_aQNe -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: ProjectF :: AttributeNamesBase a_aF1x -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: ProjectF :: AttributeNamesBase a_aFcl -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: RelationValuedAttributeF :: Text -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: RelationValuedAttributeF :: Text -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: RelationVariableF :: Text -> a_aF1x -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: RelationVariableF :: Text -> a_aFcl -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: RemoveAtomFunctionF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveAtomFunctionF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RemoveDatabaseContextFunctionF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveDatabaseContextFunctionF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RemoveInclusionDependencyF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveInclusionDependencyF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RemoveNotificationF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveNotificationF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RemoveRegisteredQueryF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveRegisteredQueryF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RemoveTypeConstructorF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: RemoveTypeConstructorF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: RenameF :: Set (Text, Text) -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: RenameF :: Set (Text, Text) -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: RestrictF :: RestrictionPredicateExprBase a_aF1x -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: RestrictF :: RestrictionPredicateExprBase a_aFcl -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: RevokeAccessExprF :: r_aEXM -> SomePermission -> AlterDBCACLExprBaseF (r_aEXM :: Type) r_aRVC
+ ProjectM36.Base: RevokeAccessExprF :: r_aF8A -> SomePermission -> AlterDBCACLExprBaseF (r_aF8A :: Type) r_aS8E
- ProjectM36.Base: RevokeDBCFunctionAccessExprF :: r_aEXM -> Text -> DBCFunctionPermission -> AlterDBCACLExprBaseF (r_aEXM :: Type) r_aRVC
+ ProjectM36.Base: RevokeDBCFunctionAccessExprF :: r_aF8A -> Text -> DBCFunctionPermission -> AlterDBCACLExprBaseF (r_aF8A :: Type) r_aS8E
- ProjectM36.Base: UndefineF :: Text -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: UndefineF :: Text -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: UngroupF :: Text -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: UngroupF :: Text -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: UnionF :: r_aQAc -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: UnionF :: r_aQNe -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: UpdateF :: Text -> Map Text (AtomExprBase ()) -> RestrictionPredicateExprBase a_aF1s -> DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: UpdateF :: Text -> Map Text (AtomExprBase ()) -> RestrictionPredicateExprBase a_aFcg -> DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: WithF :: [(WithNameExprBase a_aF1x, r_aQAc)] -> r_aQAc -> RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: WithF :: [(WithNameExprBase a_aFcl, r_aQNe)] -> r_aQNe -> RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.Base: data AlterDBCACLExprBaseF (r_aEXM :: Type) r_aRVC
+ ProjectM36.Base: data AlterDBCACLExprBaseF (r_aF8A :: Type) r_aS8E
- ProjectM36.Base: data DatabaseContextExprBaseF (a_aF1s :: Type) (r_aF1t :: Type) r_aRgI
+ ProjectM36.Base: data DatabaseContextExprBaseF (a_aFcg :: Type) (r_aFch :: Type) r_aRtK
- ProjectM36.Base: data RelationalExprBaseF (a_aF1x :: Type) r_aQAc
+ ProjectM36.Base: data RelationalExprBaseF (a_aFcl :: Type) r_aQNe
- ProjectM36.SQL.Select: BetweenOperatorF :: r_a1bp0 -> r_a1bp0 -> r_a1bp0 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: BetweenOperatorF :: r_a1bCj -> r_a1bCj -> r_a1bCj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: BinaryOperatorF :: r_a1bp0 -> OperatorName -> r_a1bp0 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: BinaryOperatorF :: r_a1bCj -> OperatorName -> r_a1bCj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: BooleanLiteralF :: Bool -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: BooleanLiteralF :: Bool -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: BooleanOperatorExprF :: r_a1bp0 -> BoolOp -> r_a1bp0 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: BooleanOperatorExprF :: r_a1bCj -> BoolOp -> r_a1bCj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: CaseExprF :: [(r_a1bp0, r_a1bp0)] -> Maybe r_a1bp0 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: CaseExprF :: [(r_a1bCj, r_a1bCj)] -> Maybe r_a1bCj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: DoubleLiteralF :: Double -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: DoubleLiteralF :: Double -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: ExistsExprF :: Select -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: ExistsExprF :: Select -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: FunctionApplicationF :: FuncName -> [r_a1bp0] -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: FunctionApplicationF :: FuncName -> [r_a1bCj] -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: IdentifierF :: n_a1130 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: IdentifierF :: n_a11gj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: InExprF :: InFlag -> r_a1bp0 -> InPredicateValue -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: InExprF :: InFlag -> r_a1bCj -> InPredicateValue -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: IntegerLiteralF :: Integer -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: IntegerLiteralF :: Integer -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: NullLiteralF :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: NullLiteralF :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: PostfixOperatorF :: r_a1bp0 -> OperatorName -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: PostfixOperatorF :: r_a1bCj -> OperatorName -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: PrefixOperatorF :: OperatorName -> r_a1bp0 -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: PrefixOperatorF :: OperatorName -> r_a1bCj -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: QuantifiedComparisonF :: r_a1bp0 -> ComparisonOperator -> QuantifiedComparisonPredicate -> Select -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: QuantifiedComparisonF :: r_a1bCj -> ComparisonOperator -> QuantifiedComparisonPredicate -> Select -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: StringLiteralF :: Text -> ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: StringLiteralF :: Text -> ScalarExprBaseF (n_a11gj :: Type) r_a1bCj
- ProjectM36.SQL.Select: [caseElseF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> Maybe r_a1bp0
+ ProjectM36.SQL.Select: [caseElseF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> Maybe r_a1bCj
- ProjectM36.SQL.Select: [caseWhensF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> [(r_a1bp0, r_a1bp0)]
+ ProjectM36.SQL.Select: [caseWhensF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> [(r_a1bCj, r_a1bCj)]
- ProjectM36.SQL.Select: [qcExprF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> r_a1bp0
+ ProjectM36.SQL.Select: [qcExprF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> r_a1bCj
- ProjectM36.SQL.Select: [qcOperatorF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> ComparisonOperator
+ ProjectM36.SQL.Select: [qcOperatorF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> ComparisonOperator
- ProjectM36.SQL.Select: [qcPredicateF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> QuantifiedComparisonPredicate
+ ProjectM36.SQL.Select: [qcPredicateF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> QuantifiedComparisonPredicate
- ProjectM36.SQL.Select: [qcQueryF] :: ScalarExprBaseF (n_a1130 :: Type) r_a1bp0 -> Select
+ ProjectM36.SQL.Select: [qcQueryF] :: ScalarExprBaseF (n_a11gj :: Type) r_a1bCj -> Select
- ProjectM36.SQL.Select: data ScalarExprBaseF (n_a1130 :: Type) r_a1bp0
+ ProjectM36.SQL.Select: data ScalarExprBaseF (n_a11gj :: Type) r_a1bCj

Files

Changelog.markdown view
@@ -1,3 +1,12 @@+# 2026-02-09 (v1.2.3)++* add support for importing whole Haskell modules for easier application logic programming+	+# 2026-01-15 (v1.2.1)++* fix critical type resolution error in MakeRelationFromExprs+* upgrade to crypton 1.8.0 and friends+ # 2026-01-06 (v1.2.0)  * add LRU result caching layer
README.markdown view
@@ -99,6 +99,7 @@ 1. [Basic Operator Benchmarks](https://rawgit.com/agentm/project-m36/master/docs/basic_benchmarks.html) 1. [Merkle Transaction Hashes](docs/merkle_transaction_graph.markdown) 1. [Handling DDL Changes](docs/Handling_DDL_Changes.markdown)+1. [Importing a Haskell Module](docs/import_haskell_module.markdown)  ### Integrations 
examples/blog.hs view
@@ -2,7 +2,6 @@ {-# LANGUAGE DeriveAnyClass, DeriveGeneric, OverloadedStrings, CPP, DerivingVia #-}  import ProjectM36.Client-import ProjectM36.Base import ProjectM36.Relation import ProjectM36.Tupleable import ProjectM36.Atom (relationForAtom)@@ -20,7 +19,7 @@ import Control.Monad (when, forM_) import Codec.Winery -import Web.Scotty as S+import qualified Web.Scotty as S import Text.Blaze.Html5 (h1, h2, h3, p, form, input, (!), toHtml, Html, a, toValue, hr, textarea) import Text.Blaze.Html5.Attributes (name, href, type_, method, action, value) import Text.Blaze.Html.Renderer.Text@@ -83,7 +82,7 @@   createSchema sessionId conn     insertSampleData sessionId conn   --create the web routes-  scotty 3000 $ do+  S.scotty 3000 $ do     S.get "/" (listBlogs sessionId conn)     S.get "/blog/:blogid" (showBlogEntry sessionId conn)     S.post "/comment" (addComment sessionId conn)@@ -126,45 +125,45 @@   handleIOError $ executeDatabaseContextExpr sessionId conn insertCommentsExpr    -- handle relational errors with scotty-handleWebError :: Either RelationalError a -> ActionM a +handleWebError :: Either RelationalError a -> S.ActionM a  handleWebError (Left err) = render500 (toHtml (show err)) >> pure (error "bad") handleWebError (Right v) = pure v  -- show a page with all the blog entries-listBlogs :: SessionId -> Connection -> ActionM ()+listBlogs :: SessionId -> Connection -> S.ActionM () listBlogs sessionId conn = do-  eRel <- liftIO $ executeRelationalExpr sessionId conn (RelationVariable "blog" ())+  eRel <- S.liftIO $ executeRelationalExpr sessionId conn (RelationVariable "blog" ())   case eRel of     Left err -> render500 (toHtml (show err))     Right blogRel -> do-      blogs <- liftIO (toList blogRel) >>= mapM (handleWebError . fromTuple) :: ActionM [Blog]+      blogs <- S.liftIO (toList blogRel) >>= mapM (handleWebError . fromTuple) :: S.ActionM [Blog]       let sortedBlogs = sortBy (\b1 b2 -> tstamp b1 `compare` tstamp b2) blogs-      html . renderHtml $ do+      S.html . renderHtml $ do         h1 "Blog Posts"         forM_ sortedBlogs $ \blog -> a ! href (toValue $ "/blog/" <> title blog) $ h2 (toHtml (title blog)) -render500 :: Html -> ActionM ()+render500 :: Html -> S.ActionM () render500 msg = do -  html . renderHtml $ do+  S.html . renderHtml $ do     h1 "Internal Server Error"       p msg-  status internalServerError500+  S.status internalServerError500    --display one blog post along with its comments-showBlogEntry :: SessionId -> Connection -> ActionM ()+showBlogEntry :: SessionId -> Connection -> S.ActionM () showBlogEntry sessionId conn = do-  blogid <- pathParam "blogid"+  blogid <- S.pathParam "blogid"   --query the database to return the blog entry with a relation-valued attribute of the associated comments   let blogRestrictionExpr = AttributeEqualityPredicate "title" (NakedAtomExpr (TextAtom blogid))       extendExpr = AttributeExtendTupleExpr "comments" (RelationAtomExpr commentsRestriction)       commentsRestriction = Restrict                            (AttributeEqualityPredicate "blogTitle" (AttributeAtomExpr "title"))                            (RelationVariable "comment" ())-  eRel <- liftIO $ executeRelationalExpr sessionId conn (Extend extendExpr +  eRel <- S.liftIO $ executeRelationalExpr sessionId conn (Extend extendExpr                                                           (Restrict                                                            blogRestrictionExpr                                                            (RelationVariable "blog" ())))-  let render = html . renderHtml+  let render = S.html . renderHtml       formatStamp = iso8601Show --formatTime defaultTimeLocale (iso8601DateFormat (Just "%H:%M:%S"))   case eRel of      Left err -> render500 (toHtml (show err))@@ -172,14 +171,14 @@     Right rel -> case singletonTuple rel of       Nothing -> do --no results for this blog id         render (h1 "No such blog post")-        status status404+        S.status status404       Just blogTuple -> case fromTuple blogTuple of --just one blog post found- it's a match!         Left err -> render500 (toHtml (show err))         Right blog -> do           --extract comments for the blog           commentsAtom <- handleWebError (atomForAttributeName "comments" blogTuple)           commentsRel <- handleWebError (relationForAtom commentsAtom)-          comments <- liftIO (toList commentsRel) >>= mapM (handleWebError . fromTuple) :: ActionM [Comment]+          comments <- S.liftIO (toList commentsRel) >>= mapM (handleWebError . fromTuple) :: S.ActionM [Comment]           let commentsSorted = sortBy (\c1 c2 -> commentTime c1 `compare` commentTime c2) comments           render $ do             --show blog details@@ -201,20 +200,20 @@               input ! type_ "submit"              --add a comment to a blog post-addComment :: SessionId -> Connection -> ActionM ()            +addComment :: SessionId -> Connection -> S.ActionM ()             addComment sessionId conn = do-  blogid <- pathParam "blogid"-  commentText <- formParam "contents"-  now <- liftIO getCurrentTime+  blogid <- S.pathParam "blogid"+  commentText <- S.formParam "contents"+  now <- S.liftIO getCurrentTime      case toInsertExpr [Comment {blogTitle = blogid,                               commentTime = now,                               contents = commentText }] "comment" of     Left err -> handleWebError (Left err)     Right insertExpr -> do      -      eRet <- liftIO (withTransaction sessionId conn (executeDatabaseContextExpr sessionId conn insertExpr) (commit sessionId conn))+      eRet <- S.liftIO (withTransaction sessionId conn (executeDatabaseContextExpr sessionId conn insertExpr) (commit sessionId conn))       case eRet of         Left err -> handleWebError (Left err)         Right _ ->-          redirect (TL.fromStrict ("/blog/" <> blogid))+          S.redirect (TL.fromStrict ("/blog/" <> blogid))       
examples/hair.hs view
@@ -2,7 +2,7 @@ import ProjectM36.Client import ProjectM36.Relation.Show.Term import GHC.Generics-import Data.Text+import Data.Text (Text) import Control.DeepSeq import qualified Data.Map as M import qualified Data.Text.IO as TIO
examples/zoo.hs view
@@ -11,6 +11,7 @@ import Data.Time.Calendar import qualified Data.Text.IO as T +--TODO add dbc func ACLs data Ticket = Ticket   { ticketId   :: Integer   , visitorAge :: Integer    -- years
project-m36.cabal view
@@ -1,6 +1,6 @@ Cabal-Version: 2.2 Name: project-m36-Version: 1.2.0+Version: 1.2.3 License: MIT --note that this license specification is erroneous and only labeled MIT to appease hackage which does not recognize public domain packages in cabal >2.2- Project:M36 is dedicated to the public domain Build-Type: Simple@@ -91,7 +91,7 @@                   cryptohash-sha256,                   text-manipulate >= 0.2.0.1 && < 0.4,                   winery >= 1.4,-                  curryer-rpc>=0.5.0,+                  curryer-rpc>=0.5.1,                   network,                   async,                   vector-instances,@@ -245,7 +245,8 @@                      ProjectM36.AccessControlList,                      ProjectM36.AccessControl,                      ProjectM36.LoginRoles,-                     ProjectM36.PrettyBytes+                     ProjectM36.PrettyBytes,+                     ProjectM36.Module     GHC-Options: -Wall -rdynamic     if os(windows)       Build-Depends: Win32 >= 2.12@@ -582,6 +583,25 @@     main-is: TutorialD/Interpreter/Import/ImportTest.hs     Other-Modules: TutorialD.Interpreter.Base, TutorialD.Interpreter.Import.Base, TutorialD.Interpreter.Import.TutorialD, TutorialD.Interpreter.RelationalExpr, TutorialD.Interpreter.Types, TutorialD.Interpreter.DatabaseContextExpr, TutorialD.Interpreter.Import.BasicExamples, TutorialD.Printer +Test-Suite test-tutoriald-import-module+    import: commontest+    type: exitcode-stdio-1.0+    main-is: TutorialD/Interpreter/Module.hs+    if flag(haskell-scripting)+        CPP-Options: -DPM36_HASKELL_SCRIPTING+    Other-Modules: TutorialD.Interpreter.Base, TutorialD.Interpreter.Import.Base, TutorialD.Interpreter.Import.TutorialD, TutorialD.Interpreter.RelationalExpr, TutorialD.Interpreter.Types, TutorialD.Interpreter.DatabaseContextExpr, TutorialD.Interpreter.Import.BasicExamples, TutorialD.Printer,         TutorialD.Interpreter,+        TutorialD.Interpreter.DatabaseContextIOOperator,+        TutorialD.Interpreter.Export.Base,+        TutorialD.Interpreter.Export.CSV,+        TutorialD.Interpreter.Import.CSV,+        TutorialD.Interpreter.InformationOperator,+        TutorialD.Interpreter.LoginRolesOperator,+        TutorialD.Interpreter.RODatabaseContextOperator,+        TutorialD.Interpreter.SchemaOperator,+        TutorialD.Interpreter.TestBase,+        TutorialD.Interpreter.TransGraphRelationalOperator,+        TutorialD.Interpreter.TransactionGraphOperator+ Test-Suite test-relation-export-csv     import: commontest     type: exitcode-stdio-1.0@@ -656,7 +676,7 @@ Executable Example-Blog     Default-Language: Haskell2010     Default-Extensions: OverloadedStrings-    Build-Depends: base, HUnit, Cabal, containers, hashable, unordered-containers, mtl, vector, time, bytestring, uuid, stm, deepseq, deepseq-generics,parallel, cassava, attoparsec, gnuplot, directory, temporary, haskeline, megaparsec, text, base64-bytestring, data-interval, filepath, transformers, stm-containers, list-t, aeson, path-pieces, either, conduit, http-api-data, template-haskell, ghc, ghc-paths, project-m36, scotty >= 0.22, blaze-html, http-types, winery, random+    Build-Depends: base, HUnit, Cabal, containers, hashable, unordered-containers, mtl, vector, time, bytestring, uuid, stm, deepseq, deepseq-generics,parallel, cassava, attoparsec, gnuplot, directory, temporary, haskeline, megaparsec, text, base64-bytestring, data-interval, filepath, transformers, stm-containers, list-t, aeson, path-pieces, either, conduit, http-api-data, template-haskell, ghc, ghc-paths, project-m36, scotty >= 0.30, blaze-html, http-types, winery, random     Main-Is: examples/blog.hs     GHC-Options: -Wall -threaded @@ -833,4 +853,3 @@         TutorialD.Interpreter.TransactionGraphOperator         TutorialD.Interpreter.Types         TutorialD.Printer- 
src/bin/ProjectM36/Interpreter.hs view
@@ -6,7 +6,6 @@ import ProjectM36.DataFrame import Text.Megaparsec import Data.Void-import Data.Text import GHC.Generics import qualified Data.Text.IO as TIO import qualified Data.Text as T@@ -16,8 +15,8 @@ import ProjectM36.Relation.Show.Term import ProjectM36.Relation -type Parser = Parsec Void Text-type ParserError = ParseErrorBundle Text Void+type Parser = Parsec Void T.Text+type ParserError = ParseErrorBundle T.Text Void type PromptLength = Int  data SafeEvaluationFlag = SafeEvaluation | UnsafeEvaluation deriving (Eq)@@ -27,7 +26,7 @@                      DisplayIOResult (IO ()) |                      DisplayRelationResult Relation |                      DisplayDataFrameResult DataFrame |-                     DisplayHintWith Text ConsoleResult |+                     DisplayHintWith T.Text ConsoleResult |                      DisplayErrorResult StringType |                      DisplayRelationalErrorResult RelationalError |                      DisplayParseErrorResult (Maybe PromptLength) ParserError | -- PromptLength refers to length of prompt text
src/bin/TutorialD/Interpreter/DatabaseContextIOOperator.hs view
@@ -12,7 +12,8 @@ data DatabaseContextIOOperator =   DatabaseContextIOOp DatabaseContextIOExpr |   LoadAtomFunctionFromFileOp FunctionName [TypeConstructor] FilePath |-  LoadDatabaseContextFunctionFromFileOp FunctionName [TypeConstructor] FilePath+  LoadDatabaseContextFunctionFromFileOp FunctionName [TypeConstructor] FilePath |+  LoadModuleFromFileOp FilePath   deriving (Show, Eq)  addAtomFunctionExprP :: Parser DatabaseContextIOExpr@@ -52,7 +53,8 @@ databaseContextIOOperatorP =    (DatabaseContextIOOp <$> databaseContextIOExprP) <|>   (reserved "loadatomfunctionfromfile" >> (LoadAtomFunctionFromFileOp <$> quotedString <*> atomTypeSignatureP <*> quotedFilePath)) <|>-  (reserved "loaddatabasecontextfunctionfromfile" >> (LoadDatabaseContextFunctionFromFileOp <$> quotedString <*> atomTypeSignatureP <*> quotedFilePath))+  (reserved "loaddatabasecontextfunctionfromfile" >> (LoadDatabaseContextFunctionFromFileOp <$> quotedString <*> atomTypeSignatureP <*> quotedFilePath)) <|>+  loadModuleFromFileP    loadAtomFunctionsP :: Parser DatabaseContextIOExpr loadAtomFunctionsP = do@@ -63,17 +65,22 @@ loadDatabaseContextFunctionsP = do   reserved "loaddatabasecontextfunctions"   LoadDatabaseContextFunctions <$> quotedString <*> quotedString <*> fmap unpack quotedString++loadModuleFromFileP :: Parser DatabaseContextIOOperator+loadModuleFromFileP = do+  reserved "loadmodulefromfile"+  LoadModuleFromFileOp <$> quotedFilePath                                               interpretDatabaseContextIOOperator :: DatabaseContextIOOperator -> IO (Either RelationalError DatabaseContextIOExpr) interpretDatabaseContextIOOperator expr = do   let loadFromFile typ functionName functionArgs functionFilePath = do-        let handler :: IOException -> IO (Either RelationalError Text)-            handler e = pure (Left (ImportError (ImportFileError (T.pack (displayException e)))))-        eFuncBody <- handle handler (Right <$> TIO.readFile functionFilePath)+        eFuncBody <- handle ioExcHandler (Right <$> TIO.readFile functionFilePath)         case eFuncBody of           Left err -> pure (Left err)           Right functionBody ->             pure (Right (typ functionName functionArgs functionBody))+      ioExcHandler :: IOException -> IO (Either RelationalError Text)+      ioExcHandler e = pure (Left (ImportError (ImportFileError (T.pack (displayException e)))))            case expr of     DatabaseContextIOOp expr' ->@@ -82,5 +89,12 @@       loadFromFile AddAtomFunction functionName functionArgs functionFilePath     LoadDatabaseContextFunctionFromFileOp functionName functionArgs functionFilePath ->       loadFromFile AddDatabaseContextFunction functionName functionArgs functionFilePath+    -- pass module contents via Text so that remote client can upload a module, duh+    LoadModuleFromFileOp modPath -> do+      eModBody <- handle ioExcHandler (Right <$> TIO.readFile modPath)+      case eModBody of+        Left err -> pure (Left err)+        Right modBody ->+          pure (Right (LoadModuleWithFunctions modBody))  
src/bin/benchmark/bigrel.hs view
@@ -23,7 +23,7 @@ import qualified Data.Text.IO as TIO import System.IO import Control.DeepSeq-import Data.Text hiding (map)+import Data.Text (Text, pack) import Data.Time.Clock import Data.UUID.V4 import qualified ProjectM36.DatabaseContextFunctionUtils as Util
src/lib/ProjectM36/AtomFunctionError.hs view
@@ -7,6 +7,7 @@ data AtomFunctionError = AtomFunctionUserError String |                          AtomFunctionTypeMismatchError |                          AtomFunctionParseError String |+                         AtomFunctionMissingReturnTypeError |                          InvalidIntervalOrderingError |                          InvalidIntervalBoundariesError |                          AtomFunctionAttributeNameNotFoundError Text |
src/lib/ProjectM36/Base.hs view
@@ -402,9 +402,12 @@   LoadAtomFunctions ObjModuleName ObjFunctionName FilePath |   AddDatabaseContextFunction FunctionName [TypeConstructor] FunctionBodyScript |   LoadDatabaseContextFunctions ObjModuleName ObjFunctionName FilePath |+  LoadModuleWithFunctions ModuleBody |   CreateArbitraryRelation RelVarName [AttributeExprBase a] Range                            deriving (Show, Eq, Generic) +type ModuleBody = StringType+ type GraphRefDatabaseContextIOExpr = DatabaseContextIOExprBase GraphRefTransactionMarker  type DatabaseContextIOExpr = DatabaseContextIOExprBase ()@@ -545,6 +548,7 @@  type FunctionName = StringType type FunctionBodyScript = StringType+type ModuleBodyScript = StringType  -- | Represents stored, user-created or built-in functions which can operates of types such as Atoms or DatabaseContexts. data Function a acl = Function {
src/lib/ProjectM36/Error.hs view
@@ -155,7 +155,8 @@ data ScriptCompilationError = TypeCheckCompilationError String String | --expected, got                               SyntaxErrorCompilationError String |                               ScriptCompilationDisabledError |-                              OtherScriptCompilationError String+                              OtherScriptCompilationError String |+                              ModuleLoadError                             deriving (Show, Eq, Generic, Typeable, NFData)                                       instance Exception ScriptCompilationError
src/lib/ProjectM36/Function.hs view
@@ -1,10 +1,13 @@ -- | Module for functionality common between the various Function types (AtomFunction, DatabaseContextFunction).+{-# LANGUAGE TypeApplications #-} module ProjectM36.Function where import ProjectM36.Base import ProjectM36.Error---import ProjectM36.Serialise.Base ()+import ProjectM36.AtomFunctionError (AtomFunctionError(AtomFunctionMissingReturnTypeError)) import ProjectM36.ScriptSession import qualified Data.HashSet as HS+import Data.List (intercalate)+import qualified Data.Text as T  -- for merkle hash                        @@ -56,3 +59,58 @@   case HS.toList $ HS.filter (\f -> funcName f == funcName') funcSet of     [] -> Left $ NoSuchFunctionError funcName'     x : _ -> Right x++{-+  \[IntegerAtom val1, IntegerAtom val2] -> +     Right $ IntegerAtom $ apply_discount val1 val2+-}+wrapAtomFunction :: [AtomType] -> FunctionName -> Either RelationalError String+wrapAtomFunction aType@(_:_) funcName' =+  pure $+  -- we have to make a string-based, dynamic wrapper since we need to get a consistent function type out of the code+  -- there's no value in having an AtomFunction with no return type, so there must be a list with at least one value+    "\\[" <>+    wrapAtomArguments aType <>+    "] -> Right $ " <> +    convType (last aType) <>+    " $ " <>+    T.unpack funcName' <>+    " " <>+    unwords (map (\i -> "val" <> show i) [1 .. length aType - 1])+wrapAtomFunction [] _ = Left (AtomFunctionUserError AtomFunctionMissingReturnTypeError)++-- | convert an AtomType into its constituent String value for use in constructing the Haskell scripting utility wrapper.+convType :: AtomType -> String+convType typ =+  case typ of+    IntegerAtomType -> "IntegerAtom"+    IntAtomType -> "IntAtom"+    ScientificAtomType -> "ScientificAtom"+    DoubleAtomType -> "DoubleAtom"+    TextAtomType -> "TextAtom"+    DayAtomType -> "DayAtom"+    DateTimeAtomType -> "DateTimeAtom"+    ByteStringAtomType -> "ByteStringAtom"+    BoolAtomType -> "BoolAtom"+    UUIDAtomType -> "UUIDAtom"+    RelationAtomType _ -> "RelationAtom" +    SubrelationFoldAtomType _ -> "SubrelationFoldAtom" -- probably won't work+    ConstructedAtomType _ _ -> "ConstructedAtom" -- needs more work to render full atom metadata+    RelationalExprAtomType -> "RelationalExprAtom"+    TypeVariableType _ -> "" -- nonsense+    ++wrapAtomArguments :: [AtomType] -> String+wrapAtomArguments atomArgs =+  intercalate "," (zipWith (\i c -> convType c <> " val" <> show @Int i) [1 ..] (init atomArgs))++wrapDatabaseContextFunction :: [AtomType] -> FunctionName -> String+wrapDatabaseContextFunction aType funcName' =+  "\\dbcfuncutils [" <>+  wrapAtomArguments (aType <> [TypeVariableType "databaseContextFunctionMonad"]) <> -- last type is throwaway+  "] dbContext -> " <>+  "let env = DatabaseContextFunctionMonadEnv dbcfuncutils in\n" <>+  "runDatabaseContextFunctionMonad env dbContext $ do\n" <>+  "  " <> T.unpack funcName' <> " " <>+  unwords (map (\i -> "val" <> show i) [1 .. length aType])+  
+ src/lib/ProjectM36/Module.hs view
@@ -0,0 +1,61 @@+-- | Utility module for importing scripted atom and database context functions.+module ProjectM36.Module where+import ProjectM36.Base+import ProjectM36.Error+import ProjectM36.AccessControlList+import ProjectM36.DatabaseContext.Types as DBCT+import Control.Monad.Trans.Writer+import Control.Monad.RWS.Strict (RWST, get, put, ask, runRWST)+import Control.Monad.Except (ExceptT, throwError, runExceptT)+import Data.Functor.Identity++declareAtomFunction :: FunctionName -> EntryPoints ()+declareAtomFunction nam = tell [DeclareAtomFunction nam]++declareDatabaseContextFunction :: FunctionName -> DBCFunctionAccessControlList -> EntryPoints ()+declareDatabaseContextFunction nam acl' = tell [DeclareDatabaseContextFunction nam acl']++type EntryPoints = Writer [DeclareFunction]++runEntryPoints :: EntryPoints () -> [DeclareFunction]+runEntryPoints = execWriter++data DeclareFunctionBase a = DeclareAtomFunction a |+                             DeclareDatabaseContextFunction a DBCFunctionAccessControlList+  deriving (Show)++type DeclareFunction = DeclareFunctionBase FunctionName++type DatabaseContextFunctionMonad a = RWST DatabaseContextFunctionMonadEnv () DatabaseContext (ExceptT RelationalError Identity) a++newtype DatabaseContextFunctionMonadEnv =+  DatabaseContextFunctionMonadEnv+  {+    utils :: DatabaseContextFunctionUtils+  }++executeRelationalExpr :: RelationalExpr -> DatabaseContextFunctionMonad Relation+executeRelationalExpr expr = do+  env <- ask+  ctx <- get+  case DBCT.executeRelationalExpr (utils env) ctx expr of+    Left err -> throwError err+    Right rel -> pure rel++executeDatabaseContextExpr :: DatabaseContextExpr -> DatabaseContextFunctionMonad ()+executeDatabaseContextExpr expr = do+  env <- ask+  ctx <- get+  case DBCT.executeDatabaseContextExpr (utils env) ctx expr of+    Left err -> throwError err+    Right ctx' ->+      put ctx'++runDatabaseContextFunctionMonad ::+  DatabaseContextFunctionMonadEnv ->+  DatabaseContext ->+  DatabaseContextFunctionMonad () ->+  Either RelationalError DatabaseContext+runDatabaseContextFunctionMonad env ctx m = do+  (_,ctx',_) <- runIdentity $ runExceptT $ runRWST m env ctx+  pure ctx'
src/lib/ProjectM36/NormalizeExpr.hs view
@@ -92,6 +92,7 @@   pure (AddDatabaseContextFunction mod' fun path) processDatabaseContextIOExpr (LoadDatabaseContextFunctions mod' fun path) =   pure (LoadDatabaseContextFunctions mod' fun path)+processDatabaseContextIOExpr (LoadModuleWithFunctions modPath) = pure (LoadModuleWithFunctions modPath) processDatabaseContextIOExpr (CreateArbitraryRelation rvName attrExprs range) =   CreateArbitraryRelation rvName <$> mapM processAttributeExpr attrExprs <*> pure range   
src/lib/ProjectM36/RelationalExpression.hs view
@@ -36,7 +36,6 @@ import Control.Monad.IO.Class (liftIO) import Data.Bifunctor (second) import Data.Maybe-import Data.Tuple (swap) import Data.Either import Data.List (foldl') import Data.Char (isUpper)@@ -58,9 +57,27 @@ import qualified Data.Functor.Foldable as Fold import Control.Applicative #ifdef PM36_HASKELL_SCRIPTING+import System.IO.Temp+import System.IO (hClose)+import qualified Data.Text.IO as TIO+import Data.Default+import ProjectM36.Module import GHC hiding (getContext) import Control.Exception import GHC.Paths+--import GHC.Unit.State (emptyUnitState)+--import GHC.Driver.Ppr (showSDocForUser)+--import GHC.Unit.Finder.Types (FindResult(..))+--import GHC.Unit.Finder (findImportedModule)+import GHC.Types.Name.Occurrence (mkVarOcc, mkTcOcc)+import GHC.Iface.Env (lookupOrig)+import GHC.Types.Name (getOccString)+import GHC.Core.Type (mkTyConApp)+import GHC.Builtin.Types (unitTy)+import GHC.Core.TyCo.Compare (eqType)+import Unsafe.Coerce+import Control.Monad (forM)+--import GHC.Utils.Outputable (ppr) #endif  data DatabaseContextExprDetails = CountUpdatedTuples@@ -318,14 +335,13 @@         Left err -> dbErr err         Right expectedType -> do       -- if we are targeting an existing rv, we can morph a MakeRelationFromExprs datum to fill in missing type variables'-          let hintedExpr = addTargetTypeHints (attributes expectedType) expr-              eNewExprType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr hintedExpr)+          let eNewExprType = runGraphRefRelationalExprM reEnv (typeForGraphRefRelationalExpr' (Just (attributes expectedType)) expr)           case eNewExprType of             Left err -> dbErr err             Right newExprType -> do               if newExprType == expectedType then do                 lift $ except $ validateAttributes tConsMapping (attributes newExprType)-                setRelVar relVarName hintedExpr +                setRelVar relVarName expr               else do                 dbErr (RelationTypeMismatchError (attributes expectedType) (attributes newExprType)) @@ -723,6 +739,12 @@                               case runDatabaseContextEvalMonad currentContext evalEnv (setRelVar relVarName (ExistingRelation rel)) of                                 Left err -> throwError err                                 Right dbstate' -> putDBCIOContext (dbc_context dbstate')+evalGraphRefDatabaseContextIOExpr (LoadModuleWithFunctions moduleBody) = do+  scriptSession <- requireScriptSession+  importModuleFromPath scriptSession moduleBody +  -- copy the module source in the db directory -- ideally this would be written into the transaction directory, but at this point, it does not yet exist+  -- load the module using GHC+  -- run the entrypoint function to get names of functions to convert to Atom and DBC functions  -- | run verification of all constraints -- needs DatabaseContext to create dummy Transaction@@ -1299,14 +1321,20 @@         x : _ -> Right x  typeForGraphRefRelationalExpr :: GraphRefRelationalExpr -> GraphRefRelationalExprM Relation-typeForGraphRefRelationalExpr (MakeStaticRelation attrs _) = lift $ except $ mkRelation attrs TS.empty-typeForGraphRefRelationalExpr (ExistingRelation rel) = pure (emptyRelationWithAttrs (attributes rel))-typeForGraphRefRelationalExpr (MakeRelationFromExprs mAttrExprs tupleExprs) = do-  mAttrs <- case mAttrExprs of-              Just attrExprs -> do-                attrs <- mapM evalGraphRefAttributeExpr attrExprs-                pure (Just (attributesFromList attrs))-              Nothing -> pure Nothing+typeForGraphRefRelationalExpr = typeForGraphRefRelationalExpr' Nothing++typeForGraphRefRelationalExpr' :: Maybe Attributes -> GraphRefRelationalExpr -> GraphRefRelationalExprM Relation+typeForGraphRefRelationalExpr' _thints (MakeStaticRelation attrs _) = lift $ except $ mkRelation attrs TS.empty+typeForGraphRefRelationalExpr' _thints (ExistingRelation rel) = pure (emptyRelationWithAttrs (attributes rel))+typeForGraphRefRelationalExpr' mAttributeTypeHints (MakeRelationFromExprs mAttrExprs tupleExprs) = do+  mAttrs <- case mAttributeTypeHints of+              Nothing ->+                case mAttrExprs of+                  Just attrExprs -> do+                    attrs <- mapM evalGraphRefAttributeExpr attrExprs+                    pure (Just (attributesFromList attrs))+                  Nothing -> pure Nothing+              Just attrTypeHints -> pure (Just attrTypeHints)   retAttrs <- typeForGraphRefTupleExprs mAttrs tupleExprs   case mAttrs of     Nothing ->@@ -1317,7 +1345,7 @@         Right retAttrs' ->            pure $ emptyRelationWithAttrs retAttrs'   -typeForGraphRefRelationalExpr (RelationVariable rvName tid) = do+typeForGraphRefRelationalExpr' _th (RelationVariable rvName tid) = do   ctx <- gfDatabaseContextForMarker tid   graph <- gfGraph   case resolveDBC' graph ctx relationVariables of@@ -1327,7 +1355,7 @@         Nothing -> throwError (RelVarNotDefinedError rvName)         Just rvExpr ->            typeForGraphRefRelationalExpr rvExpr-typeForGraphRefRelationalExpr (RelationValuedAttribute attrName) = do+typeForGraphRefRelationalExpr' _th (RelationValuedAttribute attrName) = do   env <- askEnv   case gre_extra env of     Nothing -> throwError (NoSuchAttributeNamesError (S.singleton attrName)) -- or can this be an attribute at the top-level?@@ -1343,46 +1371,46 @@           case typ of             RelationAtomType relAttrs -> pure $ emptyRelationWithAttrs relAttrs             other -> throwError (AtomTypeMismatchError (RelationAtomType A.emptyAttributes) other)-typeForGraphRefRelationalExpr (Project attrNames expr) = do+typeForGraphRefRelationalExpr' _th (Project attrNames expr) = do   exprType' <- typeForGraphRefRelationalExpr expr   projectionAttrs <- evalGraphRefAttributeNames attrNames expr   lift $ except $ project projectionAttrs exprType'-typeForGraphRefRelationalExpr (Union exprA exprB) = do+typeForGraphRefRelationalExpr' _th (Union exprA exprB) = do   exprA' <- typeForGraphRefRelationalExpr exprA   exprB' <- typeForGraphRefRelationalExpr exprB   lift $ except $ union exprA' exprB'-typeForGraphRefRelationalExpr (Join exprA exprB) = do+typeForGraphRefRelationalExpr' _th (Join exprA exprB) = do   exprA' <- typeForGraphRefRelationalExpr exprA   exprB' <- typeForGraphRefRelationalExpr exprB   lift $ except $ join exprA' exprB'-typeForGraphRefRelationalExpr (Rename attrs expr) = do+typeForGraphRefRelationalExpr' _th (Rename attrs expr) = do   expr' <- typeForGraphRefRelationalExpr expr   lift $ except $ renameMany attrs expr'-typeForGraphRefRelationalExpr (Difference exprA exprB) = do  +typeForGraphRefRelationalExpr' _th (Difference exprA exprB) = do     exprA' <- typeForGraphRefRelationalExpr exprA   exprB' <- typeForGraphRefRelationalExpr exprB   lift $ except $ difference exprA' exprB'-typeForGraphRefRelationalExpr (Group groupNames attrName expr) = do-  expr' <- typeForGraphRefRelationalExpr expr+typeForGraphRefRelationalExpr' mHints (Group groupNames attrName expr) = do+  expr' <- typeForGraphRefRelationalExpr' mHints expr   groupNames' <- evalGraphRefAttributeNames groupNames expr   lift $ except $ group groupNames' attrName expr'-typeForGraphRefRelationalExpr (Ungroup groupAttrName expr) = do+typeForGraphRefRelationalExpr' _th (Ungroup groupAttrName expr) = do   expr' <- typeForGraphRefRelationalExpr expr   lift $ except $ ungroup groupAttrName expr'-typeForGraphRefRelationalExpr (Restrict pred' expr) = do+typeForGraphRefRelationalExpr' _th (Restrict pred' expr) = do   expr' <- typeForGraphRefRelationalExpr expr   let mergedAttrsEnv = mergeAttributesIntoGraphRefRelationalExprEnv (attributes expr')   R.local mergedAttrsEnv (typeForGraphRefRestrictionPredicateExpr pred')   filt <- predicateRestrictionFilter (attributes expr') pred'   lift $ except $ restrict filt expr'-typeForGraphRefRelationalExpr Equals{} = +typeForGraphRefRelationalExpr' _th Equals{} =    pure relationFalse-typeForGraphRefRelationalExpr NotEquals{} = +typeForGraphRefRelationalExpr' _th NotEquals{} =    pure relationFalse-typeForGraphRefRelationalExpr (Extend extendTupleExpr expr) = do+typeForGraphRefRelationalExpr' _th (Extend extendTupleExpr expr) = do   rel <- typeForGraphRefRelationalExpr expr   evalGraphRefRelationalExpr (Extend extendTupleExpr (ExistingRelation rel))-typeForGraphRefRelationalExpr expr@(With withs _) = do+typeForGraphRefRelationalExpr' _th expr@(With withs _) = do   let expr' = substituteWithNameMacros [] expr       checkMacroName (WithNameExpr macroName tid) = do         ctx <- gfDatabaseContextForMarker tid@@ -1687,42 +1715,6 @@     Nothing -> throwError (NoSuchAttributeNamesError (S.singleton attrName))     Just match -> pure match --- | Optionally add type hints to resolve type variables. For example, if we are inserting into a known relvar, then we have its concrete type.    -addTargetTypeHints :: Attributes -> GraphRefRelationalExpr -> GraphRefRelationalExpr-addTargetTypeHints targetAttrs expr =-  case expr of-    MakeRelationFromExprs Nothing tupExprs ->-      MakeRelationFromExprs (Just targetAttrExprs) tupExprs-    Project attrs e ->-      Project attrs (hint e)-    Union a b ->-      Union (hint a) (hint b)-    Join a b ->-      Join (hint a) (hint b)-    Rename rens e ->-      let renamedAttrs = A.renameAttributes' (S.map swap rens) targetAttrs in-      Rename rens (addTargetTypeHints renamedAttrs e)-    Difference a b ->-      Difference (hint a) (hint b)-    Group attrs gname e ->-      Group attrs gname (hint e)-    Ungroup gname e ->-      Ungroup gname (hint e)-    Restrict restriction e ->-      Restrict restriction (hint e)-    Equals a b ->-      Equals (hint a) (hint b)-    NotEquals a b ->-      NotEquals (hint a) (hint b)-    Extend tupExprs e ->-      Extend tupExprs (hint e)-    With withs e ->-      With withs (hint e)-    _ -> expr-  where-    targetAttrExprs = map NakedAttributeExpr (A.toList targetAttrs)-    hint = addTargetTypeHints targetAttrs- resolveDBC :: (DatabaseContext -> ValueMarker a) -> DatabaseContextEvalMonad a resolveDBC f = do   graph <- dbcGraph@@ -1890,4 +1882,147 @@         pure (Attribute attrName resolvedType)   attrList <- mapM resolveOneAtomType (M.toList tupMap)   pure (A.attributesFromList attrList)-        ++importModuleFromPath :: ScriptSession -> ModuleBody -> DatabaseContextIOEvalMonad ()+#if !defined(PM36_HASKELL_SCRIPTING)+importModuleFromPath _scriptSession _moduleSource = throwError (ScriptError ScriptCompilationDisabledError)+#else+importModuleFromPath scriptSession moduleSource = do+  res <- liftIO $ try $ do+    withSystemTempFile "pm36module" $ \tempModulePath tempModuleHandle -> do+      hClose tempModuleHandle+      TIO.writeFile tempModulePath moduleSource+      runGhc (Just libdir) $ do+    -- GHC needs to see the module on disk, so we write it to a temporary location+        setSession (hscEnv scriptSession)+        dflags <- getSessionDynFlags        +        let target = Target {+              targetId = TargetFile tempModulePath Nothing,+              targetAllowObjCode = False,+              targetUnitId = homeUnitId_ dflags,+              targetContents = Nothing+            }+        setTargets [target]+        loadSuccess <- load LoadAllTargets+        case loadSuccess of+          Failed -> pure (Left (ScriptError ModuleLoadError))+          Succeeded -> do+            {-modRes <- liftIO $ findImportedModule (hscEnv scriptSession) (mkModuleName "ProjectM36.Base") NoPkgQual+            liftIO $ case modRes of+              Found modLoc _mod -> do+                let packageLoc = takeDirectory (takeDirectory (takeDirectory (ml_dyn_obj_file modLoc)))+                putStrLn packageLoc+              NoPackage{} -> error "no package"+              FoundMultiple{} -> error "multiple matches"+              NotFound{} -> error "not found"-}+            modGraph <- depanal [] False+            case mgModSummaries modGraph of+              [] -> pure (Left (ScriptError ModuleLoadError))+              (modSummary:_) -> do+                let modName = ms_mod_name modSummary+                    modModS = "ProjectM36.Module"+                    modModName = mkModuleName modModS +                    pm36FuncName = "projectM36Functions"+                    occName = mkVarOcc pm36FuncName+                    occExpectedType = mkTcOcc "EntryPoints"+                setContext [IIModule modName,+                            IIDecl $ safeImportDecl "ProjectM36.Base" Nothing+                           ]+                +                userModule <- findModule modName Nothing+                moduleModule <- findModule modModName Nothing+                (_msgs, Just (entrypointFunc, entryPointsMonadName)) <- liftIO $ runTcInteractive (hscEnv scriptSession) $ do+                  pm36Name <- lookupOrig userModule occName+                  entryPointsName <- lookupOrig moduleModule occExpectedType+                  pure (pm36Name, entryPointsName)+                monadTy <- lookupName entryPointsMonadName+                let unexpectedEP s = throw (ScriptError (OtherScriptCompilationError ("expected " <> pm36FuncName <> " signature: " <> s)))+                entryPointsTyCon <- case monadTy of+                                         Just (ATyCon tc) -> pure $ mkTyConApp tc [unitTy]+                                         Just (AnId _tc) -> unexpectedEP "AnId"+                                         Just (AConLike _clike) -> unexpectedEP "AConLike"+                                         Just (ACoAxiom _cax) -> unexpectedEP "ACoAxiom"+                                         Nothing -> unexpectedEP "missing"+                tyThing <- lookupName entrypointFunc+                case tyThing of+                      Just (ATyCon _iCon) -> unexpectedEP "ATyCon"+                      Just (ACoAxiom _) -> unexpectedEP "ACoAxoim"+                      --run the entrypoints monad+                      Just (AnId aid)+                        | getOccString aid == pm36FuncName ->+                            -- typecheck entrypoint function+                            if idType aid `eqType` entryPointsTyCon then do+                              -- call entrypoint+                              result <- compileExpr pm36FuncName+                              let funcDeclarations = runEntryPoints (unsafeCoerce result)+                              tyConv <- mkTypeConversions                              +                              mkFunctions <- forM funcDeclarations $ \funcDecl -> do+                                  case funcDecl of+                                    DeclareDatabaseContextFunction funcS acl' -> do+                                      fType <- exprType TM_Default (T.unpack funcS)+                                      dbcFuncMonadType <- exprType TM_Default "undefined :: DatabaseContextFunctionMonad ()"                                      +                                      -- extract arguments for dbc function+                                      let eAtomFuncType = convertGhcTypeToDatabaseContextFunctionAtomType dflags tyConv dbcFuncMonadType fType+                                      case eAtomFuncType of+                                        Left err -> throw (OtherScriptCompilationError (show err))+                                        Right dbcFuncType -> do+                                          let interpretedFunc = wrapDatabaseContextFunction dbcFuncType funcS+                                          dbcFunc :: DatabaseContextFunctionBodyType <- unsafeCoerce <$> compileExpr interpretedFunc+                                          let newDBCFunc = Function { funcName = funcS,+                                                                            funcType = dbcFuncType,+                                                                            funcBody = FunctionScriptBody (T.pack interpretedFunc) dbcFunc,+                                                                            funcACL = acl' }+                                          pure (MkDatabaseContextFunction newDBCFunc)+                                    DeclareAtomFunction funcS -> do+                                      --extract type from function in script+                                      fType <- exprType TM_Default (T.unpack funcS)+                                      let eAtomFuncType = convertGhcTypeToFunctionAtomType dflags tyConv fType +                                      --liftIO $ print eAtomFuncType+                                      --liftIO $ putStrLn $ showSDocForUser dflags emptyUnitState alwaysQualify (ppr fType)+                                      case eAtomFuncType of+                                        Left err -> error (show err)+                                        Right atomFuncType -> do+                                          let eInterpretedFunc = wrapAtomFunction atomFuncType funcS+                                          --liftIO $ print eInterpretedFunc+                                          case eInterpretedFunc of+                                            Left err -> error (show err)+                                            Right interpretedFunc -> do+                                              atomFunc :: AtomFunctionBodyType <- unsafeCoerce <$> compileExpr interpretedFunc+                                              --todo - return atom functions and dbc functions out of Ghc monad to add them to the context+                                              let newAtomFunc = Function { funcName = funcS,+                                                                           funcType = atomFuncType,+                                                                           funcBody = FunctionScriptBody (T.pack interpretedFunc) atomFunc,+                                                                           funcACL = def }+                                              --let execd = atomFunc [IntegerAtom 10, IntegerAtom 20]+                                              --liftIO $ print execd++                                              pure (MkAtomFunction newAtomFunc)+                              pure (Right mkFunctions)+                              else+                              unexpectedEP "type mismatch"+                      Just AnId{} -> unexpectedEP "AnId"+                      Just AConLike{} -> unexpectedEP "AConLike"+                      Nothing -> unexpectedEP "Nothing"+  case res of+      Left exc -> throwError exc+      Right eMkFunctions ->+        case eMkFunctions of+          Left err -> throwError err+          Right mkFunctions -> do+            ctx <- getDBCIOContext+            atomFuncs <- resolveIODBC atomFunctions+            dbcFuncs <- resolveIODBC dbcFunctions+            let foldMkFunction (atomFuncHS, dbcFuncHS) (MkAtomFunction atomFunc) =+                  (HS.insert atomFunc atomFuncHS, dbcFuncHS)+                foldMkFunction (atomFuncHS, dbcFuncHS) (MkDatabaseContextFunction dbcFunc) =+                  (atomFuncHS, HS.insert dbcFunc dbcFuncHS)+                (newAtomFuncs, newDBCFuncs) = foldl' foldMkFunction (mempty, mempty) mkFunctions+                ctx' = ctx { dbcFunctions = ValueMarker $ HS.union newDBCFuncs dbcFuncs,+                             atomFunctions = ValueMarker $ HS.union newAtomFuncs atomFuncs+                           }++            putDBCIOContext ctx'+#endif++data MkFunction = MkAtomFunction AtomFunction |+                  MkDatabaseContextFunction DatabaseContextFunction 
src/lib/ProjectM36/ScriptSession.hs view
@@ -1,12 +1,15 @@ {-# LANGUAGE UnboxedTuples, KindSignatures, DataKinds #-} #ifdef PM36_HASKELL_SCRIPTING {-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-} #endif module ProjectM36.ScriptSession where  #ifdef PM36_HASKELL_SCRIPTING import ProjectM36.Error+import ProjectM36.Base import GHC+import GHC.Core.TyCo.Rep import Control.Exception import Control.Monad import System.IO.Error@@ -22,65 +25,33 @@  import Unsafe.Coerce import GHC.LanguageExtensions (Extension(OverloadedStrings,ExtendedDefaultRules,ImplicitPrelude,ScopedTypeVariables))-#if MIN_VERSION_ghc(9,6,0)+-- GHC 9.4+ import Data.List.NonEmpty(NonEmpty(..))-#else-#endif-#if MIN_VERSION_ghc(9,6,0)-#else-#endif-#if MIN_VERSION_ghc(9,6,0)-import GHC.Core.TyCo.Compare (eqType)-#elif MIN_VERSION_ghc(9,0,0)-import GHC.Core.Type (eqType)-#else-import Type (eqType)-#endif-#if MIN_VERSION_ghc(9,6,0)-#elif MIN_VERSION_ghc(9,0,0)-import GHC.Unit.Types (IsBootInterface(NotBoot))-#else-#endif-#if MIN_VERSION_ghc(9,4,0) import GHC.Utils.Panic (handleGhcException) import GHC.Driver.Session (projectVersion, PackageDBFlag(PackageDB), PkgDbRef(PkgDbPath), TrustFlag(TrustPackage), gopt_set, xopt_set, PackageFlag(ExposePackage), PackageArg(PackageArg), ModRenaming(ModRenaming)) import GHC.Types.SourceText (SourceText(NoSourceText)) import GHC.Driver.Ppr (showSDocForUser)+import GHC.Utils.Outputable (ppr, Outputable)+--import GHC.Unit.Module.Graph (showModMsg, mgModSummaries') import GHC.Core.TyCo.Ppr (pprType) import GHC.Utils.Encoding (zEncodeString) import GHC.Unit.State (emptyUnitState) import GHC.Types.PkgQual (RawPkgQual(NoRawPkgQual))-#elif MIN_VERSION_ghc(9,2,0)--- GHC 9.2.2-import GHC.Utils.Panic (handleGhcException)-import GHC.Driver.Session (projectVersion, PackageDBFlag(PackageDB), PkgDbRef(PkgDbPath), TrustFlag(TrustPackage), gopt_set, xopt_set, PackageFlag(ExposePackage), PackageArg(PackageArg), ModRenaming(ModRenaming))-import GHC.Types.SourceText (SourceText(NoSourceText))-import GHC.Driver.Ppr (showSDocForUser)-import GHC.Types.TyThing.Ppr (pprTypeForUser)-import GHC.Utils.Encoding (zEncodeString)-import GHC.Unit.State (emptyUnitState)-#elif MIN_VERSION_ghc(9,0,0)--- GHC 9.0.0-import GHC.Utils.Panic (handleGhcException)-import GHC.Driver.Session (projectVersion, PackageDBFlag(PackageDB), PkgDbRef(PkgDbPath), TrustFlag(TrustPackage), gopt_set, xopt_set, PackageFlag(ExposePackage), PackageArg(PackageArg), ModRenaming(ModRenaming))-import GHC.Types.Basic (SourceText(NoSourceText))-import GHC.Utils.Outputable (showSDocForUser)-import GHC.Utils.Encoding (zEncodeString)-import GHC.Core.Ppr.TyThing (pprTypeForUser)-#else--- GHC 8.10.7-import BasicTypes (SourceText(NoSourceText))-import Outputable (showSDocForUser)-import PprTyThing (pprTypeForUser)-import Encoding (zEncodeString)-import Panic (handleGhcException)-import DynFlags (projectVersion, PkgConfRef(PkgConfFile), TrustFlag(TrustPackage), gopt_set, xopt_set, PackageFlag(ExposePackage), PackageArg(PackageArg), ModRenaming(ModRenaming), PackageDBFlag(PackageDB))-#endif- import GHC.Exts (addrToAny#) import GHC.Ptr (Ptr(..)) import GHCi.ObjLink (initObjLinker, ShouldRetainCAFs(RetainCAFs), resolveObjs, lookupSymbol, loadDLL, loadObj)+--import GHC.Builtin.Types (integerTyCon, intTyCon, doubleTyCon, eqTyCon)+--import qualified Data.Map as M+import Data.List (find)+import qualified Control.Monad.Catch as CMC++#if MIN_VERSION_ghc(9,6,0)+import GHC.Core.TyCo.Compare (eqType)+import GHC.Unit.Types (UnitId)+import GHC.Driver.Env (hsc_home_unit)+import GHC.Unit.Home (homeUnitId) #endif+#endif -- endif for SCRIPTING FLAG  data ScriptSession = ScriptSession {@@ -179,8 +150,36 @@         packages = map (\m -> ExposePackage ("-package " ++ m) (PackageArg m) (ModRenaming True [])) required_packages   --liftIO $ traceShowM (showSDoc dflags' (ppr packages))     _ <- setSessionDynFlags dflags'-    let safeImportDecl :: String -> Maybe String -> ImportDecl (GhcPass 'Parsed)-        safeImportDecl fullModuleName _mQualifiedName = ImportDecl {+    let unqualifiedModules = map (\modn -> IIDecl $ safeImportDecl modn Nothing) [+          "Prelude",+          "Data.Map",+          "Data.Either",+          "Data.Time.Calendar",+--          "Data.Scientific",+          "Control.Monad.State",+          "ProjectM36.Base",+          "ProjectM36.Error",+          "ProjectM36.Relation",+          "ProjectM36.DatabaseContext",+          "ProjectM36.DatabaseContext.Types",+          "ProjectM36.AtomFunctionError",+          "ProjectM36.RelationalExpression"]+        qualifiedModules = map (\(modn, qualNam) -> IIDecl $ safeImportDecl modn (Just qualNam)) [+          ("Data.Text", "T")+          ]+    setContext (unqualifiedModules ++ qualifiedModules)+    env <- getSession+{-    case mgLookupModule (mkModuleName "ProjectM36") moduleInfos of+       Nothing -> error "failed to load project-m36 module"+       Just moduleInfo ->+  -}        +    atomFuncType <- mkTypeForName "AtomFunctionBodyType"+    dbcFuncType <- mkTypeForName "DatabaseContextFunctionBodyType"++    pure (Right (ScriptSession env atomFuncType dbcFuncType))++safeImportDecl :: String -> Maybe String -> ImportDecl (GhcPass 'Parsed)+safeImportDecl fullModuleName _mQualifiedName = ImportDecl { #if MIN_VERSION_ghc(9,6,0) #else           ideclSourceSrc = NoSourceText,@@ -237,28 +236,8 @@ #endif           ideclSafe      = True           }-        unqualifiedModules = map (\modn -> IIDecl $ safeImportDecl modn Nothing) [-          "Prelude",-          "Data.Map",-          "Data.Either",-          "Data.Time.Calendar",-          "Control.Monad.State",-          "ProjectM36.Base",-          "ProjectM36.Error",-          "ProjectM36.Relation",-          "ProjectM36.DatabaseContext",-          "ProjectM36.DatabaseContext.Types",-          "ProjectM36.AtomFunctionError",-          "ProjectM36.RelationalExpression"]-        qualifiedModules = map (\(modn, qualNam) -> IIDecl $ safeImportDecl modn (Just qualNam)) [-          ("Data.Text", "T")-          ]-    setContext (unqualifiedModules ++ qualifiedModules)-    env <- getSession-    atomFuncType <- mkTypeForName "AtomFunctionBodyType"-    dbcFuncType <- mkTypeForName "DatabaseContextFunctionBodyType"-    pure (Right (ScriptSession env atomFuncType dbcFuncType)) + addImport :: String -> Ghc () addImport moduleNam = do   ctx <- getContext@@ -294,9 +273,9 @@         Just _ -> error ("failed to find type synonym " ++ name)  compileScript :: Type -> Text -> Ghc (Either ScriptCompilationError a)-compileScript funcType script = do+compileScript funcType' script = do   let sScript = unpack script-  mErr <- typeCheckScript funcType script+  mErr <- typeCheckScript funcType' script   case mErr of     Just err -> pure (Left err)     Nothing ->@@ -309,12 +288,12 @@ typeCheckScript expectedType inp = do   dflags <- getSessionDynFlags   --catch exception for SyntaxError-  funcType <- GHC.exprType TM_Inst (unpack inp)+  funcType' <- GHC.exprType TM_Inst (unpack inp)   --liftIO $ putStrLn $ showType dflags expectedType ++ ":::" ++ showType dflags funcType-  if eqType funcType expectedType then+  if eqType funcType' expectedType then     pure Nothing     else-    pure (Just (TypeCheckCompilationError (showType dflags expectedType) (showType dflags funcType)))+    pure (Just (TypeCheckCompilationError (showType dflags expectedType) (showType dflags funcType')))  mangleSymbol :: Maybe String -> String -> String -> String mangleSymbol pkg module' valsym =@@ -335,20 +314,20 @@ type ModuleDirectory = FilePath  loadFunctionFromDirectory :: ObjectLoadMode -> ModName -> FuncName -> FilePath -> FilePath -> IO (Either LoadSymbolError a)-loadFunctionFromDirectory mode modName funcName modDir objPath =+loadFunctionFromDirectory mode modName funcName' modDir objPath =   if takeFileName objPath /= objPath then     pure (Left SecurityLoadSymbolError)   else     let fullObjPath = modDir </> objPath in-      loadFunction mode modName funcName fullObjPath+      loadFunction mode modName funcName' fullObjPath   loadFunction :: ObjectLoadMode -> ModName -> FuncName -> FilePath -> IO (Either LoadSymbolError a)-loadFunction loadMode modName funcName objPath = do+loadFunction loadMode modName funcName' objPath = do   initObjLinker RetainCAFs   let loadFuncForSymbol = do             _ <- resolveObjs-        ptr <- lookupSymbol (mangleSymbol Nothing modName funcName)+        ptr <- lookupSymbol (mangleSymbol Nothing modName funcName')         case ptr of           Nothing -> pure (Left LoadSymbolError)           Just (Ptr addr) -> case addrToAny# addr of@@ -356,17 +335,24 @@   case loadMode of     LoadAutoObjectFile ->       if takeExtension objPath == ".o" then-          loadFunction LoadObjectFile modName funcName objPath+          loadFunction LoadObjectFile modName funcName' objPath         else-          loadFunction LoadDLLFile modName funcName objPath+          loadFunction LoadDLLFile modName funcName' objPath     LoadObjectFile -> do       loadObj objPath       loadFuncForSymbol     LoadDLLFile -> do+#if MIN_VERSION_ghc(9,10,2)+      eErr <- loadDLL objPath+      case eErr of+        Left _err -> pure (Left LoadSymbolError)+        Right _ptr -> loadFuncForSymbol+#else       mErr <- loadDLL objPath       case mErr of         Just _ -> pure (Left LoadSymbolError)         Nothing -> loadFuncForSymbol+#endif  prefixUnderscore :: String prefixUnderscore =@@ -377,4 +363,70 @@       ("darwin",_) -> "_"       ("cygwin",_) -> "_"       _ -> ""++getHomeUnitId :: ScriptSession -> UnitId+getHomeUnitId sSession =+  homeUnitId (hsc_home_unit (hscEnv sSession))++data TypeConversionError = UnsupportedTypeConversionError String+  deriving Show++mkTypeConversions :: GhcMonad m => m [(Type, AtomType)]+mkTypeConversions = do+  let extTypes = [("Integer", IntegerAtomType),+                  ("Int", IntAtomType),+                  ("Double", DoubleAtomType),+                  ("Scientific", ScientificAtomType), -- found in multiple modules?+                  ("Text", TextAtomType),+                  ("Day", DayAtomType),+                  ("UTCTime", DateTimeAtomType),+                  ("ByteString", ByteStringAtomType),+                  ("Bool", BoolAtomType),+                  ("UUID", UUIDAtomType)+                 ]+  res <- forM extTypes $ \(nam, typ) -> do+    -- extract type from bottom value+    ghcType <- (Just <$> exprType TM_Default ("undefined :: " <> nam)) `CMC.catch` (\(_ :: SomeException) -> pure Nothing)+    pure (ghcType, typ)+  let mapFilter (Nothing, _) = Nothing+      mapFilter (Just t, at) = Just (t, at)+  pure (mapMaybe mapFilter res)+                                +convertGhcTypeToFunctionAtomType :: DynFlags -> [(Type, AtomType)] -> Type -> Either TypeConversionError [AtomType]+convertGhcTypeToFunctionAtomType dflags tyConv typ =+  case typ of+    TyConApp _tycon _args -> do+      aType <- findTypeConv dflags typ tyConv+      pure [aType]+    fun@FunTy{} -> do+      arg <- convertGhcTypeToFunctionAtomType dflags tyConv (ft_arg fun)+      rest <- convertGhcTypeToFunctionAtomType dflags tyConv (ft_res fun)+      pure (arg <> rest)+    other -> Left (UnsupportedTypeConversionError (pprShow other dflags))++    +pprShow :: Outputable a => a -> DynFlags -> String+pprShow x dflags = showSDocForUser dflags emptyUnitState alwaysQualify (ppr x)++findTypeConv :: DynFlags -> Type -> [(Type, AtomType)] -> Either TypeConversionError AtomType+findTypeConv dflags typ tyConv =+  case find (\(k,_v) -> k `eqType` typ) tyConv of+    Nothing -> Left (UnsupportedTypeConversionError (pprShow typ dflags))+    Just (_,match') -> +      pure match'++-- | Last argument should be `DatabaseContextFunctionMonad ()`+convertGhcTypeToDatabaseContextFunctionAtomType :: DynFlags -> [(Type, AtomType)] -> Type -> Type -> Either TypeConversionError [AtomType]+convertGhcTypeToDatabaseContextFunctionAtomType dflags tyConv dbcFuncMonadType typ =+  case typ of+    TyConApp{} |+      typ `eqType` dbcFuncMonadType -> pure []+    TyConApp{} -> do+      aType <- findTypeConv dflags typ tyConv+      pure [aType]+    fun@FunTy{} -> do+      arg <- convertGhcTypeToDatabaseContextFunctionAtomType dflags tyConv dbcFuncMonadType (ft_arg fun)+      rest <- convertGhcTypeToDatabaseContextFunctionAtomType dflags tyConv dbcFuncMonadType (ft_res fun)+      pure (arg <> rest)+    other -> Left (UnsupportedTypeConversionError (pprShow other dflags)) #endif
src/lib/ProjectM36/Transaction/Persist.hs view
@@ -16,7 +16,6 @@ import ProjectM36.DatabaseContext.Types import ProjectM36.IsomorphicSchema.Types hiding (concreteDatabaseContext, subschemas) import ProjectM36.DatabaseContextFunctions.Basic-import ProjectM36.AtomFunction import ProjectM36.Persist (DiskSync, renameSync, writeSerialiseSync, readDeserialise) import ProjectM36.Function import ProjectM36.AccessControlList@@ -48,6 +47,7 @@ import GHC import Control.Exception import GHC.Paths+import ProjectM36.AtomFunction #endif  xattrName :: String
test/Relation/Atomable.hs view
@@ -9,7 +9,7 @@ import ProjectM36.Relation import ProjectM36.Base import Data.Time.Calendar (fromGregorian)-import Data.Text+import Data.Text (Text) import qualified Data.Map as M import Data.Proxy import Codec.Winery
test/Server/WebSocket.hs view
@@ -13,7 +13,7 @@ import Control.Concurrent import System.Exit import Data.Typeable-import Data.Text hiding (map)+import Data.Text (Text) import Data.Aeson import qualified Data.ByteString.Lazy as BS import ProjectM36.Relation
+ test/TutorialD/Interpreter/Module.hs view
@@ -0,0 +1,46 @@+-- | Test import via ProjectM36.Module which allows a user to import any number of atom functions or database context functions.+{-# LANGUAGE CPP #-}+import System.Exit+import Test.HUnit+#ifdef PM36_HASKELL_SCRIPTING+import Data.Time.Calendar+import TutorialD.Interpreter.TestBase+import ProjectM36.Client+import qualified ProjectM36.Attribute as A+import ProjectM36.Relation+#endif++main :: IO ()+main = do+  tcounts <- runTestTT (TestList [+#ifdef PM36_HASKELL_SCRIPTING+    testImportModule+#endif                                  +    ])+  if errors tcounts + failures tcounts > 0 then exitFailure else exitSuccess+    +    +#ifdef PM36_HASKELL_SCRIPTING+testImportModule :: Test+testImportModule = TestCase $ do+  (sess, conn) <- dateExamplesConnection emptyNotificationCallback+  let importmodule = "loadmodulefromfile \"test/TutorialD/Interpreter/TestModule.hs\""+  executeTutorialD sess conn importmodule+  -- install relvar+  executeTutorialD sess conn "ticket_sales:=relation{ticketId Integer, visitorAge Integer, basePrice Integer, visitDate Day}"+  --execute the atom function in the module+  executeTutorialD sess conn "x:=relation{tuple{a applyDiscount(8,20)}}"+  eres <- executeRelationalExpr sess conn (RelationVariable "x" ())+  let expectedres = mkRelationFromList (A.attributesFromList [Attribute "a" IntegerAtomType]) [[IntegerAtom 10]]+  assertEqual "x applyDiscount" expectedres eres++  --execute the dbc function in the module+  executeTutorialD sess conn "execute addSale(1,8,20,fromGregorian(2025, 10, 3))"+  let salesAttrs = A.attributesFromList [Attribute "ticketId" IntegerAtomType,+                                         Attribute "visitorAge" IntegerAtomType,+                                         Attribute "basePrice" IntegerAtomType,+                                         Attribute "visitDate" DayAtomType]+  let expectedres' = mkRelationFromList salesAttrs [[IntegerAtom 1, IntegerAtom 8, IntegerAtom 10, DayAtom (fromGregorian 2025 10 03)]]+  eres' <- executeRelationalExpr sess conn (RelationVariable "ticket_sales" ())+  assertEqual "ticket_sales addSale" expectedres' eres'+#endif
test/TutorialD/Interpreter/TestBase.hs view
@@ -5,7 +5,7 @@ import ProjectM36.DateExamples import ProjectM36.DatabaseContextExpr import Test.HUnit-import Data.Text+import Data.Text (Text, unpack) import System.Random (mkStdGen)  dateExamplesConnection :: NotificationCallback -> IO (SessionId, Connection)
test/TutorialD/InterpreterTest.hs view
@@ -101,7 +101,8 @@       testSubrelationAttributeAtomExpr,       testComplexTypeVarResolution,       testNotifications,-      testDBCFunctionAccessControl+      testDBCFunctionAccessControl,+      testAttributeTypeHintsFromExistingRelVar       ]  simpleRelTests :: Test@@ -950,3 +951,11 @@   -- check that the non-privileged role can run the dbc function   executeTutorialD session user1conn "execute deleteAll()"   +testAttributeTypeHintsFromExistingRelVar :: Test+testAttributeTypeHintsFromExistingRelVar = TestCase $ do+  (session, dbconn) <- dateExamplesConnection emptyNotificationCallback+  -- validate that declaring a relvar and then changing its type fails+  executeTutorialD session dbconn "x:=relation{a Integer}"+  let err1 = "RelationTypeMismatchError"+  expectTutorialDErr session dbconn (T.isPrefixOf err1) "x:=relation{tuple{a 3, b 4}}"+