示例#1
0
 def change_variables(self, query, common_predicate_name):
     new_query = copy.deepcopy(query)
     variables_names = [chr(i) for i in range(97, 123)]
     for id_c, cq in enumerate(query):
         for predicate in cq:
             if predicate.name == common_predicate_name:
                 standard_names = [
                     variable.name for variable in predicate.variables
                 ]
         for id_p, predicate in enumerate(cq):
             if not predicate.name == common_predicate_name:
                 for id_v, variable in enumerate(predicate.variables):
                     if variable.name in standard_names:
                         index = standard_names.index(variable.name)
                         if index > 25:
                             print("wrong index")
                         else:
                             new_query[id_c][id_p].variables[
                                 id_v].name = variables_names[index]
     variables = []
     for i in range(len(standard_names)):
         variables.append(Variable(variables_names[i]))
     s1 = Predicate(common_predicate_name, variables)
     query1 = [[s1]]
     query2 = []
     for id_c, cq in enumerate(new_query):
         query2.append([])
         for predicate in cq:
             if not predicate.name == common_predicate_name:
                 query2[id_c].append(predicate)
     return query1, query2
示例#2
0
 def predicateParser(self, one_pred_str):
     left_idx = one_pred_str.find('(')
     right_idx = one_pred_str.find(')')
     pred_name = one_pred_str[0:left_idx]
     var_strs = one_pred_str[left_idx + 1:right_idx].strip().split(',')
     variables = [Variable(one_var.strip()) for one_var in var_strs]
     return Predicate(pred_name, variables)
示例#3
0
class Condition:
    def __init__(self, subject, predicate, object):
        SUBJECTS = {'Subject' : self.subject,
                    'Sender' : self.sender,
                    'To' : self.to,
                    'Cc' : self.cc,
                    'To or cc' : self.toOrCc,
                    'X-Spam-Flag' : self.xSpamFlag,
                    'Reply-To' : self.replyTo}
        if subject in SUBJECTS:
            self.match = SUBJECTS[subject]
        else:
            raise KeyError(subject)
        self.predicate = Predicate(predicate,object)
        self.object = object
        
    def subject(self, email):
        return self.predicate.match(email.get('Subject'))
    def sender(self, email):
        return self.predicate.match(email.get('From'))
    def to(self, email):
        return self.predicate.match(email.get('To'))
    def cc(self, email):
        return self.predicate.match(email.get('Cc'))
    def toOrCc(self, email):
        return self.to(email) or self.cc(email)
    def xSpamFlag(self, email):
        return self.predicate.match(email.get('X-Spam-Flag'))
    def replyTo(self, email):
        return self.predicate.match(email.get('Reply-To'))
示例#4
0
 def __init__(self, subject, predicate, object):
     SUBJECTS = {'Subject' : self.subject,
                 'Sender' : self.sender,
                 'To' : self.to,
                 'Cc' : self.cc,
                 'To or cc' : self.toOrCc,
                 'X-Spam-Flag' : self.xSpamFlag,
                 'Reply-To' : self.replyTo}
     if subject in SUBJECTS:
         self.match = SUBJECTS[subject]
     else:
         raise KeyError(subject)
     self.predicate = Predicate(predicate,object)
     self.object = object
示例#5
0
    def createPredicateFromPackage(cls, interpreter, p_inp, name):
        """
        Create a new predicate. Class method that creates a new predicate from a package.

        :param interpreter:  Interpreter
        :param p_inp: str (full package, e.g., G{?a,?b})
        :param name: str
        :return: boolean
        """

        if independent(p_inp):
            interpreter.raiseError(
                f"Error: Trying to use a package with variables, with name {name}"
            )
            return False

        p_name, _, p_inp = p_inp.partition("{")
        p_inp = p_inp[:-1]

        if p_name not in interpreter.packages:
            interpreter.raiseError(f"Error: Package {p_name} not found.")
            return False

        pack_match = interpreter.packages[p_name]

        t = MatchDictionary.match(interpreter, p_inp, pack_match.p_pat)
        if t:
            forward, backward, _ = t
            new_pred = Predicate(interpreter, name, pack_match.recursive,
                                 pack_match.random)
            for basic in pack_match.basic:
                new_pred.addBasic(smart_replace(basic, forward))
            for falsehood in pack_match.nope:
                new_pred.addNot(smart_replace(falsehood, forward))
            for i in range(pack_match.count):
                new_pred.addCase(smart_replace(pack_match.cases[i], forward),
                                 smart_replace(pack_match.then[i], forward))

            interpreter.predicates[name] = new_pred

            return True
