Esempio n. 1
0
 def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder, eval_operands=True) -> Expression:
     if eval_operands:
         operands = evaluate_all(
             operands, frame, gui_holder.expression.children[1:])
     gui_holder.expression.set_entries([])
     gui_holder.apply()
     return self.execute_evaluated(operands, frame)
 def execute(self,
             operands: List[Expression],
             frame: Frame,
             gui_holder: Holder,
             eval_operands=True):
     verify_exact_callable_length(self, 1, len(operands))
     operand = operands[0]
     if eval_operands:
         operand = evaluate_all(operands, frame,
                                gui_holder.expression.children[1:])[0]
     if not isinstance(operand, Promise):
         raise OperandDeduceError(
             f"Force expected a Promise, received {operand}")
     if operand.forced:
         return operand.expr
     if logger.fragile:
         raise IrreversibleOperationError()
     gui_holder.expression.set_entries([
         VisualExpression(operand.expr, gui_holder.expression.display_value)
     ])
     gui_holder.apply()
     evaluated = evaluate(operand.expr, operand.frame,
                          gui_holder.expression.children[0])
     if not logger.dotted and not isinstance(evaluated, (Pair, NilType)):
         raise TypeMismatchError(
             f"Unable to force a Promise evaluating to {operand.expr}, expected another Pair or Nil"
         )
     operand.expr = evaluated
     operand.force()
     return operand.expr
