예제 #1
0
    def addCase(self, to_match, then):
        """
        Add a translation case to package.

        :param to_match: str, the pattern needs matching
        :param then: str, what to search if the match was successful
        :return: None
        """
        to_match = to_match.strip()
        if len(to_match) == 0:
            self.cases.append('')
            self.then.append(then)
            self.count += 1
            return
        to_match = processParen(to_match)
        if not to_match:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in package {self.name}")
            return
        then = processParen(then)
        if not then:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in package {self.name}")
            return
        if len(to_match) == 0:
            self.cases.append('')
            self.then.append(then)
            self.count += 1
            return
        self.cases.append(to_match)
        self.then.append(then)
        self.count += 1
예제 #2
0
    def addCase(self, to_match, then, insert=False):
        """
        Add a translation case to predicate.

        :param to_match: str, the pattern needs matching
        :param then: str, what to search if the match was successful
        :param insert: Boolean - add it at the end
        :return: None
        """
        to_match = to_match.strip()
        if len(to_match) == 0:

            if insert:
                self.cases = [to_match] + self.cases
                self.then = [then] + self.then
                self.count += 1
                return

            self.cases.append('')
            self.then.append(then)
            self.count += 1
            return

        to_match = processParen(to_match)
        if not to_match:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in predicate {self.name}")
            return

        then = processParen(then)
        if not then:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in predicate {self.name}")
            return

        if len(to_match) == 0:
            if insert:
                self.cases = [to_match] + self.cases
                self.then = [then] + self.then
                self.count += 1
                return

            self.cases.append('')
            self.then.append(then)
            self.count += 1
            return

        if insert:
            self.cases = [to_match] + self.cases
            self.then = [then] + self.then
            self.count += 1
            return

        self.cases.append(to_match)
        self.then.append(then)
        self.count += 1
예제 #3
0
    def addNot(self, to_match, insert=False):
        """
        Add a terminal case - stops looking if matched. not that useful but sometimes important.

        :param to_match: str, pattrn to match
        :param insert: boolean, add in the beginning
        :return:
        """
        to_match = to_match.strip()
        if len(to_match) == 0:

            if insert:
                self.nope = [''] + self.nope
                return

            self.nope.append('')
            return
        to_match = processParen(to_match)
        if not to_match:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in predicate {self.name}")
        if len(to_match) == 0:
            if insert:
                self.nope = [''] + self.nope
                return
            self.nope.append('')
            return

        if insert:
            self.nope = [to_match] + self.nope
            return

        self.nope.append(to_match)
예제 #4
0
    def addBasic(self, to_match, insert=False):
        """
        Adding a Fact to predicate.

        :param to_match: str, pattern to match
        :param insert: boolean, denoting whether to add in the beginning
        :return: None
        """

        to_match = to_match.strip()
        if len(to_match) == 0:

            if insert:
                self.basic = [''] + self.basic
                return

            self.basic.append('')
            return
        to_match = processParen(to_match)
        if not to_match:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in predicate {self.name}")
        if len(to_match) == 0:
            if insert:
                self.basic = [''] + self.basic
                return

            self.basic.append('')
            return

        if insert:
            self.basic = [to_match] + self.basic
            return

        self.basic.append(to_match)
예제 #5
0
파일: Domain.py 프로젝트: YuvalLot/pyLocal
    def insert_range(self, variable, range_search, line):
        """
        Inserts a variable range to the domain predicate.

        :param variable: str
        :param range_search: str
        :param line: int
        :return: bool
        """
        if variable == "?all":
            for variable in self.variables:
                if variable in self.range_searches:
                    continue
                self.range_searches[variable] = smart_replace(
                    range_search, {"?all": variable})
            return True
        if variable not in self.variables:
            self.interpreter.raiseError(
                f"Error: Variable {variable} not part of Domain {self.name}, in line {line}"
            )
            return False
        range_search = processParen(range_search)
        if not range_search:
            self.interpreter.raiseError(
                f"Error: Illegal range search in Domain {self.name} of variable {variable}, in line {line}"
            )
            return False
        if variable in self.range_searches:
            self.interpreter.raiseError(
                f"Error: In Domain {self.name}, variable {variable} already has a defined range, in line {line}"
            )
            return False
        self.range_searches[variable] = range_search
        return True
