Beispiel #1
0
    def step(self):
        while self.intentions and not self.intentions[0]:
            self.intentions.popleft()

        for intention_stack in self.intentions:
            intention = intention_stack[-1]

            # Wait until.
            if intention.wait_until:
                if intention.wait_until < self.env.time():
                    intention.wait_until = None
                else:
                    continue

            break
        else:
            return False

        instr = intention.instr

        if not instr:
            intention_stack.pop()
            if not intention_stack:
                self.intentions.remove(intention_stack)
            elif intention.calling_term:
                frozen = intention.head_term.freeze(intention.scope, {})
                calling_intention = intention_stack[-1]
                if not pyson.unify(intention.calling_term, frozen,
                                   calling_intention.scope,
                                   calling_intention.stack):
                    raise RuntimeError("back unification failed")
            return True

        try:
            if instr.f(self, intention):
                intention.instr = instr.success
            else:
                intention.instr = instr.failure
                if not intention.instr:
                    raise PysonError("plan failure")
        except PysonError as err:
            log = pyson.Log(LOGGER)
            raise log.error("%s @ %s",
                            err,
                            instr.f,
                            loc=instr.loc,
                            extra_locs=instr.extra_locs)
        except:
            log = pyson.Log(LOGGER)
            raise log.exception("python exception @ %s",
                                instr.f,
                                loc=instr.loc,
                                extra_locs=instr.extra_locs)

        return True
Beispiel #2
0
def repl(hook):
    lineno = 0
    tokens = []

    while True:
        try:
            log = pyson.Log(pyson.get_logger(__name__), 3)

            if not tokens:
                line = pyson.util.prompt("pyson.parser >>> ")
            else:
                line = pyson.util.prompt("pyson.parser ... ")

            lineno += 1

            tokens.extend(pyson.lexer.tokenize(pyson.StringSource("<stdin>", line), log, lineno))

            while tokens:
                token_stream = iter(tokens)
                try:
                    agent = parse_agent("<stdin>", token_stream, log, frozenset())
                except StopIteration:
                    log.throw()
                    break
                else:
                    log.throw()
                    hook(agent)
                    tokens = list(token_stream)
        except pyson.AggregatedError as error:
            print(str(error), file=sys.stderr)
            tokens = []
        except KeyboardInterrupt:
            print()
            sys.exit(0)
Beispiel #3
0
    def test_unexpected_eof(self):
        src = pyson.StringSource("<test>", "a")
        log = pyson.Log(pyson.get_logger(__name__), 3)
        tokens = pyson.lexer.TokenStream(src, log)

        with self.assertRaises(pyson.AggregatedError):
            pyson.parser.parse(tokens, log, frozenset())
Beispiel #4
0
def main(source, lineno=1):
    log = pyson.Log(pyson.get_logger(__name__), 3)

    for tok in tokenize(source, log, lineno):
        log.info("%s", tok.lexeme, loc=tok.loc)

    log.throw()
Beispiel #5
0
    def step(self):
        while self.intentions and not self.intentions[0]:
            self.intentions.popleft()

        for intention_stack in self.intentions:
            intention = intention_stack[-1]

            # Suspended / waiting.
            if intention.waiter is not None:
                if intention.waiter.poll(self.env):
                    intention.waiter = None
                else:
                    continue

            break
        else:
            return False

        instr = intention.instr

        if not instr:
            intention_stack.pop()
            if not intention_stack:
                self.intentions.remove(intention_stack)
            elif intention.calling_term:
                frozen = intention.head_term.freeze(intention.scope, {})
                calling_intention = intention_stack[-1]
                if not pyson.unify(intention.calling_term, frozen, calling_intention.scope, calling_intention.stack):
                    raise RuntimeError("back unification failed")
            return True

        try:
            if instr.f(self, intention):
                intention.instr = instr.success
            else:
                intention.instr = instr.failure
                if not intention.instr:
                    raise PysonError("plan failure")
        except PysonError as err:
            log = pyson.Log(LOGGER)
            raise log.error("%s", err, loc=instr.loc, extra_locs=instr.extra_locs)
        except Exception as err:
            log = pyson.Log(LOGGER)
            raise log.exception("agent %r raised python exception: %r", self.name, err,
                                loc=instr.loc, extra_locs=instr.extra_locs)

        return True
Beispiel #6
0
    def test_unify_return_value(self):
        src = pyson.StringSource("<test>", "+!p <- (X = 2) + 1 > 0.")
        log = pyson.Log(pyson.get_logger(__name__), 3)
        tokens = pyson.lexer.TokenStream(src, log)

        with self.assertRaises(pyson.AggregatedError):
            pyson.parser.parse(tokens, log, frozenset())
            log.throw()
Beispiel #7
0
    def test_rule_head_not_unifiable(self):
        src = pyson.StringSource("<test>", "rule(X + 1) :- true.")
        log = pyson.Log(pyson.get_logger(__name__), 3)
        tokens = pyson.lexer.TokenStream(src, log)
        pyson.parser.parse(tokens, log, frozenset())

        with self.assertRaises(pyson.AggregatedError):
            log.throw()
Beispiel #8
0
    def test_formula_type(self):
        src = pyson.StringSource("<test>", "+!plan <- ?true.")
        log = pyson.Log(pyson.get_logger(__name__), 3)
        tokens = pyson.lexer.TokenStream(src, log)
        pyson.parser.parse(tokens, log, frozenset())

        with self.assertRaises(pyson.AggregatedError):
            log.throw()