Esempio n. 3
0
 def execute(self,
             operands: List[Expression],
             frame: Frame,
             gui_holder: Holder,
             eval_operands=True):
     verify_exact_callable_length(self, 1, len(operands))
     if eval_operands:
         operands = evaluate_all(operands, frame,
                                 gui_holder.expression.children[1:])
     if (not isinstance(operands[0], Symbol)):
         raise OperandDeduceError(''.join([
             'Load expected a Symbol, received ', '{}'.format(operands[0]),
             '.'
         ]))
     if logger.fragile:
         raise IrreversibleOperationError()
     try:
         with open(''.join(['{}'.format(operands[0].value),
                            '.scm'])) as file:
             code = (('(begin' + '\n'.join(file.readlines())) + '\n)')
             buffer = TokenBuffer([code])
             expr = get_expression(buffer)
             gui_holder.expression.set_entries([
                 VisualExpression(expr, gui_holder.expression.display_value)
             ])
             gui_holder.apply()
             return evaluate(expr, frame, gui_holder.expression.children[0],
                             True)
     except OSError as e:
         raise LoadError(e)
 def execute(self,
             operands: List[Expression],
             frame: Frame,
             gui_holder: Holder,
             eval_operands=True):
     verify_exact_callable_length(self, 1, len(operands))
     if eval_operands:
         operands = evaluate_all(operands, frame,
                                 gui_holder.expression.children[1:])
     if not isinstance(operands[0], Symbol):
         raise OperandDeduceError(
             f"Load expected a Symbol, received {operands[0]}.")
     if logger.fragile:
         raise IrreversibleOperationError()
     try:
         with open(f"{operands[0].value}.scm") as file:
             code = "(begin-noexcept" + "\n".join(file.readlines()) + "\n)"
             buffer = TokenBuffer([code])
             expr = get_expression(buffer)
             gui_holder.expression.set_entries([
                 VisualExpression(expr, gui_holder.expression.display_value)
             ])
             gui_holder.apply()
             return evaluate(expr, frame, gui_holder.expression.children[0],
                             True)
     except OSError as e:
         raise LoadError(e)
 def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder, eval_operands=True):
     verify_exact_callable_length(self, 1, len(operands))
     if eval_operands:
         operand = evaluate(operands[0], frame, gui_holder.expression.children[1])
     else:
         operand = operands[0]
     gui_holder.expression.set_entries([VisualExpression(operand, gui_holder.expression.display_value)])
     gui_holder.apply()
     return evaluate(operand, frame, gui_holder.expression.children[0], True)
    def quasiquote_evaluate(cls, expr: Expression, frame: Frame, gui_holder: Holder, splicing=False):
        is_well_formed = False

        if isinstance(expr, Pair):
            try:
                lst = pair_to_list(expr)
            except OperandDeduceError:
                pass
            else:
                is_well_formed = not any(map(
                    lambda x: isinstance(x, Symbol) and x.value in ["unquote", "quasiquote", "unquote-splicing"], lst))

        visual_expression = gui_holder.expression
        if not is_well_formed:
            visual_expression.children[2:] = []

        if isinstance(expr, Pair):
            if isinstance(expr.first, Symbol) and expr.first.value in ("unquote", "unquote-splicing"):
                if expr.first.value == "unquote-splicing" and not splicing:
                    raise OperandDeduceError("Unquote-splicing must be in list template.")
                gui_holder.evaluate()
                verify_exact_callable_length(expr.first, 1, len(pair_to_list(expr)) - 1)
                out = evaluate(expr.rest.first, frame, visual_expression.children[1])
                visual_expression.value = out
                gui_holder.complete()
                return out
            elif isinstance(expr.first, Symbol) and expr.first.value == "quasiquote":
                visual_expression.value = expr
                gui_holder.complete()
                return expr
            else:
                if is_well_formed:
                    out = []
                    for sub_expr, holder in zip(pair_to_list(expr), visual_expression.children):
                        splicing = isinstance(sub_expr, Pair) and isinstance(sub_expr.first, Symbol) \
                                and sub_expr.first.value == "unquote-splicing"
                        evaluated = Quasiquote.quasiquote_evaluate(sub_expr, frame, holder, splicing)
                        if splicing:
                            if not isinstance(evaluated, (Pair, NilType)):
                                raise TypeMismatchError(f"Can only splice lists, not {evaluated}.")
                            out.extend(pair_to_list(evaluated))
                        else:
                            out.append(evaluated)
                    out = make_list(out)
                else:
                    if not logger.dotted:
                        raise OperandDeduceError(f"{expr} is an ill-formed quasiquotation.")
                    out = Pair(Quasiquote.quasiquote_evaluate(expr.first, frame, visual_expression.children[0]),
                               Quasiquote.quasiquote_evaluate(expr.rest, frame, visual_expression.children[1]))
                visual_expression.value = out
                gui_holder.complete()
                return out
        else:
            visual_expression.value = expr
            gui_holder.complete()
            return expr
 def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder, eval_operands=True):
     verify_exact_callable_length(self, 2, len(operands))
     if eval_operands:
         operands = evaluate_all(operands, frame, gui_holder.expression.children[1:])
     func, args = operands
     if not isinstance(func, Applicable):
         raise OperandDeduceError(f"Unable to apply {func}.")
     gui_holder.expression.set_entries([VisualExpression(Pair(func, args), gui_holder.expression.display_value)])
     gui_holder.expression.children[0].expression.children = []
     gui_holder.apply()
     args = pair_to_list(args)
     return func.execute(args, frame, gui_holder.expression.children[0], False)
    def execute(self,
                operands: List[Expression],
                frame: Frame,
                gui_holder: Holder,
                eval_operands=True):
        new_frame = Frame(self.name,
                          self.frame if self.lexically_scoped else frame)

        if eval_operands and self.evaluates_operands:
            operands = evaluate_all(operands, frame,
                                    gui_holder.expression.children[1:])

        if self.var_param:
            verify_min_callable_length(self, len(self.params), len(operands))
        else:
            verify_exact_callable_length(self, len(self.params), len(operands))

        if len(self.body) > 1:
            body = [Pair(Symbol("begin"), make_list(self.body))]
        else:
            body = self.body

        for param, value in zip(self.params, operands):
            new_frame.assign(param, value)

        if self.var_param:
            new_frame.assign(self.var_param,
                             make_list(operands[len(self.params):]))

        out = None
        gui_holder.expression.set_entries([
            VisualExpression(expr, gui_holder.expression.display_value)
            for expr in body
        ])

        gui_holder.apply()

        for i, expression in enumerate(body):
            out = evaluate(expression,
                           new_frame,
                           gui_holder.expression.children[i],
                           self.evaluates_operands and i == len(body) - 1,
                           log_stack=len(self.body) == 1)

        new_frame.assign(return_symbol, out)

        if not self.evaluates_operands:
            gui_holder.expression.set_entries(
                [VisualExpression(out, gui_holder.expression.display_value)])
            out = evaluate(out, frame, gui_holder.expression.children[i], True)

        return out
 def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder, eval_operands=True):
     verify_exact_callable_length(self, 1, len(operands))
     if eval_operands:
         operands = evaluate_all(operands, frame, gui_holder.expression.children[1:])
     if not isinstance(operands[0], String):
         raise OperandDeduceError(f"Load expected a String, received {operands[0]}.")
     if logger.fragile:
         raise IrreversibleOperationError()
     from os import listdir
     from os.path import join
     directory = operands[0].value
     try:
         targets = sorted(listdir(directory))
         targets = [join(directory, target) for target in targets if target.endswith(".scm")]
         exprs = [make_list([Symbol("load"), make_list([Symbol("quote"), Symbol(x[:-4])])]) for x in targets]
         equiv = make_list([Symbol("begin-noexcept")] + exprs)
         gui_holder.expression.set_entries([equiv])
         gui_holder.apply()
         return evaluate(equiv, frame, gui_holder.expression.children[0], True)
     except Exception as e:
         raise SchemeError(e)