示例#6
0
 def readTypes(self):
     types = list(self.prologInterface.simpleQuery('base(X).'))
     for t in types:
         t = t['X']
         predicate = None
         typ = []
         predicateName = ''
         predicateType = ''
         addPredicateName = True
         addPredicateType = False
         for st in t:
             if(st == ' ' or st == ''):
                 continue
             else:
                 if(st == '('):
                     predicate = Predicate()
                     predicate.setName(predicateName)
                     addPredicateType = True
                     addPredicateName = False
                     continue
                 elif(st == ',' or st == ')'):
                     typ.append(predicateType)
                     predicateType = ''
                     addPredicateType = True
                     continue
                 else:
                     pass
                 if(addPredicateName):
                     predicateName += st
                 elif(addPredicateType):
                     predicateType += st
                 else:
                     pass
         predicate.addTypes(typ)
         predicate.addArity(len(typ))
         self.dictOfPredicates[predicateName] = predicate
示例#7
0
 def readModes(self):
     modes = list(self.prologInterface.simpleQuery('mode(Z,X,Y).'))
     for m in modes:
         m1 = m
         m = m['Y']
         if m[0] == ',':
             m = m[2:len(m)-1]
         elif m[0] == '(':
             m = m[1:len(m)-1]
         else:
             pass
         predicate = None
         conditionalPredicates = []
         mod = []
         predicateName = ''
         predicateType = ''
         addPredicateName = True
         addPredicateType = False
         insideBracket = False
         for st in m:
             if(st == ' ' or st == ''):
                 continue
             else:
                 if(st == '('):
                     predicate = Predicate()
                     predicate.setName(predicateName)
                     p = self.dictOfPredicates[predicateName]
                     predicate.addTypes(p.getTypes())
                     addPredicateType = True
                     insideBracket = True
                     addPredicateName = False
                     continue
                 elif(st == ',' and insideBracket):
                     mod.append(predicateType)
                     predicateType = ''
                     addPredicateType = True
                     continue
                 elif(st == ')' and insideBracket):
                     mod.append(predicateType)
                     predicateType = ''
                     addPredicateType = True
                     insideBracket = False
                     continue
                 elif(st == ',' and not insideBracket):
                     predicate.addModes(m1['Z'], 'none', mod, [])
                     predicate.addArity(len(mod))
                     conditionalPredicates.append(predicate)
                     mod = []
                     predicateName = ''
                     predicateType = ''
                     addPredicateName = True
                     continue
                 else:
                     pass
                 if(addPredicateName):
                     predicateName += st
                 elif(addPredicateType):
                     predicateType += st
                 else:
                     pass
         predicate.addModes(m1['Z'], m1['X'], mod, conditionalPredicates)
         predicate.addArity(len(mod))
         if(self.dictOfPredicates.has_key(predicateName)):
             predicate1 = self.dictOfPredicates[predicateName]
             predicate1.addModes(m1['Z'], m1['X'], mod, conditionalPredicates)
             predicate1.appendAggregators(m1['Z'], m1['X'])
         else:
             predicate.appendAggregators(m1['Z'], m1['X'])
             self.dictOfPredicates[predicateName] = predicate
