Beispiel #1
0
    def do(self, funcEnv, resourceId, *args, **kargs):
        """
        Retract function handler implementation
        """

        # convert <TYPE:value> to python value
        resourceId = Function.resolve(
            self, funcEnv,
            self.semplify(funcEnv, resourceId, types.Symbol, ("1", "symbol")))

        if resourceId != "nil":
            try:
                resource = funcEnv.RESOURCES[resourceId]
            except KeyError:
                raise InvalidArgValueError(
                    "Resource with logical name %s cannot be found" %
                    str(resourceId))
            else:

                #                for fragment in args:
                #
                #                    # revolve variables and function calls
                #                    fragment = self.resolve(funcEnv, self.semplify(funcEnv, fragment))
                #
                #                    resource.write(str(fragment))

                resource.write("".join([
                    str(self.resolve(funcEnv, self.semplify(funcEnv, x)))
                    for x in args
                ]))

        return types.NullValue()
Beispiel #2
0
    def do(self, theEnv, aPath, *args, **kargs):
        """
        function handler implementation
        """

        aPath = self.resolve(
            theEnv,
            self.semplify(theEnv, aPath, types.Lexeme,
                          ('1', 'symbol or string')))

        aPath = os.path.abspath(aPath)

        if not exists(aPath):
            raise InvalidArgValueError(
                "Function load was unable to open file %s" % aPath)

        oldcwd = os.getcwd()

        os.chdir(os.path.dirname(aPath))

        aFile = open(aPath, 'rU')
        aString = aFile.read()

        try:
            parsed = theEnv.network.getParser().parse(aString, extended=True)
        except Exception, e:
            print >> theEnv.RESOURCES['werror'], theEnv.network.getParser(
            ).ExceptionPPrint(e, aString)
            os.chdir(oldcwd)
            return types.Symbol('FALSE')
Beispiel #3
0
    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")
Beispiel #4
0
 def do(self, theEnv, theValue, theComparison, theThen, *args, **kargs):
     """
     handler of the Case function:
         check theValue against theComparison: if they match
         the actions in the case arguments are executed
         otherwise an InvalidCaseException is raised to return control
         to the outer switch function 
     @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.6.html#Heading287
     """
     
     returnValue = types.Symbol("FALSE")
     
     # check for case format first:
     if not isinstance(theThen, types.Symbol) or theThen.pyEqual("then"):
         raise InvalidArgValueError("The `then` keyword is expected as second argument of a case clause")
     
     # resolve theComparison to its real value
     if isinstance(theComparison, (types.FunctionCall, types.Variable)):
         theComparison = self.resolve(theEnv, theComparison)
     
     # this is not the case    
     if theValue != theComparison:
         raise InvalidCaseException()
     
     # CLIPS documentation:
     # the return value of a case function is the one returned from the last
     # action in the case arguments
     for action in args:
         # function are executed
         if isinstance(action, (types.FunctionCall, types.Variable)):
             returnValue = self.resolve(theEnv, action)
         else:
             returnValue = action
         
     return returnValue
Beispiel #5
0
    def do(self, theEnv, theMultifield, theBegin, theEnd, *args, **kargs):
        """
        handler of the function
        @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.2.html#Heading225
        """

        
        theMultifield = self.semplify(theEnv, theMultifield, list, ("1", "multifield"))
        theBegin = self.resolve(theEnv, 
                                    self.semplify(theEnv, theBegin, types.Integer, ("2", "integer")))
        theEnd = self.resolve(theEnv, 
                                    self.semplify(theEnv, theEnd, types.Integer, ("3", "integer")))

        try:
            if theBegin != theEnd:
                # remove a slice of the multifield
                # check for index values first
                if theBegin - 1 >= len(theMultifield) or theEnd > len(theMultifield):
                    raise IndexError()
                return theMultifield[theBegin-1:theEnd]
            else:
                # remove a single item from the multifield
                return [theMultifield[theBegin-1]]
        except IndexError:
            # invalid field!
            raise InvalidArgValueError("Multifield index %s out of range 1..%d in function delete$"%(
                                            ("range %d..%d"%(theBegin, theEnd) if theBegin != theEnd else str(theBegin)),
                                            len(theMultifield)
                                        ))
