@@ -6,9 +6,11 @@ import ProjectM36.TupleSet
66import ProjectM36.Base
77import ProjectM36.Error
88import ProjectM36.AtomType
9−import ProjectM36.AtomFunctionBody
9+import ProjectM36.Attribute (emptyAttributes)
10+import ProjectM36.ScriptSession
1011import ProjectM36.DataTypes.Primitive
1112import ProjectM36.AtomFunction
13+import ProjectM36.DatabaseContextFunction
1214import qualified ProjectM36.Attribute as A
1315import qualified Data.Map as M
1416import qualified Data.HashSet as HS
@@ -185,16 +187,6 @@ evalRelationalExpr (Extend tupleExpression relExpr) = do
185187 Left err -> pure (Left err)
186188 Right (newAttrs, tupProc') -> pure $ relMogrify tupProc' newAttrs rel
187189
188−emptyDatabaseContext :: DatabaseContext
189−emptyDatabaseContext = DatabaseContext { inclusionDependencies = M.empty,
190− relationVariables = M.empty,
191− atomFunctions = HS.empty,
192− notifications = M.empty,
193− typeConstructorMapping = []
194− }
195−
196−
197−
198190--helper function to process relation variable creation/assignment
199191setRelVar :: RelVarName -> Relation -> DatabaseState (Maybe RelationalError)
200192setRelVar relVarName rel = do
@@ -376,20 +368,61 @@ evalContextExpr (RemoveAtomFunction funcName) = do
376368 put (currentContext {atomFunctions = updatedFuncs })
377369 pure Nothing
378370 else
379− pure (Just (AtomFunctionNameNotInUseError funcName))
371+ pure (Just (FunctionNameNotInUseError funcName))
372+
373+evalContextExpr (RemoveDatabaseContextFunction funcName) = do
374+ context <- get
375+ let dudFunc = emptyDatabaseContextFunction funcName
376+ dbcFuncs = dbcFunctions context
377+ if HS.member dudFunc dbcFuncs then do
378+ let updatedFuncs = HS.delete dudFunc dbcFuncs
379+ put (context { dbcFunctions = updatedFuncs })
380+ pure Nothing
381+ else
382+ pure (Just (FunctionNameNotInUseError funcName))
383+
384+evalContextExpr (ExecuteDatabaseContextFunction funcName atomArgExprs) = do
385+ context <- get
386+ --resolve atom arguments
387+ let relExprState = mkRelationalExprState context
388+ atomTypes = map (\atomExpr -> evalState (typeFromAtomExpr emptyAttributes atomExpr) relExprState) atomArgExprs
389+ eFunc = databaseContextFunctionForName funcName (dbcFunctions context)
390+ case eFunc of
391+ Left err -> pure (Just err)
392+ Right func -> do
393+ let expectedArgCount = length (dbcFuncType func)
394+ actualArgCount = length atomTypes
395+ safeInit [_] = []
396+ safeInit [] = [] -- different behavior from normal init
397+ safeInit (_:xs) = safeInit xs
398+ if expectedArgCount /= actualArgCount then
399+ pure (Just (FunctionArgumentCountMismatch expectedArgCount actualArgCount))
400+ else do
401+ {-
402+ mapM_ (\(expType, actType) -> case atomTypeVerify expType actType of
403+ Left err -> pure (Just err)
404+ Right _ -> pure Nothing) (safeInit (zip (dbcFuncType func) atomTypes))
405+ -}
406+ let eAtomArgs = map (\arg -> evalState (evalAtomExpr emptyTuple arg) relExprState) atomArgExprs
407+ if length (lefts eAtomArgs) > 1 then
408+ pure (Just (MultipleErrors (lefts eAtomArgs)))
409+ else do
410+ let newContext = evalDatabaseContextFunction func (rights eAtomArgs) context
411+ put newContext
412+ pure Nothing
380413
381414evalDatabaseContextIOExpr :: Maybe ScriptSession -> DatabaseContext -> DatabaseContextIOExpr -> IO (Either RelationalError DatabaseContext)
382415evalDatabaseContextIOExpr mScriptSession currentContext (AddAtomFunction funcName funcType script) = do
383416 case mScriptSession of
384− Nothing -> pure (Left (AtomFunctionBodyScriptError ScriptCompilationDisabledError))
417+ Nothing -> pure (Left (ScriptError ScriptCompilationDisabledError))
385418 Just scriptSession -> do
386419 res <- try $ runGhc (Just libdir) $ do
387420 setSession (hscEnv scriptSession)
388421 let atomFuncs = atomFunctions currentContext
389422 --compile the function
390− eCompiledFunc <- compileAtomFunctionScript scriptSession script
423+ eCompiledFunc <- compileScript (atomFunctionBodyType scriptSession) script
391424 pure $ case eCompiledFunc of
392− Left err -> Left (AtomFunctionBodyScriptError err)
425+ Left err -> Left (ScriptError err)
393426 Right compiledFunc -> do
394427 funcAtomType <- mapM (\funcTypeArg -> atomTypeForTypeConstructor funcTypeArg (typeConstructorMapping currentContext)) funcType
395428 let updatedFuncs = HS.insert newAtomFunc atomFuncs
@@ -400,14 +433,45 @@ evalDatabaseContextIOExpr mScriptSession currentContext (AddAtomFunction funcNam
400433
401434 -- check if the name is already in use
402435 if HS.member funcName (HS.map atomFuncName atomFuncs) then
403− Left (AtomFunctionNameInUseError funcName)
436+ Left (FunctionNameInUseError funcName)
437+ else do
438+ Right newContext
439+ case res of
440+ Left (exc :: SomeException) -> pure $ Left (ScriptError (OtherScriptCompilationError (show exc)))
441+ Right eContext -> case eContext of
442+ Left err -> pure (Left err)
443+ Right context' -> pure (Right context')
444+
445+evalDatabaseContextIOExpr mScriptSession currentContext (AddDatabaseContextFunction funcName funcType script) = do
446+ case mScriptSession of
447+ Nothing -> pure (Left (ScriptError ScriptCompilationDisabledError))
448+ Just scriptSession -> do
449+ res <- try $ runGhc (Just libdir) $ do
450+ setSession (hscEnv scriptSession)
451+ eCompiledFunc <- compileScript (dbcFunctionBodyType scriptSession) script
452+ pure $ case eCompiledFunc of
453+ Left err -> Left (ScriptError err)
454+ Right compiledFunc -> do
455+ funcAtomType <- mapM (\funcTypeArg -> atomTypeForTypeConstructor funcTypeArg (typeConstructorMapping currentContext)) funcType
456+ let updatedDBCFuncs = HS.insert newDBCFunc (dbcFunctions currentContext)
457+ newContext = currentContext { dbcFunctions = updatedDBCFuncs }
458+ dbcFuncs = dbcFunctions currentContext
459+ newDBCFunc = DatabaseContextFunction {
460+ dbcFuncName = funcName,
461+ dbcFuncType = funcAtomType,
462+ dbcFuncBody = DatabaseContextFunctionBody (Just script) compiledFunc
463+ }
464+ -- check if the name is already in use
465+ if HS.member funcName (HS.map dbcFuncName dbcFuncs) then
466+ Left (FunctionNameInUseError funcName)
404467 else do
405468 Right newContext
406469 case res of
407− Left (exc :: SomeException) -> pure $ Left (AtomFunctionBodyScriptError (OtherScriptCompilationError (show exc)))
470+ Left (exc :: SomeException) -> pure $ Left (ScriptError (OtherScriptCompilationError (show exc)))
408471 Right eContext -> case eContext of
409472 Left err -> pure (Left err)
410473 Right context' -> pure (Right context')
474+
411475
412476updateTupleWithAtomExprs :: (M.Map AttributeName AtomExpr) -> DatabaseContext -> RelationTuple -> Either RelationalError RelationTuple
413477updateTupleWithAtomExprs exprMap context tupIn = do
@@ -568,7 +632,7 @@ evalAtomExpr tupIn (FunctionAtomExpr funcName arguments ()) = do
568632 safeInit [] = [] -- different behavior from normal init
569633 safeInit (_:xs) = safeInit xs
570634 if expectedArgCount /= actualArgCount then
571− throwE (AtomFunctionArgumentCountMismatch expectedArgCount actualArgCount)
635+ throwE (FunctionArgumentCountMismatch expectedArgCount actualArgCount)
572636 else do
573637 _ <- mapM (\(expType, actType) -> either throwE pure (atomTypeVerify expType actType)) (safeInit (zip (atomFuncType func) argTypes))
574638 evaldArgs <- mapM (\arg -> liftE (evalAtomExpr tupIn arg)) arguments