def evaluate(expr: Expression, frame: Frame, gui_holder: log.Holder,
             tail_context: bool = False, *, log_stack: bool=True) -> Union[Expression, Thunk]:
    depth = 0
    thunks = []
    holders = []

    while True:
        if depth > RECURSION_LIMIT:
            raise OutOfMemoryError("Debugger ran out of memory due to excessively deep recursion.")

        visual_expression = gui_holder.expression

        if log_stack:
            log.logger.eval_stack.append(f"{repr(expr)} [frame = {frame.id}]")
            depth += 1

        holders.append(gui_holder)

        if isinstance(expr, Number) \
                or isinstance(expr, Callable) \
                or isinstance(expr, Boolean) \
                or isinstance(expr, String) \
                or isinstance(expr, Promise):
            ret = expr
        elif isinstance(expr, Symbol):
            gui_holder.evaluate()
            ret = frame.lookup(expr)
        elif isinstance(expr, Pair):
            if tail_context:
                if log_stack:
                    log.logger.eval_stack.pop()
                return Thunk(expr, frame, gui_holder, log_stack)
            else:
                gui_holder.evaluate()
                operator = expr.first
                import environment
                if isinstance(operator, Symbol) and environment.get_special_form(operator.value):
                    operator = environment.get_special_form(operator.value)
                else:
                    operator = evaluate(operator, frame, visual_expression.children[0])
                operands = pair_to_list(expr.rest)
                out = apply(operator, operands, frame, gui_holder)
                if isinstance(out, Thunk):
                    expr, frame = out.expr, out.frame
                    thunks.append(out)
                    if out.gui_holder.state != log.HolderState.EVALUATING:
                        out.gui_holder.evaluate()
                    if log.logger.show_thunks:
                        gui_holder = out.gui_holder
                    else:
                        gui_holder.expression.display_value = out.gui_holder.expression.display_value
                        gui_holder.expression.base_expr = out.gui_holder.expression.base_expr
                        gui_holder.expression.set_entries(list(x.expression for x in out.gui_holder.expression.children))
                    continue
                ret = out
        elif expr is Nil or expr is Undefined:
            ret = expr
        else:
            raise Exception("Internal error. Please report to maintainer!")

        for _ in range(depth):
            log.logger.eval_stack.pop()

        for thunk, holder in zip(reversed(thunks), reversed(holders)):
            holder.expression.value = ret
            holder.complete()
            thunk.evaluate(ret)

        holders[0].expression.value = ret
        holders[0].complete()

        return ret