Beispiel #6
0
    def createFact(self, theEnv, arg):
        if isinstance(arg, types.OrderedRhsPattern):

            return OrderedFact(
                values=[
                    self.semplify(theEnv,
                                  v)  # resolve to BaseParsedTypes if needed
                    for v in arg.values
                ],
                moduleName=theEnv.modulesManager.currentScope.moduleName)

        elif isinstance(arg, types.TemplateRhsPattern):
            # convert it in a new Template Fact
            # the fact value is a dict with (slotName, slotValue) where slotValue
            # need to be resolved

            return TemplateFact(
                templateName=arg.templateName,
                values=dict([(v.slotName, self.semplify(theEnv, v.slotValue))
                             for v in arg.templateSlots]),
                moduleName=theEnv.modulesManager.currentScope.templates.
                getDefinition(arg.templateName).moduleName)

        else:
            raise InvalidArgValueError("Invalid fact format")
Beispiel #7
0
    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")
Beispiel #8
0
    def do(self, theEnv, theCondition, theThen, *args, **kargs):
        """
        handler of the IfThenElse function:
            if-then-else conditional structure
        @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.6.html#Heading280
        """
        
        returnValue = types.NullValue()
        
        if not theThen.pyEqual("then"):
            raise InvalidArgValueError("Check appropriate syntax for if function: if expects second argument to be the `then` keyword")
        
        # try to split the then-actions from the else-actions
        
        thenActions = []
        elseActions = []
        
        workingOn = thenActions
        for action in args:
            if isinstance(action, types.Symbol) and action.pyEqual("else"): 
                workingOn = elseActions
            else:
                workingOn.append(action)
            
        # if no else is found, not problem: elseActions is empty and all actions are in thenActions
        
        
        # time to evaluate the condition
        
        if isinstance(theCondition, types.FunctionCall):
            theCondition = self.resolve(theEnv, theCondition)
        
        # CLIPS documentation:
        # then-actions are executed if the result of theCondition is not <Symbol:FALSE>
        # (even <NullValue> is a true-like value)
        # else-actions are executed only if return of theCondition is exactly <Symbol:FALSE>
        
        if isinstance(theCondition, types.Symbol) and theCondition.pyEqual("FALSE"):
            # execute ELSE
            theActions = elseActions
        else:
            # execute THEN
            theActions = thenActions

        for action in theActions:
            # function are executed
            if isinstance(action, types.FunctionCall):
                returnValue = self.resolve(theEnv, action)
            else:
                # types work as return values
                returnValue = action
            
        # CLIPS documentation:
        # the if-then-else return value is always the value of the last execute action
        return returnValue
    def do(self, theEnv, *args, **kargs):
        """
        function handler implementation
        """
        try:
            _thePNodes = [
                theEnv.network.getPNode(ruleName) for ruleName in [
                    self.resolve(
                        theEnv,
                        self.semplify(theEnv, ruleName, types.Symbol, (
                            "ALL", "symbol"))) for ruleName in args
                ]
            ]
        except RuleNotFoundError, e:

            raise InvalidArgValueError(e.message)
Beispiel #10
0
 def resolveFact(self, funcEnv, arg):
     """
     Resolve integer, *, WME to a WME or a list of WME
     or raise exception if invalid arg
     """
     if isinstance(arg, types.Integer):
         #convert the <Interger:INT> into a <WME:f-INT>
         return funcEnv.network.getWmeFromId(arg.evaluate())
     elif isinstance(arg, types.Symbol) and arg.evaluate() == "*":
         # if (retract *) format is used, i have to retract all
         # fact in working memory that this scope can see
         return funcEnv.network.factsForScope()
     elif isinstance(arg, WME):
         return arg
     else:
         raise InvalidArgValueError("Invalid fact format")
Beispiel #11
0
    def do(self, theEnv, theFact, *args, **kargs):
        """
        Function handler implementation
        @see http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.9.html#Heading303
        """

        # 1) resolve the theFact to a WME
        theFact = self.resolveFact(
            theEnv,
            self.semplify(theEnv, theFact, (WME, types.Integer),
                          ('1', "fact-address or integer")))

        # 2) check if it's a template fact
        if not isinstance(theFact.fact, TemplateFact):
            raise InvalidArgValueError("")

        # 3) get a copy of the fact inside the wme
        theBackup = theFact.fact

        # 4) retract the wme
        theEnv.network.retractFact(theFact)

        del theFact

        # 5) modify the fact with the new values for the slots:

        for theSlot in args:
            # each arg is a types.OrderedRhsQualcosa: index 0 is the slot name, then values
            assert isinstance(theSlot, types.OrderedRhsPattern)
            theSlotName = self.resolve(
                theEnv, self.semplify(theEnv, theSlot.values[0], types.Symbol))

            if len(theSlot.values) > 2:
                # it's a multifield
                theSlotValues = self.semplify(theEnv, theSlot.values[1:None])
            else:
                # it's a single field
                theSlotValues = self.semplify(theEnv, theSlot.values[1])

            theBackup[theSlotName] = theSlotValues

        # 6) assert the new fact

        theWme, isNew = theEnv.network.assertFact(theBackup)

        return theWme if isNew else types.Symbol("FALSE")