예제 #6
0
파일: Query.py 프로젝트: YuvalLot/pyLocal
    def create(cls, interpreter, query):
        """
        Main way of creating queries. Used class method and not __init__ because it calls itself recursively. While it is possible to use __init__ and call
        input recursively, this way is more aesthetically pleasing (in my opinion), because it allows the __init__ to behave as a private method behind the
        scenes.

        :param interpreter: Interpreter
        :param query: str
        :return: Query (None if illegal)
        """
        X = Query(interpreter)
        query = processParen(query)
        if not query:
            interpreter.raiseError("Error: Incomplete Parentheses")
            return
        X.input(query)
        return X
예제 #7
0
    def addNot(self, to_match):
        """
        Adding a terminal case to package.

        :param to_match: str, pattern to match
        :return: None
        """
        to_match = to_match.strip()
        if len(to_match) == 0:
            self.nope.append('')
            return
        to_match = processParen(to_match)
        if not to_match:
            self.interpreter.raiseError(
                f"Error: Incomplete parentheses in package {self.name}")
        if len(to_match) == 0:
            self.nope.append('')
            return
        self.nope.append(to_match)
예제 #8
0
파일: Domain.py 프로젝트: YuvalLot/pyLocal
    def insert_elimination(self, elim, when, line):
        """
        Inserts a constraint.

        :param elim: str
        :param when: str
        :param line: int
        :return: bool
        """
        elim = processParen(elim)
        if not elim:
            self.interpreter.raiseError(
                f"Error: In Domain {self.name}, elimination {elim} illegal, in line {line}"
            )
            return False
        self.eliminations[elim] = {
            var
            for var in self.variables if var_in_query(elim, var)
        }
        self.when[elim] = when
        return True
예제 #9
0
파일: Domain.py 프로젝트: YuvalLot/pyLocal
    def insert_constraint(self, const, when, line):
        """
        Inserts a constraint.

        :param const: str
        :param when: str
        :param line: int
        :return: bool
        """
        const = processParen(const)
        if not const:
            self.interpreter.raiseError(
                f"Error: In Domain {self.name}, constraint {const} illegal, in line {line}"
            )
            return False
        self.constraints[const] = {
            var
            for var in self.variables if var_in_query(const, var)
        }
        self.when[const] = when
        return True