Esempio n. 11
0
 def quasiquote_evaluate(cls,
                         expr: Expression,
                         frame: Frame,
                         gui_holder: Holder,
                         splicing=False):
     is_well_formed = False
     if isinstance(expr, Pair):
         try:
             lst = pair_to_list(expr)
         except OperandDeduceError:
             pass
         else:
             is_well_formed = (not any(
                 map((lambda x:
                      (isinstance(x, Symbol) and
                       (x.value in
                        ['unquote', 'quasiquote', 'unquote-splicing']))),
                     lst)))
     visual_expression = VisualExpression(expr)
     gui_holder.link_visual(visual_expression)
     if (not is_well_formed):
         visual_expression.children[2:] = []
     if isinstance(expr, Pair):
         if (isinstance(expr.first, Symbol)
                 and (expr.first.value in ('unquote', 'unquote-splicing'))):
             if ((expr.first.value == 'unquote-splicing')
                     and (not splicing)):
                 raise OperandDeduceError(
                     'Unquote-splicing must be in list template.')
             gui_holder.evaluate()
             verify_exact_callable_length(expr.first, 1,
                                          (len(pair_to_list(expr)) - 1))
             out = evaluate(expr.rest.first, frame,
                            visual_expression.children[1])
             visual_expression.value = out
             gui_holder.complete()
             return out
         elif (isinstance(expr.first, Symbol)
               and (expr.first.value == 'quasiquote')):
             visual_expression.value = expr
             gui_holder.complete()
             return expr
         else:
             if is_well_formed:
                 out = []
                 for (sub_expr, holder) in zip(pair_to_list(expr),
                                               visual_expression.children):
                     splicing = (isinstance(sub_expr, Pair)
                                 and isinstance(sub_expr.first, Symbol)
                                 and (sub_expr.first.value
                                      == 'unquote-splicing'))
                     evaluated = Quasiquote.quasiquote_evaluate(
                         sub_expr, frame, holder, splicing)
                     if splicing:
                         if (not isinstance(evaluated, (Pair, NilType))):
                             raise TypeMismatchError(''.join([
                                 'Can only splice lists, not ',
                                 '{}'.format(evaluated), '.'
                             ]))
                         out.extend(pair_to_list(evaluated))
                     else:
                         out.append(evaluated)
                 out = make_list(out)
             else:
                 if (not logger.dotted):
                     raise OperandDeduceError(''.join([
                         '{}'.format(expr),
                         ' is an ill-formed quasiquotation.'
                     ]))
                 out = Pair(
                     Quasiquote.quasiquote_evaluate(
                         expr.first, frame, visual_expression.children[0]),
                     Quasiquote.quasiquote_evaluate(
                         expr.rest, frame, visual_expression.children[1]))
             visual_expression.value = out
             gui_holder.complete()
             return out
     else:
         visual_expression.value = expr
         gui_holder.complete()
         return expr