Beispiel #12
0
    def do(self, funcEnv, resourceId, theFormat, *args, **kargs):
        """
        Function handler implementation
        """

        resourceId = self.semplify(funcEnv, resourceId, (types.Symbol),
                                   ("1", "symbol"))

        theFormat = self.resolve(
            funcEnv,
            self.semplify(funcEnv, theFormat, (types.String), ("2", "string")))

        try:
            if not resourceId.pyEqual('nil'):
                resource = funcEnv.RESOURCES[resourceId.evaluate()]
            else:
                resource = None
        except KeyError:
            raise InvalidArgValueError(
                "Resource with logical name %s cannot be found" %
                str(resourceId))
        else:

            returnValueRaw = []

            for fragment in args:

                # revolve variables and function calls
                returnValueRaw.append(
                    self.resolve(funcEnv, self.semplify(funcEnv, fragment)))

            # execute replacement of special chars:
            #
            theFormat = theFormat.replace("%n", "\n")\
                                    .replace("%r", "\r")\
                                    #.replace("%%", "%")

            # theFormat is a string
            returnValueRaw = theFormat % tuple(returnValueRaw)

            if resource is not None:
                resource.write(returnValueRaw)

            return types.String(returnValueRaw)
Beispiel #13
0
    def do(self, theEnv, theMultifield, theBegin, theEnd, *args, **kargs):
        """
        handler of the function
        @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.2.html#Heading226
        """

        theMultifield = self.semplify(theEnv, theMultifield, list,
                                      ("1", "multifield"))
        theBegin = self.resolve(
            theEnv,
            self.semplify(theEnv, theBegin, types.Integer, ("2", "integer")))
        theEnd = self.resolve(
            theEnv,
            self.semplify(theEnv, theEnd, types.Integer, ("3", "integer")))

        try:
            if theBegin - 1 >= len(theMultifield) or theEnd > len(
                    theMultifield):
                raise IndexError()

            theBegin = theMultifield[0:theBegin - 1]
            theEnd = theMultifield[theEnd:None]

        except IndexError:
            # invalid field!
            raise InvalidArgValueError(
                "Multifield index %s out of range 1..%d in function delete$" %
                (("range %d..%d" %
                  (theBegin, theEnd) if theBegin != theEnd else str(theBegin)),
                 len(theMultifield)))
        else:
            theInner = []
            for theArg in args:
                theArg = self.semplify(
                    theEnv, theArg, (list),
                    ("1", "number, lexeme, fact-address or multifield"))
                if isinstance(theArg, list):
                    theInner += theArg
                else:
                    theInner.append(theArg)

            return theBegin + theInner + theEnd
    def do(self, theEnv, theStrategy, *args, **kargs):
        """
        handler of the function
        @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-13.7.html#Heading452
        """

        theStrategy = self.resolve(
            theEnv,
            self.semplify(theEnv, theStrategy, types.Symbol, ("1", "symbol")))

        if strategies.factory.isValid(theStrategy):
            theOld = theEnv.network.agenda.changeStrategy(
                strategies.factory.newInstance(theStrategy))
            return types.Symbol(theOld)
        else:
            raise InvalidArgValueError(
                "Function set-strategy expected argument #1 to be of type symbol "
                +
                "with value depth, breadth, lex, mea, complexity, simplicity, or random"
            )
Beispiel #15
0
 def createFact(self, theEnv, arg):
     if isinstance(arg, types.OrderedRhsPattern):
         # convert it in a new Ordered Fact
         return OrderedFact(values=[self.semplify(theEnv, v, types.BaseParsedType) for v in arg.values], 
                            moduleName=theEnv.modulesManager.currentScope.moduleName)
         
     elif isinstance(arg, types.TemplateRhsPattern):
         # convert it in a new Template Fact
         # the fact value is a dict with (slotName, slotValue) where slotValue:
                             # is a baseparsedtype if singlefield
                             
         return TemplateFact(templateName=arg.templateName, 
                             values=dict([(v.slotName, self.semplify(theEnv, v.slotValue, types.BaseParsedType)) if isinstance(v, types.SingleFieldRhsSlot)
                                             # or a list if multifield (solved, this means is a list of base-parsed-type)
                                             else (v.slotName, self.semplify(theEnv, v.slotValue, list)) if isinstance(v, types.MultiFieldRhsSlot)
                                                 else (v.slotName, v.slotValue) #don't know what to do FIXME
                           for v in arg.templateSlots]), 
                             moduleName=theEnv.modulesManager.currentScope.templates.getDefinition(arg.templateName).moduleName)
                             
     else:
         raise InvalidArgValueError("Unknown fact format in RHS pattern")