Beispiel #9
0
    def _build_agent(self, source, actions, agent_cls=Agent, name=None):
        # Parse source.
        log = pyson.Log(LOGGER, 3)
        tokens = pyson.lexer.TokenStream(source, log)
        ast_agent = pyson.parser.parse(tokens, log, frozenset(source.name))
        log.throw()

        return self.build_agent_from_ast(source, ast_agent, actions, agent_cls, name)
Beispiel #10
0
def main(source, hook):
    log = pyson.Log(pyson.get_logger(__name__), 3)

    tokens = pyson.lexer.TokenStream(source, log, 1)
    agent = parse(source.name, tokens, log)

    log.throw()

    hook(agent)
Beispiel #11
0
def repl(agent, env, actions):
    lineno = 0
    tokens = []

    env = Environment()
    variables = {}
    intention = Intention()

    while True:
        try:
            log = pyson.Log(LOGGER, 3)

            try:
                if not tokens:
                    line = pyson.util.prompt("%s >>> " % agent.name)
                else:
                    line = pyson.util.prompt("%s ... " % agent.name)
            except KeyboardInterrupt:
                print()
                sys.exit(0)

            lineno += 1

            tokens.extend(
                pyson.lexer.tokenize(pyson.StringSource("<stdin>", line), log,
                                     lineno))

            while tokens:
                token_stream = iter(tokens)
                try:
                    tok = next(token_stream)
                    tok, body = pyson.parser.parse_plan_body(
                        tok, token_stream, log)
                except StopIteration:
                    log.throw()
                    break
                else:
                    log.throw()
                    tokens = list(token_stream)

                    intention.instr = Instruction(noop)
                    body.accept(
                        BuildInstructionsVisitor(variables, actions,
                                                 intention.instr, log))
                    log.throw()
                    agent.intentions.append(collections.deque([intention]))
                    env.run_agent(agent)
                    dump_variables(variables, intention.scope)
        except pyson.AggregatedError as error:
            print(str(error), file=sys.stderr)
            tokens = []
        except pyson.PysonError as error:
            LOGGER.error("%s", error)
            tokens = []
Beispiel #12
0
    def build_agent_from_ast(self, source, ast_agent, actions, agent_cls=Agent, name=None):
        # This function is also called by the optimizer.

        log = pyson.Log(LOGGER, 3)
        agent = agent_cls(self, self._make_name(name or source.name))

        # Add rules to agent prototype.
        for ast_rule in ast_agent.rules:
            variables = {}
            head = ast_rule.head.accept(BuildTermVisitor(variables))
            consequence = ast_rule.consequence.accept(BuildQueryVisitor(variables, actions, log))
            agent.add_rule(Rule(head, consequence))

        # Add plans to agent prototype.
        for ast_plan in ast_agent.plans:
            variables = {}

            head = ast_plan.head.accept(BuildTermVisitor(variables))

            if ast_plan.context:
                context = ast_plan.context.accept(BuildQueryVisitor(variables, actions, log))
            else:
                context = TrueQuery()

            body = Instruction(noop)
            body.f = noop
            if ast_plan.body:
                ast_plan.body.accept(BuildInstructionsVisitor(variables, actions, body, log))

            plan = Plan(ast_plan.trigger, ast_plan.goal_type, head, context, body)
            agent.add_plan(plan)

        # Add beliefs to agent prototype.
        for ast_belief in ast_agent.beliefs:
            belief = ast_belief.accept(BuildTermVisitor({}))
            agent.call(pyson.Trigger.addition, pyson.GoalType.belief,
                       belief, Intention(), delayed=True)

        # Call initial goals on agent prototype.
        for ast_goal in ast_agent.goals:
            term = ast_goal.atom.accept(BuildTermVisitor({}))
            agent.call(pyson.Trigger.addition, pyson.GoalType.achievement,
                       term, Intention(), delayed=True)

        # Report errors.
        log.throw()

        self.agents[agent.name] = agent
        return ast_agent, agent
Beispiel #13
0
def _wait(agent, term, intention):
    # Handle optional arguments.
    args = [pyson.grounded(arg, intention.scope) for arg in term.args]
    if len(args) == 2:
        event, millis = args
    else:
        if pyson.is_number(args[0]):
            millis = args[0]
            event = None
        else:
            millis = None
            event = args[0]

    # Type checks.
    if not (millis is None or pyson.is_number(millis)):
        raise pyson.PysonError("expected timeout for .wait to be numeric")
    if not (event is None or pyson.is_string(event)):
        raise pyson.PysonError("expected event for .wait to be a string")

    # Event.
    if event is not None:
        # Parse event.
        if not event.endswith("."):
            event += "."
        log = pyson.Log(LOGGER, 1)
        tokens = pyson.lexer.TokenStream(pyson.StringSource("<.wait>", event),
                                         log)
        tok, ast_event = pyson.parser.parse_event(tokens.next(), tokens, log)
        if tok.lexeme != ".":
            raise log.error(
                "expected no further tokens after event for .wait, got: '%s'",
                tok.lexeme,
                loc=tok.loc)

        # Build term.
        event = ast_event.accept(pyson.runtime.BuildEventVisitor(log))

    # Timeout.
    if millis is None:
        until = None
    else:
        until = agent.env.time() + millis / 1000

    # Create waiter.
    intention.waiter = pyson.runtime.Waiter(event=event, until=until)
    yield