예제 #10
0
파일: Query.py 프로젝트: YuvalLot/pyLocal
    def input(self, query: str):
        """
        Main function that builds queries.
        Searches for logical gates (&, |, $, ~).
        Searches for package calls (G{...}(...))

        :param query: str
        :return: None
        """

        # looking for cuts
        searchForCuts = splitWithoutParen(query, "\\")
        if len(searchForCuts) != 1:
            self.gateA = Query.create(self.interpreter, searchForCuts[0])
            self.gateB = Query.create(self.interpreter,
                                      "\\".join(searchForCuts[1:]))
            self.type = '\\'
            return

        # looking for ands
        searchForAnd = splitWithoutParen(query, "&")
        if len(searchForAnd) != 1:
            self.gateA = Query.create(self.interpreter, searchForAnd[0])
            self.gateB = Query.create(self.interpreter,
                                      "&".join(searchForAnd[1:]))
            self.type = '&'
            return

        # looking for ors
        searchForOr = splitWithoutParen(query, "|")
        if len(searchForOr) != 1:
            self.gateA = Query.create(self.interpreter, searchForOr[0])
            self.gateB = Query.create(self.interpreter,
                                      "|".join(searchForOr[1:]))
            self.type = '|'
            return

        # looking for Xor
        searchForXor = splitWithoutParen(query, "$")
        if len(searchForXor) != 1:
            # print(searchForXor)
            self.gateA = Query.create(self.interpreter, searchForXor[0])
            self.gateB = Query.create(self.interpreter,
                                      "$".join(searchForXor[1:]))
            self.type = '$'
            return

        # looking for not
        searchForFilter = splitWithoutParen(query, "~")
        if len(searchForFilter) != 1:
            if len(searchForFilter) != 2 or searchForFilter[0] != '':
                self.interpreter.raiseError("Error: ~ must have 1 side!")
                return
            self.gateA = Query.create(self.interpreter, searchForFilter[1])
            self.type = "~"
            return

        # conditional statements
        if query[:4] == "cond":
            processed = processParen(query[5:-1])
            if not processed:
                self.interpreter.raiseError("Error: illegal cond statement")
                return
            self.type = "c"

            parts = splitWithoutParen(processed)
            for part in parts:
                trie = splitWithoutParen(part, ">")
                if len(trie) != 2:
                    self.interpreter.raiseError(f"Error: {part} illegal cond")
                    return
                cond, exe = trie
                cond = Query.create(self.interpreter, cond)
                exe = Query.create(self.interpreter, exe)
                self.cond.append((cond, exe))
            return

        # Changing a reference
        searchForReferenceDefinition = outString(query, ":=")
        if searchForReferenceDefinition:
            parts = query.split(":=")
            if len(parts) != 2:
                self.interpreter.raiseError(
                    f"Error: Illegal pattern for changing a reference, '{query}'"
                )
                return
            self.gateA, self.gateB = parts
            self.type = ":="
            return

        # Dereference
        if outString(query, "!") and len(splitWithoutParen(query, "!")) == 1:
            self.gateA = query
            self.type = "!"
            return

        # Folding
        if outString(query, "%") and len(splitWithoutParen(
                query, "%")) == 1 and not outString(query, ":"):
            self.gateA = query
            self.type = "%"
            return

        # case that package
        searchForPackage = outString(query, "}(")
        if searchForPackage:
            self.gateA = query
            self.type = 'pi'
            return

        # case that it is a simple clause
        self.gateA = query
        self.type = 'r'
        return
예제 #11
0
    def match(self, pattern):
        """
        Given a pattern, look through all cases and determine if there exists a match.
        if match is basic, return basic solution.
         if match is terminal, return False.
        if match is translational, return the new search that has to be done, and a way (the backward dictionary) to translate from solutions of the new
        search back to the parameters given in the pattern. This is the fundamental idea of back chaining, used to solved queries.

        :param pattern: str
        :return: Generator of (search, forward, backward), False
        """

        pattern = processParen(pattern)
        if pattern is False or pattern is None:
            self.interpreter.raiseError("Error: Incomplete Parentheses")
            return

        # Looking for false facts
        for nope in self.nope:
            t = MatchDictionary.match(self.interpreter, pattern, nope)
            if t and not t[
                    2]:  # only in the case the patterns matched AND no wiggle room
                return

        if self.random:
            # print("RANDOM")
            while True:
                if len(self.basic) == 0 and self.count == 0:
                    return
                ch = []
                if len(self.basic) != 0:
                    ch.append('basic')
                if self.count != 0:
                    ch.append('translation')
                indices_name = random.choice(ch)
                if indices_name == 'basic':
                    basic = random.choice(self.basic)
                    t = MatchDictionary.match(self.interpreter, pattern, basic)
                    if t:
                        # print(f"Match basic: {t[0]},{t[1]}")
                        yield 1, t[1], t[0]
                        if self.recursive:
                            return
                if indices_name == 'translation':
                    i = random.randint(0, self.count - 1)
                    t = MatchDictionary.match(self.interpreter, pattern,
                                              self.cases[i])
                    if t:
                        # print(f"Matched with {self.cases[i]}: {t[0]},{t[1]}")
                        then = self.then[i]
                        then = smart_replace(then, t[0])
                        yield then, t[1], t[0]
                        if self.recursive:
                            return

        for basic in self.basic:
            t = MatchDictionary.match(self.interpreter, pattern, basic)
            if t:
                yield 1, t[1], t[0]
                if self.recursive:
                    return

        for i in range(self.count):
            t = MatchDictionary.match(self.interpreter, pattern, self.cases[i])
            if t:
                then = self.then[i]
                then = smart_replace(then, t[0])
                yield then, t[1], t[0]
                if self.recursive:
                    return
