def do(self, theEnv, theName=None, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.4.html#Heading248 """ theName = self.resolve(theEnv, theName) if isinstance( theName, (types.FunctionCall, types.Variable)) else theName if theName is None or (isinstance(theName, types.Symbol) and theName.pyEqual("t")): theResource = theEnv.RESOURCES["stdin"] elif not isinstance(theName, types.Symbol): raise InvalidArgTypeError( "Function read expected argument #1 to be of type symbol") else: theResource = theEnv.RESOURCES[theName.evaluate()] try: theString = theResource.readline() # python file.readline() doc: # An empty string is returned only when EOF is encountered immediately # @see http://docs.python.org/release/2.4.4/lib/bltin-file-objects.html if theString == "": return types.Symbol("EOF") return types.String(theString) except EOFError: return types.Symbol("EOF") except IOError: return types.Symbol("*** READ ERROR ***")
def do(self, theEnv, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-13.7.html#Heading450 """ args = list(args) args.reverse() try: for theModule in args: theModule = self.resolve( theEnv, self.semplify(theEnv, theModule, types.Symbol, ("ALL", "symbol"))) if not theEnv.modulesManager.isDefined(theModule): raise InvalidArgValueError("Unable to find defmodule %s" % theModule) else: theEnv.network.agenda.focusStack.append(theModule) return types.Symbol("TRUE") except IndexError: return types.Symbol("FALSE")
def test_NestedAndOrReversion(self): lhs = [ types.AndPatternCE([ types.OrPatternCE(["A", "B"]), types.OrPatternCE([ "C", "D", types.AndPatternCE(["Z", types.OrPatternCE(["W", "X"])]) ]) ]) ] lhs = analysis.normalizeLHS(lhs, self.MM) self.assertIsInstance(lhs, types.OrPatternCE) permutations = [] for i in range(0, 8): self.assertIsInstance(lhs.patterns[i], types.AndPatternCE) permutations.append(lhs.patterns[i].patterns) permutationExpected = [["A", "C"], ["B", "C"], ["A", "D"], ["B", "D"], ["A", "Z", "W"], ["A", "Z", "X"], ["B", "Z", "W"], ["B", "Z", "X"]] self.assertEqual(permutations, permutationExpected)
def do(self, theEnv, theName=None, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.4.html#Heading245 """ theName = self.resolve(theEnv, theName) if isinstance( theName, (types.FunctionCall, types.Variable)) else theName if theName is None: toClose = theEnv.RESOURCES.keys() elif not isinstance(theName, types.Symbol): raise InvalidArgTypeError( "Function open expected argument #1 to be of type symbol") else: toClose = [theName.evaluate()] if len(toClose) > 0: try: for resourceName in toClose: theEnv.RESOURCES[resourceName].close() del theEnv.RESOURCES[resourceName] return types.Symbol("TRUE") except KeyError: return types.Symbol("FALSE") else: return types.Symbol("FALSE")
def test_ReturnFalseIfNotFound(self): self.assertTrue( self.forInput( types.String("w"), types.String("Nel mezzo del cammin di nostra vita")).expect( types.Symbol("FALSE")))
def test_ErrorOnInvalidInput(self): self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Integer(2), types.String("blabla")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.String("blabla"), types.Float(2))
def test_StringIndexFound(self): self.assertTrue( self.forInput( types.String("camm"), types.String("Nel mezzo del cammin di nostra vita")).expect( types.Integer(15)))
def test_StringIndexFoundAlwaysTheFirstOne(self): self.assertTrue( self.forInput( types.String("e"), types.String("Nel mezzo del cammin di nostra vita")).expect( types.Integer(2)))
def test_NestedNotOrReversion(self): lhs = [ types.NotPatternCE( types.OrPatternCE([ "C", "D", types.AndPatternCE([ "Z", types.NotPatternCE(types.OrPatternCE(["W", "X"])) ]) ])) ] lhs = analysis.normalizeLHS(lhs, self.MM) self.assertIsInstance(lhs, types.OrPatternCE) permutations = [] for i in range(0, 4): self.assertIsInstance(lhs.patterns[i], types.AndPatternCE) self.assertIsInstance(lhs.patterns[i].patterns[1], types.NotPatternCE) if isinstance(lhs.patterns[i].patterns[1].pattern, types.AndPatternCE): permutations.append("~({0})".format(" ".join([ t if not isinstance(t, types.NotPatternCE) else "~" + t.pattern for t in lhs.patterns[i].patterns[1].pattern.patterns ]))) else: permutations.append("~" + lhs.patterns[i].patterns[1].pattern) permutationExpected = ["~C", "~D", "~(Z ~W)", "~(Z ~X)"] self.assertEqual(permutations, permutationExpected)
def _swapNotOr(Not, NotParent, NotIndex): # not arg is a single subpattern # it could be another and/or/not or an # ordered/template # (not (or must be converted to (or (not (not # (not (and (or must be converted to (or (not (and changed = False if isinstance(Not.pattern, types.OrPatternCE): # need to start a new browseOr here # before make reversions while _browseOr(Not.pattern): changed = True # then reverse (not (or with (or (not reversedOrArguments = [] for inOrPattern in Not.pattern.patterns: reversedOrArguments.append(types.NotPatternCE(inOrPattern)) # then replace the main Not arg with the new Or ([Not, Not,..]) NotParent[NotIndex] = types.OrPatternCE(reversedOrArguments) changed = True elif isinstance(Not.pattern, types.AndPatternCE): # if found an (not (and (??? # status, i need to try to reverse # all (and (or in the changed = _swapAndOr(Not.pattern, Not, None) or changed return changed
def _swapAndOr(And, AndParent, AndIndex): changed = False for index, inAndPattern in enumerate(And.patterns): if isinstance(inAndPattern, types.OrPatternCE): newOrPatterns = [] for orPattern in inAndPattern.patterns: #newOrPatterns = And.patterns[0:index] + [orPattern] + And.patterns[index+1:None] newOrPatterns.append(types.AndPatternCE(And.patterns[0:index] + [orPattern] + And.patterns[index+1:None])) newOr = types.OrPatternCE(newOrPatterns) if isinstance(AndParent, types.NotPatternCE): AndParent.pattern = newOr elif AndIndex is not None: AndParent[AndIndex] = newOr else: raise MyClipsBugException("Parent of And is not Not and no index is available") changed = True elif isinstance(inAndPattern, types.AndPatternCE): changed = _swapAndOr(inAndPattern, And.patterns, index) or changed elif isinstance(inAndPattern, types.NotPatternCE): changed = _swapNotOr(inAndPattern, And.patterns, index) or changed #if changed: # return changed return changed
def do(self, theEnv, theFirst, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.5.html#Heading256 """ theFirst = self.resolve(theEnv, theFirst) if isinstance( theFirst, (types.FunctionCall, types.Variable)) else theFirst if not isinstance(theFirst, (types.Integer, types.Float)): raise InvalidArgTypeError( "Function * expected argument #1 to be of type integer or float" ) theMul = theFirst.evaluate() for (index, theSecond) in enumerate(args): if isinstance(theSecond, (types.FunctionCall, types.Variable)): theSecond = self.resolve(theEnv, theSecond) if not isinstance(theSecond, (types.Integer, types.Float)): raise InvalidArgTypeError( "Function * expected argument #%d to be of type integer or float" % index + 2) theMul = theMul * theSecond.evaluate() # CLIPS documentation: # after all computations, if the value is still an integer, then create a new <Integer:theMul> # otherwise <Float:theMul> if isinstance(theMul, int): return types.Integer(theMul) else: return types.Float(theMul)
def test_ErrorOnDefRuleEval(self): theString = """ (defrule r (A B C) => ) """ theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, types.Symbol("FALSE"))
def test_InputClassKept(self): theString = "This_Is_a_MiXed_StrIng" theResultString = self.theFunc.do(self.theEnv, types.String(theString)) theResultSymbol = self.theFunc.do(self.theEnv, types.Symbol(theString)) self.assertEqual(theResultString.__class__, types.String) self.assertEqual(theResultSymbol.__class__, types.Symbol)
def test_Concatenation(self): theWme = WME(1, OrderedFact([])) self.assertTrue( self.forInput(types.Symbol("ciao"), types.String("mucca"), types.Integer(1), types.Float(1.5), theWme).expect( types.String("ciaomucca11.5" + str(theWme))))
def do(self, theEnv, thePath, theName, theMode=None, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.4.html#Heading244 """ thePath = self.resolve(theEnv, thePath) if isinstance( thePath, (types.FunctionCall, types.Variable)) else thePath theName = self.resolve(theEnv, theName) if isinstance( theName, (types.FunctionCall, types.Variable)) else theName theMode = self.resolve(theEnv, theMode) if isinstance(theMode, (types.FunctionCall, types.Variable)) \ else theMode if theMode is not None else types.String("r") if not isinstance(thePath, (types.String, types.Symbol)): raise InvalidArgTypeError( "Function open expected argument #1 to be of type string or symbol" ) # normalize the string to a path. In documentation: # all special chars and \ in the path must be escaped # these means that the path is already a valid path # for python thePath = thePath.evaluate() if isinstance( thePath, types.Symbol) else thePath.evaluate()[1:-1] if not isinstance(theName, types.Symbol): raise InvalidArgTypeError( "Function open expected argument #2 to be of type symbol") # check if a resource with the same logical name is already used assert isinstance(theEnv, FunctionEnv) if theEnv.RESOURCES.has_key(theName.evaluate()): raise InvalidArgValueError( "Illegal logical name used for open function: %s" % theName.evaluate()) if not isinstance(theMode, types.String): raise InvalidArgTypeError( "Function open expected argument #3 to be of type string") # normalize the mode removing quotes if <String> theMode = theMode.evaluate()[1:-1] modeMap = {"r": "rU", "r+": "rU+", "w": "w", "a": "a"} import myclips try: theMode = modeMap[theMode] fileResource = open(thePath, theMode) theEnv.RESOURCES[theName.evaluate()] = fileResource return types.Symbol("TRUE") except KeyError: myclips.logger.error("Invalid mode for Open: %s", theMode) return types.Symbol("FALSE") except IOError, e: myclips.logger.error("IOError in Open: %s", e) return types.Symbol("FALSE")
def test_FunctionResultToUpcase(self): theString = types.String("This_Is_a_MiXed_StrIng") theFuncCall = types.FunctionCall(types.Symbol("upcase"), self.theEnv.modulesManager, [theString]) theResult = self.theFunc.do(self.theEnv, theFuncCall) self.assertEqual(theResult.__class__, types.String) self.assertEqual(len(set(string.ascii_lowercase).intersection(set(theResult.evaluate()))), 0) self.assertEqual(theResult, self.theFunc.do(self.theEnv, theString))
def test_PushOne(self): Scope("A", self.theEnv.modulesManager) self.theEnv.modulesManager.changeCurrentScope("MAIN") self.assertTrue(self.forInput(types.Symbol("A")) .expect(types.Symbol("TRUE"))) self.assertEqual(self.theEnv.network.agenda.focusStack[-1], "A")
def do(self, theEnv, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.12.html#Heading316 """ try: return types.Symbol(theEnv.network.agenda.focusStack.pop()) except IndexError: return types.Symbol("FALSE")
def test_FunctionCallAsArgument(self): if not self.theEnv.modulesManager.currentScope.functions.has("upcase"): self.skipTest("upcase not defined") self.assertTrue( self.forInput( types.FunctionCall("upcase", self.theEnv.modulesManager, [types.String("acqua")]), types.String("acqua")).expect( types.Integer(cmp("acqua".upper(), "acqua"))))
def test_ErrorOnNotStringOrSymbolInpyt(self): self.assertRaisesRegexp(InvalidArgTypeError, "Function build expected argument #1 to be of type string or symbol", self.theFunc.do, self.theEnv, types.Integer(10)) self.assertRaisesRegexp(InvalidArgTypeError, "Function build expected argument #1 to be of type string or symbol", self.theFunc.do, self.theEnv, types.Float(1.5)) self.assertRaisesRegexp(InvalidArgTypeError, "Function build expected argument #1 to be of type string or symbol", self.theFunc.do, self.theEnv, [types.Symbol("bla")])
def test_EvalFunctionCall(self): if not self.theEnv.modulesManager.currentScope.functions.has("+"): self.skipTest("+ not defined") theString = """ (+ 1 1) """ theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, types.Integer(2))
def test_SimpleAndOrReversion(self): lhs = [types.AndPatternCE([types.OrPatternCE(["A", "B"]), "C"])] lhs = analysis.normalizeLHS(lhs, self.MM) self.assertIsInstance(lhs, types.OrPatternCE) self.assertIsInstance(lhs.patterns[0], types.AndPatternCE) self.assertIsInstance(lhs.patterns[1], types.AndPatternCE) self.assertEqual(lhs.patterns[0].patterns, ["A", "C"]) self.assertEqual(lhs.patterns[1].patterns, ["B", "C"])
def test_BuildModule(self): self.assertFalse(self.theEnv.modulesManager.isDefined("A")) theString = """ (defmodule A) """ theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, types.Symbol("TRUE")) self.assertTrue(self.theEnv.modulesManager.isDefined("A"))
def test_BuildRule(self): preRules = len(self.theEnv.network.rules) theString = """ (defrule r (A B C) => ) """ theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, types.Symbol("TRUE")) self.assertEqual(len(self.theEnv.network.rules), preRules + 1)
def test_EvalBaseTypes(self): typesMap = { "1": types.Integer(1), "1.5": types.Float(1.5), "symbol": types.Symbol("symbol"), '"string"': types.String("string") } for (theString, theResultCmp) in typesMap.items(): theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, theResultCmp)
def do(self, theEnv, theSubSet, theMultifield, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.2.html#Heading221 """ theSubSet = self.semplify(theEnv, theSubSet, list, ("1", "multifield")) theMultifield = self.semplify(theEnv, theMultifield, list, ("2", "multifield")) return types.Symbol("TRUE") if set(theSubSet) <= set( theMultifield) else types.Symbol("FALSE")
def test_DummyJoinNodeCreationAfterFirstPatternCE(self): self.network.addRule(types.DefRuleConstruct("A", self.MM, lhs=[ types.OrderedPatternCE([ types.Symbol("A"), types.Symbol("B"), types.Symbol("C"), ], self.MM) ])) self.assertIsInstance(self.network._root.children[0].children[0].children[0].children[0].children[0].memory.children[0], JoinNode) self.assertTrue(self.network._root.children[0].children[0].children[0].children[0].children[0].memory.children[0].isLeftRoot())
def test_ScopeRevertedAfterScopeChangeOnModuleBuilt(self): theOldScope = self.theEnv.modulesManager.currentScope.moduleName theString = """ (defmodule A) """ theResult = self.theFunc.do(self.theEnv, types.String(theString)) self.assertEqual(theResult, types.Symbol("TRUE")) self.assertTrue(self.theEnv.modulesManager.isDefined("A")) self.assertEqual(theOldScope, self.theEnv.modulesManager.currentScope.moduleName)
def normalizeLHS(lhs, MM): """ Change patterns orders (and nested patterns order) to normalize lhs in a Or (And ( normal form with all nested Or regrouped in a single top level Or """ if isinstance(lhs, list): # check if LHS has not pattern and handle this case as # (or (and (initial-fact))) if len(lhs) == 0: return types.OrPatternCE([types.AndPatternCE([_makeInitialFactPattern(MM)])]) # wrap the pattern list with an AndCE lhs = types.AndPatternCE(lhs) if isinstance(lhs, types.AndPatternCE): # wrap the AndCE with an OrCE lhs = types.OrPatternCE([lhs]) # then normalize lhs in a # form that has # all or inside the lhs reduced to # a single or at the top level of # the rule while _browseOr(lhs): continue # then compact all # (or (or # and # (and (and # as a single container while _compactPatterns(lhs): continue while _existsToNotNot(lhs): continue # then add a (initial-fact) # before (not or (test pattern # if they are first in the a group _initialFactNormalization(lhs, MM) return lhs