Beispiel #16
0
    def do(self, theEnv, theExpression, *args, **kargs):
        """
        handler of the Switch function:
            regroup a list of case functions and execute the right one
            for the theCondition value. Execute a default case
            if not case cases match if a default case exists,
            otherwise return None
        @see: http://www.comp.rgu.ac.uk/staff/smc/teaching/clips/vol1/vol1-12.6.html#Heading287
        """
        
        # theExpression have to be evaluated and compared to each case
        # if expression value match the case, it's executed
        # and its return value returned
        # if no expression match and a default is provided, default is executed
        
        # phase 1:
        # filter/check case function in args
        # and isolate the last default function (if any)
        
        theCases = []
        theDefault = None
        if len(args) > 0:
            for index in range(0, len(args)):
                caseFunc = args[index]
                if isinstance(caseFunc, types.FunctionCall) and caseFunc.funcName == "case":
                    theCases.append(caseFunc)
                elif isinstance(caseFunc, types.FunctionCall) and caseFunc.funcName == "default":
                    if index == len(args) - 1:
                        theDefault = caseFunc
                    else:
                        raise InvalidArgValueError("Default clause for a switch function have to be the last one")
                else:
                    raise InvalidArgTypeError("Invalid argument for a switch function: %s"%str(caseFunc))
                
        
        # phase 2:
        # calculate the value for the theExpression
        if isinstance(theExpression, (types.FunctionCall, types.Variable) ):
            theResult = self.resolve(theEnv, theExpression)
        else:
            theResult = theExpression

        returnValue = None
        
        # phase 3:
        # evaluate the "case function" arguments
        for caseFunc in theCases:
            # execute the case Function
            # if it return something not None, it's ok
            # if return is None = it's not the right case
            # (maybe it's better and exception)
            try:
                returnValue = caseFunc.funcDefinition.linkedType.__class__.execute(caseFunc.funcDefinition.linkedType, 
                                                                                   theEnv, theResult, *(caseFunc.funcArgs))
                break # break the for at the first positive case clause executed
            except InvalidCaseException:
                pass

        # phase 4:
        # if returnValue == None, then no case match
        # try to execute the default if any
        # otherwise return None
            
        if returnValue is None and theDefault is not None:
            return theDefault.funcDefinition.linkedType.__class__.execute(theDefault.funcDefinition.linkedType, 
                                                                          theEnv, theResult, *(theDefault.funcArgs))
        else:
            return returnValue if returnValue is not None else types.Symbol("FALSE")
Beispiel #17
0
    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#Heading247
        """

        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"]
            needSeek = False
        elif not isinstance(theName, types.Symbol):
            raise InvalidArgTypeError(
                "Function read expected argument #1 to be of type symbol")
        else:
            theResource = theEnv.RESOURCES[theName.evaluate()]
            needSeek = True

        # get a ConstantParser: it will read 1 single Lexeme|Number from a string
        constantParser = theEnv.network.getParser().getSParser(
            'ConstantParser')

        quoteGuard = None

        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")

            quoteGuard = theString[0] == '"'

            if quoteGuard:
                # need to read a <String>
                while True:

                    theToken = constantParser.scanString(theString).next()
                    theResult = theToken[0][0]

                    # check if the Result is a String
                    if isinstance(theResult, types.String):
                        # <String> found, continue
                        break
                    else:
                        # i've not found a string
                        # this means i've not read enoght to find
                        # the end quote for the string and the parser
                        # read a symbol instead
                        theOtherString = theResource.readline()
                        if theOtherString == "":
                            raise InvalidArgValueError(
                                "Encountered End-Of-File while scanning a string: %s"
                                % theString)
                        theString += theOtherString

            else:
                # anything is ok
                # read only the first one
                theToken = constantParser.scanString(theString).next()
                theResult = theToken[0][0]

            if needSeek:
                # need to seek the resource read pointer
                # to the first not read char
                endPosition = theToken[2]
                theResource.seek(endPosition - len(theString) + 1,
                                 1)  # 1 == relative to the position

            return theResult

        except (StopIteration, EOFError):
            return types.Symbol("EOF")
        except IOError:
            return types.Symbol("*** READ ERROR ***")
    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