Esempio n. 12
0
def string_exec(strings, out, visualize_tail_calls, global_frame=None):
    import log

    empty = False

    if global_frame is None:
        empty = True
        from environment import build_global_frame
        log.logger.f_delta -= 1
        global_frame = build_global_frame()
        log.logger.active_frames.pop(0)  # clear builtin frame
        log.logger.f_delta += 1
        log.logger.global_frame = log.logger.frame_lookup[id(global_frame)]
        log.logger.graphics_lookup[id(global_frame)] = Canvas()

    log.logger.export_states = []
    log.logger.roots = []
    log.logger.frame_updates = []
    log.logger._out = []
    log.logger.visualize_tail_calls(visualize_tail_calls)

    for i, string in enumerate(strings):
        try:
            if not string.strip():
                continue
            buff = TokenBuffer([string])
            while not buff.done:
                expr = get_expression(buff)
                if expr is None:
                    continue
                empty = False
                log.logger.new_expr()
                holder = Holder(expr, None)
                Root.setroot(holder)
                res = evaluate(expr, global_frame, holder)
                if res is not Undefined:
                    out(res)
                if not log.logger.fragile and log.logger.autodraw:
                    try:
                        log.logger.raw_out("AUTODRAW" +
                                           json.dumps([log.logger.i, log.logger.heap.record(res)]) + "\n")
                    except RecursionError:
                        pass
        except (SchemeError, ZeroDivisionError, RecursionError, ValueError) as e:
            if isinstance(e, ParseError):
                log.logger.new_expr()
                raise
            if not log.logger.fragile:
                log.logger.raw_out("Traceback (most recent call last)\n")
                for j, expr in enumerate(log.logger.eval_stack[:MAX_TRACEBACK_LENGTH - 1]):
                    log.logger.raw_out(str(j).ljust(3) + " " + expr + "\n")
                truncated = len(log.logger.eval_stack) - MAX_TRACEBACK_LENGTH
                if len(log.logger.eval_stack) > MAX_TRACEBACK_LENGTH:
                    log.logger.raw_out(f"[{truncated} lines omitted from traceback]\n")
                    log.logger.raw_out(
                        str(len(log.logger.eval_stack) - 1).ljust(3) + " " + log.logger.eval_stack[-1] + "\n"
                    )
            log.logger.out(e)
        except TimeLimitException:
            if not log.logger.fragile:
                log.logger.out("Time limit exceeded.")
        log.logger.new_expr()

    if empty:
        log.logger.new_expr()
        holder = Holder(Undefined, None)
        Root.setroot(holder)
        evaluate(Undefined, global_frame, holder)
        log.logger.new_expr()
Esempio n. 13
0
def evaluate(expr: Expression,
             frame: Frame,
             gui_holder: log.Holder,
             tail_context: bool = False,
             *,
             log_stack: bool = True) -> Union[(Expression, Thunk)]:
    '\n    >>> global_frame = __import__("special_forms").build_global_frame()\n    >>> gui_holder = __import__("gui").Holder(None)\n    >>> __import__("gui").Root.setroot(gui_holder)\n    >>> __import__("gui").silent = True\n\n    >>> buff = __import__("lexer").TokenBuffer(["(+ 1 2)"])\n    >>> expr = __import__("parser").get_expression(buff)\n    >>> result = evaluate(expr, global_frame, gui_holder)\n    >>> print(result)\n    3\n    >>> evaluate(__import__("parser").get_expression(__import__("lexer").TokenBuffer(["(+ 3 4 5)"])), global_frame, gui_holder)\n    12\n    >>> evaluate(__import__("parser").get_expression(__import__("lexer").TokenBuffer(["(* 3 4 5)"])), global_frame, gui_holder)\n    60\n    >>> evaluate(__import__("parser").get_expression(__import__("lexer").TokenBuffer(["(* (+ 1 2) 4 5)"])), global_frame, gui_holder)\n    60\n    >>> __import__("gui").silent = False\n    '
    depth = 0
    thunks = []
    holders = []
    while True:
        if (depth > RECURSION_LIMIT):
            raise OutOfMemoryError(
                'Debugger ran out of memory due to excessively deep recursion.'
            )
        if isinstance(gui_holder.expression, Expression):
            visual_expression = log.VisualExpression(expr)
            gui_holder.link_visual(visual_expression)
        else:
            visual_expression = gui_holder.expression
        if log_stack:
            log.logger.eval_stack.append(''.join([
                '{}'.format(repr(expr)), ' [frame = ', '{}'.format(frame.id),
                ']'
            ]))
            depth += 1
        holders.append(gui_holder)
        if (isinstance(expr, Number) or isinstance(expr, Callable)
                or isinstance(expr, Boolean) or isinstance(expr, String)
                or isinstance(expr, Promise)):
            ret = expr
        elif isinstance(expr, Symbol):
            gui_holder.evaluate()
            ret = frame.lookup(expr)
        elif isinstance(expr, Pair):
            if tail_context:
                if log_stack:
                    log.logger.eval_stack.pop()
                return Thunk(expr, frame, gui_holder, log_stack)
            else:
                gui_holder.evaluate()
                operator = expr.first
                import environment
                if (isinstance(operator, Symbol)
                        and environment.get_special_form(operator.value)):
                    operator = environment.get_special_form(operator.value)
                else:
                    operator = evaluate(operator, frame,
                                        visual_expression.children[0])
                operands = pair_to_list(expr.rest)
                out = apply(operator, operands, frame, gui_holder)
                if isinstance(out, Thunk):
                    (expr, frame) = (out.expr, out.frame)
                    gui_holder = out.gui_holder
                    thunks.append(out)
                    continue
                ret = out
        elif ((expr is Nil) or (expr is Undefined)):
            ret = expr
        else:
            raise Exception('Internal error. Please report to maintainer!')
        for _ in range(depth):
            log.logger.eval_stack.pop()
        for (thunk, holder) in zip(reversed(thunks), reversed(holders)):
            holder.expression.value = ret
            holder.complete()
            thunk.evaluate(ret)
        holders[0].expression.value = ret
        holders[0].complete()
        return ret