示例#8
0
def builtin(interpreter, query_name, query_pat, depth, found):
    """
    Builtin predicates (many different libraries).

    :param interpreter: Interpreter
    :param query_name: str
    :param query_pat: str
    :param depth: Counter
    :param found: "pointer" bool
    :return: Generator
    """

    found[0] = True

    # checks for terminal match
    if query_name == "GuaranteeUnify":
        comps = splitWithoutParen(query_pat)
        if len(comps) != 2:
            return
        comp1, comp2 = comps
        m = MatchDictionary.match(interpreter, comp1, comp2)
        if m and not m[2]:
            yield {}
        return

    # Can be unified
    if query_name == "CanUnify":
        comps = splitWithoutParen(query_pat)
        if len(comps) != 2:
            return
        comp1, comp2 = comps
        m = MatchDictionary.match(interpreter, comp1, comp2)
        if m:
            yield {}
        return

    # Exact copy of a pattern
    if query_name == "ExactCopy":
        comps = splitWithoutParen(query_pat)
        if len(comps) != 2:
            return
        comp1, comp2 = comps
        bs = get_all_basics(comp1)
        copy = MatchDictionary.transform(comp1, bs, {})
        m = MatchDictionary.match(interpreter, comp2, copy)
        if m:
            print(m[1])
            yield m[1]
        return

    # Online Request
    if query_name == "Request":
        parts = splitWithoutParen(query_pat)
        if len(parts) != 2:
            return
        try:
            inLcl = url_opener(parts[0][1:-1])
            if inLcl is None:
                return
            m = MatchDictionary.match(interpreter, parts[1], inLcl)
            if m:
                yield m[1]
        except Exception as e:
            print(e)
        finally:
            return

    # Ref.new - Create reference
    if query_name == "Ref.new":
        comps = splitWithoutParen(query_pat)
        if len(comps) != 1:
            return
        comp1, = comps
        if match_type(comp1) != "var":
            return
        rand = hex(randint(10000, 10000000))
        while rand in interpreter.references:
            rand = hex(randint(100, 100000))
        interpreter.references[rand] = "nil"
        yield {comp1: rand}
        return

    # Ref.del - delete a reference
    if query_name == "Ref.del":
        comps = splitWithoutParen(query_pat)
        if len(comps) != 1:
            return
        comp1, = comps
        if comp1 not in interpreter.references:
            return
        del interpreter.references[comp1]
        yield {}
        return

    if query_name == "SecIns":
        print(">> ", end="")
        inspect = input()
        try:
            print(eval(inspect))
            yield {}
        except Exception as e:
            print(e)
        return

    # Break predicate
    if query_name == 'hBreak' and (interpreter.list_added
                                   or interpreter.types_added):
        parts = splitWithoutParen(query_pat)
        if len(parts) != 2 or "[" in parts[0] or "?" in parts[0]:
            return
        broken = list(parts[0])
        if len(broken) == 0:
            return
        inLcl = '['
        for broke in broken:
            inLcl += broke + ","
        inLcl = inLcl[:-1] + "]"
        m = MatchDictionary.match(interpreter, parts[1], inLcl)
        if m:
            yield m[1]
        return

    # domain generator
    if query_name == "Domain-Generator":
        parts = splitWithoutParen(query_pat)
        if len(parts) != 4 or any(
                match_type(part) != "list" for part in parts):
            return
        variables = splitWithoutParen(parts[0][1:-1])
        if any(match_type(pattern) != "var" for pattern in variables):
            return
        ranges = splitWithoutParen(parts[1][1:-1])
        if len(ranges) != len(variables):
            return
        constraints = splitWithoutParen(parts[2][1:-1])
        elims = splitWithoutParen(parts[3][1:-1])
        D = Domain(interpreter, "~~Anon")
        D.variables = variables
        D.raw_vars = parts[0][1:-1]
        for i, var in enumerate(variables):
            D.range_searches[var] = ranges[i]
        for const in constraints:
            D.insert_constraint(const, "", -1)
        for elim in elims:
            D.insert_elimination(elim, "", -1)
        yield from D.search(depth, parts[0][1:-1])

    # Input
    if query_name == "hInput" and interpreter.strings_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if parts[0][0] != "?":
            return
        yield "Request"
        inp = interpreter.received_input
        interpreter.received_input = False
        yield {parts[0]: '"' + inp + '"'}

    # isList predicate (checks if list)
    if query_name == 'isList' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if parts[0][0] == "[":
            yield {}
        return

    # isVar predicate (checks if variable)
    if query_name == 'isVar' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if '?' == parts[0][0]:
            yield {}
        return

    # Title predicate (checks if title)
    if query_name == 'isTitle' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        try:
            T_name, _, T_pat = parts[0].partition("(")
            if T_name in interpreter.titles:
                yield {}
        except IndexError:
            pass
        except ValueError:
            pass
        return

    # Integer predicate (checks if integer)
    if query_name == 'isInteger' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        try:
            a = int(parts[0])
            yield {}
        except IndexError:
            pass
        except ValueError:
            pass
        return

    # Floating predicate (checks if float)
    if query_name == 'isFloating' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        try:
            a = float(parts[0])
            yield {}
        except IndexError:
            pass
        except ValueError:
            pass
        return

    # Known Predicate (checks if variables in predicate)
    if query_name == 'isKnown' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if outString(parts[0], "?"):
            return
        yield {}

    # Predicate predicate (is it a predicate)
    if query_name == 'isPredicate' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if parts[0] in interpreter.predicates or \
                (parts[0] in ['Add', 'Sub', 'Mul', 'Div', 'Mod', 'Floor', 'Ceil', 'Power', 'Log', 'Sin', 'Cos', 'Tan',
                              'LT'] and interpreter.math_added) \
                or parts[0] == 'Print' or parts[0] == 'Predicate' or (parts[0] == 'Break' and interpreter.list_added):
            yield {}
        return

    # isPackage predicate (is it a package)
    if query_name == 'isPackage' and interpreter.types_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if parts[0] in interpreter.packages:
            yield {}
        return

    # Math Predicates
    if query_name in [
            'hAdd', 'hSub', 'hMul', 'hDiv', 'hMod', 'hFloor', 'hCeil',
            'hPower', 'hLog', 'hSin', 'hCos', 'hTan', 'hLT', 'hE'
    ] and interpreter.math_added:
        yield from MathHelper.Reader(query_name, query_pat)
        return

    # Print 'predicate'
    if query_name == 'Print':
        parts = splitWithoutParen(query_pat)
        printible = []
        for part in parts:
            printible.append(formatPrint(part))
        printed = joinPrint(printible)
        interpreter.message(printed)
        yield "Print"
        if len(query_pat) != 0 and query_pat[-1] == ",":
            interpreter.newline = True
        else:
            interpreter.newline = False
        yield {}

    # AllSolutions predicate
    if query_name == 'hAllSolutions' and interpreter.predicates_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 3:
            return
        if parts[0][0] == "?":
            return
        try:
            n = int(parts[1])
        except ValueError:
            return
        sols = []
        pattern = ",".join([f"?x{j}" for j in range(n)])
        q = f"{parts[0]}({pattern})"
        for sol in interpreter.mixed_query(q, 0, depth.count, True):
            sols.append(smart_replace(f"[{pattern}]", sol))
        final = "[" + ",".join(sols) + "]"
        m = MatchDictionary.match(interpreter, parts[2], final)
        if m:
            yield m[1]
        return

    # Save predicate
    if query_name == 'hSave' and interpreter.save_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return
        if outString(parts[0], "?"):
            return
        to_save = parts[0]
        interpreter.saved.insert(0, to_save)
        yield {}
        return

    # helper Load predicate
    if query_name == 'hLoad' and interpreter.save_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) == 1:
            if len(interpreter.saved) == 0:
                return
            else:
                to_load = interpreter.saved.popleft()
                t = MatchDictionary.match(interpreter, parts[0], to_load)
                if t:
                    yield t[1]
        return

    # Chars predicate
    if query_name == 'ToChars' and interpreter.strings_added:

        parts = splitWithoutParen(query_pat)
        if len(parts) != 2 or outString("[", parts[0]) or outString(
                parts[0], "?") or parts[0][0] != '"' or parts[0][-1] != '"':
            return
        broken = list(parts[0][1:-1])
        inLcl = '[' + ",".join(list(map(lambda c: f'"{c}"', broken))) + "]"
        m = MatchDictionary.match(interpreter, parts[1], inLcl)
        if m:
            yield m[1]
        return

    # Chars to String
    if query_name == 'ToString' and interpreter.strings_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 2 or outString(
                parts[0], "?") or "[" != parts[0][0] or "]" != parts[0][-1]:
            return

        broken = splitWithoutParen(parts[0][1:-1])
        inLcl = '"'
        for broke in broken:
            if broke[0] != '"' or broke[-1] != '"':
                return
            inLcl += broke[1:-1]
        inLcl += '"'
        m = MatchDictionary.match(interpreter, parts[1], inLcl)
        if m:
            yield m[1]
        return

    # open file
    if query_name == 'hOpen' and interpreter.filestream_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 3:
            return
        file_name, file_type, file_var = parts
        if match_type(file_var) != "var":
            return
        file_name = file_name[1:-1]
        print(file_name)
        if file_type not in ["r", "w", "a", "rp"]:
            if file_type == "rp":
                file_type = "r+"
            interpreter.raiseError(f"Error: Illegal file type '{file_type}'")
            return
        if ":" not in file_name:
            try:
                f = open(interpreter.filepath + "/" + file_name, file_type)
            except FileNotFoundError:
                interpreter.raiseError(f"Error: File not found, '{file_name}'")
                return
        else:
            try:
                f = open(file_name, file_type)
            except FileNotFoundError:
                interpreter.raiseError(f"Error: File not found, '{file_name}'")
                return
        file_hash = hashlib.md5(
            (random().as_integer_ratio()[0] +
             random().as_integer_ratio()[1]).__str__().encode()).hexdigest()
        interpreter.files[file_hash] = f
        yield {file_var: file_hash}
        return

    # read file
    if query_name == 'hRead' and interpreter.filestream_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 2:
            return
        file_name, char_to = parts
        if match_type(char_to) != 'var':
            return False
        if file_name not in interpreter.files:
            interpreter.raiseError(f"Error: File '{file_name}' not opened.")
            return
        file_read = interpreter.files[file_name]
        try:
            c = file_read.read(1)
        except UnsupportedOperation:
            interpreter.raiseError(f"Error: File '{file_name}' not readable.")
            return

        yield {char_to: '"' + c + '"'}
        return

    # write in file
    if query_name == 'hWrite' and interpreter.filestream_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 2:
            return
        file_name, write = parts
        if write[0] == '"':
            write = write[1:-1]
        if file_name not in interpreter.files:
            interpreter.raiseError(f"Error: File '{file_name}' not opened.")
            return

        try:
            interpreter.files[file_name].write(write)
        except UnsupportedOperation:
            interpreter.raiseError(f"Error: File '{file_name}' not writable.")
            return

        yield {}

    # close file
    if query_name == 'hClose' and interpreter.filestream_added:
        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return

        file_name = parts[0]
        if file_name in interpreter.files:
            interpreter.files[file_name].close()
            interpreter.files.pop(file_name)
            yield {}
            return
        else:
            interpreter.raiseError(f"Error: file '{file_name}' not found.")
            return

    # Tracing searching algorithm
    if query_name == "Trace" and interpreter.inspect_added:
        if query_pat == "On":
            interpreter.trace_on = True
        elif query_pat == "Off":
            interpreter.trace_on = False
        elif query_pat == "OnOn":
            interpreter.console_trace_on = True
        elif query_pat == "OffOff":
            interpreter.console_trace_on = False
        else:
            return
        yield {}
        return

    # Show Memory
    if query_name == "ShowMem" and interpreter.inspect_added:
        interpreter.message(
            f"{interpreter.memory}\n{interpreter.references}\n")
        yield "Print"
        yield {}
        return

    # Listing - list all cases of predicate
    if query_name == "Listing" and interpreter.inspect_added:
        p_name = query_pat

        if p_name == "ALL":
            for predicate in interpreter.predicates.values():
                interpreter.message(predicate.__str__())
            yield 'Print'
            yield {}
            return

        if p_name not in interpreter.predicates:
            return
        else:
            predicate_match = interpreter.predicates[p_name]
            interpreter.message(predicate_match.__str__())
            yield "Print"
            yield {}
            return

        return

    if interpreter.dynamic_added and query_name in {"AssertF", "AssertFE", "AssertN", "AssertNE", "AssertC", "AssertCE", "DeleteF",
                                                    "DeleteN", "DeleteC", "Create", "SwitchRecursive", "SwitchRandom", 'Clear', 'Delete'} \
            :

        parts = splitWithoutParen(query_pat)
        if len(parts) != 1:
            return

        if query_name == "Create":
            if re.fullmatch(r'[a-zA-Z_0-9\-\.]+',
                            query_pat) and query_pat not in Lexer.reserved:
                new_pred = Predicate(interpreter, query_pat, False, False)
                interpreter.predicates[new_pred.name] = new_pred
                yield {}
            return
        if query_name == "SwitchRecursive":
            if query_pat in interpreter.predicates:
                pred = interpreter.predicates[query_pat]
                pred.recursive = not pred.recursive
                yield {}
            return
        if query_name == "SwitchRandom":
            if query_pat in interpreter.predicates:
                pred = interpreter.predicates[query_pat]
                pred.random = not pred.random
                yield {}
            return
        if query_name == 'Delete':
            if query_pat in interpreter.predicates:
                del interpreter.predicates[query_pat]
                yield {}
            return

        predicate_changed, _, body = query_pat.partition("(")
        body = "(" + body
        body = remove_whitespace(body)

        if predicate_changed not in interpreter.predicates:
            return

        predicate_changed = interpreter.predicates[predicate_changed]

        if query_name == "AssertFE":
            basic = processParen(body)
            if basic:
                predicate_changed.addBasic(basic)
                yield {}
                return
            else:
                return
        if query_name == "AssertF":
            basic = processParen(body)
            if basic:
                predicate_changed.addBasic(basic, insert=True)
                yield {}
                return
            else:
                return

        if query_name == "AssertNE":
            basic = processParen(body)
            if basic:
                predicate_changed.addNot(basic)
                yield {}
                return
            else:
                return
        if query_name == "AssertN":
            basic = processParen(body)
            if basic:
                predicate_changed.addNot(basic, insert=True)
                yield {}
                return
            else:
                return

        if query_name == "AssertCE":
            to_match, _, then = body.partition(">")
            to_match, then = processParen(to_match), processParen(then)
            if not to_match or not then:
                return
            predicate_changed.addCase(to_match, then)
            yield {}
            return
        if query_name == "AssertC":
            to_match, _, then = body.partition(">")
            to_match, then = processParen(to_match), processParen(then)
            if not to_match or not then:
                return
            predicate_changed.addCase(to_match, then, insert=True)
            yield {}
            return

        if query_name == "DeleteF":
            body = processParen(body)
            if body in predicate_changed.basic:
                predicate_changed.basic.remove(body)
                yield {}
                return
            else:
                return
        if query_name == "DeleteN":
            body = processParen(body)
            if body in predicate_changed.nope:
                predicate_changed.nope.remove(body)
                yield {}
                return
            else:
                return
        if query_name == 'DeleteC':
            to_match, _, then = body.partition(">")
            to_match, then = processParen(to_match), processParen(then)
            if to_match in predicate_changed.cases:
                index = predicate_changed.cases.index(to_match)
                if then != predicate_changed.then[index]:
                    return
                predicate_changed.cases.remove(to_match)
                predicate_changed.then.remove(then)
                predicate_changed.count -= 1
                yield {}
                return
            else:
                return

        if query_name == 'Clear':
            predicate_changed.cases = []
            predicate_changed.then = []
            predicate_changed.count = 0
            predicate_changed.basic = []
            predicate_changed.nope = []
            yield {}
            return

        return

    found[0] = False