Пример #1
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
Пример #2
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