def test_ErrorOnInvalidInput(self): self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Symbol("1"), types.Integer(2), types.String("blabla")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Integer(2), types.Symbol("1"), types.String("blabla")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Integer(1), types.Integer(2), types.Integer("100"))
def test_EvalGlobalVar(self): from myclips.GlobalsManager import GlobalVarDefinition (self.theEnv.modulesManager.currentScope.globalsvars.addDefinition( GlobalVarDefinition( self.theEnv.modulesManager.currentScope.moduleName, "?*a*", types.GlobalAssignment( types.GlobalVariable(types.Symbol("a"), self.theEnv.modulesManager, True), types.Integer(1))))) self.assertTrue( self.forInput(types.String("?*a*")).expect(types.Integer(1)))
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#Heading258 """ 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 div expected argument #1 to be of type integer or float" ) theDiv = int(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 div expected argument #%d to be of type integer or float" % index + 2) # Division is always performed between integer values # and result is always casted to an integer theDiv = int(theDiv / int(theSecond.evaluate())) # WARNING: # this function always return an Integer! return types.Integer(theDiv)
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_StringIndexFoundAlwaysTheFirstOne(self): self.assertTrue( self.forInput( types.String("e"), types.String("Nel mezzo del cammin di nostra vita")).expect( types.Integer(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_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 test_ErrorOnNotStringOrSymbolInput(self): self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Integer(10), types.String("a")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Float(1.5), types.String("a")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, [types.Symbol("bla")], types.String("a")) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.String("a"), types.Integer(10)) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.String("a"), types.Float(1.5)) self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.String("a"), [types.Symbol("bla")])
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 do(self, theEnv, theWme, *args, **kargs): """ Function handler implementation @see http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.9.html#Heading306 """ theWme = self.semplify(theEnv, theWme, WME, ("1", "fact-address")) return types.Integer(theWme.factId)
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 do(self, theEnv, theMultifield, *args, **kargs): if myclips.STRICT_MODE: try: theMultifield = self.semplify(theEnv, theMultifield, list) theLength = len(theMultifield) except InvalidArgTypeError: theLength = -1 finally: return types.Integer(theLength) else: return _Length.do(self, theEnv, theMultifield, *args, **kargs)
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_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, theString, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.3.html#Heading240 """ # resolve to a python value (trim quotes from string too) theString = self.resolve(theEnv, # semplify to a BaseParsedType if variable or function call and check types self.semplify(theEnv, theString, (types.String, types.Symbol), ("1", "string or symbol"))) return types.Integer(len(theString))
def do(self, theEnv, theMultifield, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.7.html#Heading295 """ theMultifield = self.semplify(theEnv, theMultifield, (list, types.Lexeme), ("1", "multifield, string or symbol")) return types.Integer( len(theMultifield) if isinstance(theMultifield, list) else len( self.resolve(theEnv, theMultifield)))
def do(self, theEnv, theNumber, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.5.html#Heading263 """ theNumber = self.resolve(theEnv, theNumber) if isinstance( theNumber, (types.FunctionCall, types.Variable)) else theNumber if not isinstance(theNumber, (types.Integer, types.Integer)): raise InvalidArgTypeError( "Function integer expected argument #1 to be of type integer or float" ) return types.Integer(int(theNumber.evaluate()))
def do(self, theEnv, theValue, theMultifield, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.2.html#Heading220 """ theValue = self.semplify(theEnv, theValue, (types.Lexeme, types.Number, WME), ("1", "number, lexeme or fact")) theMultifield = self.semplify(theEnv, theMultifield, list, ("2", "multifield")) try: theIndex = theMultifield.index(theValue) except ValueError: return types.Symbol("FALSE") else: return types.Integer(theIndex)
def do(self, theEnv, theNeedle, theHaystack, *args, **kargs): """ handler of the function @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.3.html#Heading234 """ theNeedle = self.resolve(theEnv, self.semplify(theEnv, theNeedle, types.Lexeme, ("1", "string or symbol"))) theHaystack = self.resolve(theEnv, self.semplify(theEnv, theHaystack, types.Lexeme, ("2", "string or symbol"))) thePosition = pystring.find(theHaystack, theNeedle) if thePosition != -1: return types.Integer(thePosition + 1) else: return types.Symbol("FALSE")
def test_StringLength(self): self.assertTrue( self.forInput(types.String("12345678")).expect(types.Integer(8)))
def do(self, theEnv, theRange, *args, **kargs): """ handler of the Loop-For-Count function: classic for-i-from-1-to-n conditional structure @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.6.html#Heading282 """ returnValue = types.Symbol("FALSE") # theRange is the range specifier # it could be a list([<Variable>, <Integer:MIN>, <Integer:MAX>]) or a <Integer:MAX> if isinstance(theRange, list): # if it's list, then: # [0] is a variable # [1] is the min # [2] is the max if len(theRange) != 3 \ or not isinstance(theRange[0], types.SingleFieldVariable)\ or not isinstance(theRange[1], types.Integer)\ or not isinstance(theRange[2], types.Integer)\ : raise InvalidArgValueError( "Range specifier format for loop-for-count function must be a <Integer> or a [<Variable>, <Integer>, <Integer>]" ) theVarBind = theRange[0].evaluate() theMin = theRange[1].evaluate() theMax = theRange[2].evaluate() + 1 else: # function definition restriction ensure theRange to be a list or a <Integer> theMax = theRange.evaluate() + 1 theMin = 1 theVarBind = None theActions = [] # strip the optional DO from the args[0] if it's there if len(args) > 0: if isinstance(args[0], types.Symbol) and args[0].pyEqual("do"): theActions = list(args[1:]) else: theActions = list(args) # CLIPS documentation: # while will loop until theResult is a <Symbol:FALSE> or Return/Break functions are used # if return is used, the function execution halt # if break is used, loop break and while return a value # so, return is not caught here, but from the function caller # break are caught here instead try: for theVarValue in range(theMin, theMax): if theVarBind is not None: theEnv.variables[theVarBind] = types.Integer(theVarValue) for action in theActions: # function are executed if isinstance(action, types.FunctionCall): self.resolve(theEnv, action) except BreakException: # break caught, stop loooooooooop! pass # CLIPS documentation: # the if-then-else return value is always the value of the last execute action return returnValue
def test_IntegerIsNotEqualInteger(self): s1 = types.Integer("1") s2 = types.Integer("2") self.assertFalse(s1 == s2)
def test_ZeroLength(self): self.assertTrue( self.forInput(types.String("")).expect(types.Integer(0)))
def test_IntegerIsNotEqualFloatWithSameContent(self): s1 = types.Integer("1") s2 = types.Float("1") self.assertFalse(s1 == s2)
def test_IntegerIsANumber(self): s1 = types.Integer("1") self.assertIsInstance(s1, types.Number)
def test_ErrorOnInvalidInput(self): self.assertRaises(InvalidArgTypeError, self.theFunc.do, self.theEnv, types.Integer(2))
def test_IntegerIsNotALexeme(self): s1 = types.Integer("1") self.assertNotIsInstance(s1, types.Lexeme)
def test_NullStringIfFirstArgIsGreaterThanSecond(self): self.assertTrue( self.forInput(types.Integer(3), types.Integer(1), types.String("ciao")).expect(types.String("")))
def test_SingleCharFromString(self): self.assertTrue( self.forInput(types.Integer(3), types.Integer(3), types.String("ciao")).expect(types.String("a")))
def test_SubStingOfSymbol(self): self.assertTrue( self.forInput(types.Integer(1), types.Integer(3), types.Symbol("ciao")).expect(types.String("cia")))