예제 #12
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
예제 #13
0
    def o_single_push(self, compA, compB):

        compA = processParen(compA)
        compB = processParen(compB)

        if compB == "_":
            compB = f"?@{MatchDictionary.index}"
            MatchDictionary.index += 1
        if compA == "_":
            compA = f"?@{MatchDictionary.index}"
            MatchDictionary.index += 1

        if not compA or not compB:
            return

        if any(map(lambda infx: infx in compA, self.interpreter.infixes)):
            compA = lookup(compA, self.interpreter.infixes)
        if any(map(lambda infx: infx in compB, self.interpreter.infixes)):
            compB = lookup(compB, self.interpreter.infixes)

        if not compA or not compB:
            return False

        typeA = match_type(compA)
        typeB = match_type(compB)

        # print(compA, typeA, compB, typeB)

        if typeA in ['list', 'head']:
            compA = processHead(compA)
            if not compA:
                return False
            typeA = match_type(compA)
        if typeB in ['list', 'head']:
            compB = processHead(compB)
            if not compB:
                return False
            typeB = match_type(compB)

        if typeA == 'constant' and typeB == 'constant':
            return compA == compB

        # var with var & var with constant
        if typeA == 'var' and typeB == 'var':
            return self.o_var_with_var(compA, compB)
        if typeA == 'var' and typeB == 'constant':
            return self.o_var_with_const(compA, compB)
        if typeA == 'constant' and typeB == 'var':
            return self.o_const_with_var(compA, compB)

        # Lists with vars
        if typeA == 'list' and typeB == 'var':
            return self.o_list_with_var(compA, compB)
        if typeA == 'var' and typeB == 'list':
            return self.o_var_with_list(compA, compB)

        # Appended lists with vars
        if typeA == 'head' and typeB == 'var':
            return self.o_head_with_var(compA, compB)
        if typeA == 'var' and typeB == 'head':
            return self.o_var_with_head(compA, compB)

        # lists with lists, lists with appended lists.
        if typeA == 'list' and typeB == 'list':
            return self.o_list_with_list(compA, compB)
        if typeA == 'head' and typeB == 'head':
            return self.o_head_with_head(compA, compB)
        if typeA == 'list' and typeB == 'head':
            return self.o_list_with_head(compA, compB)
        if typeA == 'head' and typeB == 'list':
            return self.o_head_with_list(compA, compB)

        # titles match
        if typeA == 'title' and typeB == 'title':
            return self.o_title_with_title(compA, compB)
        if typeA == 'var' and typeB == 'title':
            return self.o_var_with_title(compA, compB)
        if typeA == 'title' and typeB == 'var':
            return self.o_title_with_var(compA, compB)

        # Packages match
        if typeA == 'pack' and typeB == 'pack':
            return self.o_pack_with_pack(compA, compB)
        if typeA == 'pack' and typeB == 'var':
            return self.o_pack_with_var(compA, compB)
        if typeA == 'var' and typeB == 'pack':
            return self.o_var_with_pack(compA, compB)

        # Pair Match
        if typeA == "pair" and typeB == "pair":
            return self.o_pair_with_pair(compA, compB)
        if typeA == "pair" and typeB == "var":
            return self.o_pair_with_var(compA, compB)
        if typeA == "var" and typeB == "pair":
            return self.o_var_with_pair(compA, compB)

        return False