Esempio n. 14
0
def string_exec(strings, out, global_frame=None):
    import log
    empty = False
    if (global_frame is None):
        empty = True
        from environment import build_global_frame
        log.logger.f_delta -= 1
        global_frame = build_global_frame()
        log.logger.active_frames.pop(0)
        log.logger.f_delta += 1
        log.logger.global_frame = log.logger.frame_lookup[id(global_frame)]
        log.logger.graphics_lookup[id(global_frame)] = Canvas()
    log.logger.export_states = []
    log.logger.roots = []
    log.logger.frame_updates = []
    log.logger._out = []
    for (i, string) in enumerate(strings):
        try:
            if (not string.strip()):
                continue
            buff = TokenBuffer([string])
            while (not buff.done):
                expr = get_expression(buff)
                if (expr is None):
                    continue
                empty = False
                log.logger.new_expr()
                holder = Holder(expr, None)
                Root.setroot(holder)
                res = evaluate(expr, global_frame, holder)
                if (res is not Undefined):
                    out(res)
                if ((not log.logger.fragile) and log.logger.autodraw
                        and isinstance(res, Pair)):
                    log.logger.raw_out((('AUTODRAW' + json.dumps(
                        [log.logger.i,
                         log.logger.heap.record(res)])) + '\n'))
        except (SchemeError, ZeroDivisionError, RecursionError,
                ValueError) as e:
            if isinstance(e, ParseError):
                log.logger.new_expr()
                raise
            if (not log.logger.fragile):
                log.logger.raw_out('Traceback (most recent call last)\n')
                for (j, expr) in enumerate(
                        log.logger.eval_stack[:(MAX_TRACEBACK_LENGTH - 1)]):
                    log.logger.raw_out(
                        (((str(j).ljust(3) + ' ') + expr) + '\n'))
                truncated = (len(log.logger.eval_stack) - MAX_TRACEBACK_LENGTH)
                if (len(log.logger.eval_stack) > MAX_TRACEBACK_LENGTH):
                    log.logger.raw_out(''.join([
                        '[', '{}'.format(truncated),
                        ' lines omitted from traceback]\n'
                    ]))
                    log.logger.raw_out((((str(
                        (len(log.logger.eval_stack) - 1)).ljust(3) + ' ') +
                                         log.logger.eval_stack[(-1)]) + '\n'))
            log.logger.out(e)
        except TimeLimitException:
            if (not log.logger.fragile):
                log.logger.out('Time limit exceeded.')
        log.logger.new_expr()
    if empty:
        log.logger.new_expr()
        holder = Holder(Undefined, None)
        Root.setroot(holder)
        evaluate(Undefined, global_frame, holder)
        log.logger.new_expr()