def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder):
        verify_min_callable_length(self, 2, len(operands))

        bindings = operands[0]
        if not isinstance(bindings, Pair) and bindings is not Nil:
            raise OperandDeduceError(f"Expected first argument of let to be a Pair, not {bindings}.")

        new_frame = Frame("anonymous let", frame)

        bindings_holder = gui_holder.expression.children[1]

        bindings = pair_to_list(bindings)

        for i, binding in enumerate(bindings):
            if not isinstance(binding, Pair):
                raise OperandDeduceError(f"Expected binding to be a Pair, not {binding}.")
            binding_holder = bindings_holder.expression.children[i]
            binding = pair_to_list(binding)
            if len(binding) != 2:
                raise OperandDeduceError(f"Expected binding to be of length 2, not {len(binding)}.")
            name, expr = binding
            if not isinstance(name, Symbol):
                raise OperandDeduceError(f"Expected first element of binding to be a Symbol, not {name}.")
            new_frame.assign(name, evaluate(expr, frame, binding_holder.expression.children[1]))

        value = None

        for i, (operand, holder) in enumerate(zip(operands[1:], gui_holder.expression.children[2:])):
            value = evaluate(operand, new_frame, holder, i == len(operands) - 2)

        new_frame.assign(return_symbol, value)
        return value
예제 #2
0
 def execute_simple(self, operand: Expression):
     if isinstance(operand, Pair):
         try:
             pair_to_list(operand)
             return SingletonTrue
         except OperandDeduceError:
             return SingletonFalse
     else:
         return SingletonFalse
    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
예제 #4
0
파일: lists.py 프로젝트: SallyPeng00/61a
 def execute_simple(self, operand: Expression) -> Expression:
     if ((not isinstance(operand, Pair)) and (operand is not Nil)):
         raise OperandDeduceError(''.join([
             'Unable to calculate length, as ', '{}'.format(operand),
             ' is not a valid list.'
         ]))
     return Number(len(pair_to_list(operand)))
예제 #5
0
 def execute(self, operands: List[Expression], frame: Frame,
             gui_holder: Holder):
     verify_min_callable_length(self, 1, len(operands))
     for (cond_i, cond) in enumerate(operands):
         if (not isinstance(cond, Pair)):
             raise OperandDeduceError(''.join([
                 'Unable to evaluate clause of cond, as ',
                 '{}'.format(cond), ' is not a Pair.'
             ]))
         expanded = pair_to_list(cond)
         cond_holder = gui_holder.expression.children[(cond_i + 1)]
         cond_holder.link_visual(VisualExpression(cond))
         eval_condition = SingletonTrue
         if ((not isinstance(expanded[0], Symbol))
                 or (expanded[0].value != 'else')):
             eval_condition = evaluate(expanded[0], frame,
                                       cond_holder.expression.children[0])
         if ((isinstance(expanded[0], Symbol) and
              (expanded[0].value == 'else'))
                 or (eval_condition is not SingletonFalse)):
             out = eval_condition
             for (i, expr) in enumerate(expanded[1:]):
                 out = evaluate(expr, frame,
                                cond_holder.expression.children[(i + 1)],
                                (i == (len(expanded) - 2)))
             return out
     return Undefined
    def execute(self,
                operands: List[Expression],
                frame: Frame,
                gui_holder: Holder,
                name: str = "lambda"):
        verify_min_callable_length(self, 2, len(operands))
        params = operands[0]
        if not logger.dotted and not isinstance(params, (Pair, NilType)):
            raise OperandDeduceError(
                f"Expected Pair as parameter list, received {params}.")
        params, var_param = dotted_pair_to_list(params)
        for i, param in enumerate(params):
            if (logger.dotted
                    or i != len(params) - 1) and not isinstance(param, Symbol):
                raise OperandDeduceError(
                    f"Expected Symbol in parameter list, received {param}.")
            if isinstance(param, Pair):
                param_vals = pair_to_list(param)
                if len(param_vals) != 2 or \
                        not isinstance(param_vals[0], Symbol) or \
                        not isinstance(param_vals[1], Symbol) or \
                        param_vals[0].value != "variadic":
                    raise OperandDeduceError(
                        f"Each member of a parameter list must be a Symbol or a variadic "
                        f"parameter, not {param}.")
                var_param = param_vals[1]
                params.pop()

        return self.procedure(params, var_param, operands[1:], frame, name)
예제 #7
0
 def execute(self,
             operands: List[Expression],
             frame: Frame,
             gui_holder: Holder,
             name: str = 'lambda'):
     verify_min_callable_length(self, 2, len(operands))
     params = operands[0]
     if ((not logger.dotted) and (not isinstance(params, (Pair, NilType)))):
         raise OperandDeduceError(''.join([
             'Expected Pair as parameter list, received ',
             '{}'.format(params), '.'
         ]))
     (params, var_param) = dotted_pair_to_list(params)
     for (i, param) in enumerate(params):
         if ((logger.dotted or (i != (len(params) - 1)))
                 and (not isinstance(param, Symbol))):
             raise OperandDeduceError(''.join([
                 'Expected Symbol in parameter list, received ',
                 '{}'.format(param), '.'
             ]))
         if isinstance(param, Pair):
             param_vals = pair_to_list(param)
             if ((len(param_vals) != 2)
                     or (not isinstance(param_vals[0], Symbol))
                     or (not isinstance(param_vals[1], Symbol))
                     or (param_vals[0].value != 'variadic')):
                 raise OperandDeduceError(''.join([
                     'Each member of a parameter list must be a Symbol or a variadic parameter, not ',
                     '{}'.format(param), '.'
                 ]))
             var_param = param_vals[1]
             params.pop()
     return self.procedure(params, var_param, operands[1:], frame, name)
예제 #8
0
 def __init__(self,
              base_expr: Expression = None,
              true_base_expr: Expression = None):
     self.display_value = base_expr
     self.base_expr = (base_expr if
                       (true_base_expr is None) else true_base_expr)
     self.value = None
     self.children = []
     self.id = get_id()
     if (logger.op_count >= OP_LIMIT):
         self.children = fake_obj
         return
     if (base_expr is None):
         return
     if (isinstance(base_expr, ValueHolder)
             or isinstance(base_expr, evaluate_apply.Callable)
             or isinstance(base_expr, Promise) or (base_expr == Nil)
             or (base_expr == Undefined)):
         self.value = base_expr
     elif isinstance(base_expr, Pair):
         try:
             self.set_entries(pair_to_list(base_expr))
         except OperandDeduceError:
             self.set_entries([base_expr.first, base_expr.rest])
     else:
         raise NotImplementedError(base_expr, type(base_expr))
예제 #9
0
 def execute(self, operands: List[Expression], frame: Frame,
             gui_holder: Holder):
     verify_min_callable_length(self, 2, len(operands))
     bindings = operands[0]
     if ((not isinstance(bindings, Pair)) and (bindings is not Nil)):
         raise OperandDeduceError(''.join([
             'Expected first argument of let to be a Pair, not ',
             '{}'.format(bindings), '.'
         ]))
     new_frame = Frame('anonymous let', frame)
     gui_holder.expression.children[1].link_visual(
         VisualExpression(bindings))
     bindings_holder = gui_holder.expression.children[1]
     bindings = pair_to_list(bindings)
     for (i, binding) in enumerate(bindings):
         if (not isinstance(binding, Pair)):
             raise OperandDeduceError(''.join([
                 'Expected binding to be a Pair, not ',
                 '{}'.format(binding), '.'
             ]))
         binding_holder = bindings_holder.expression.children[i]
         binding_holder.link_visual(VisualExpression(binding))
         binding = pair_to_list(binding)
         if (len(binding) != 2):
             raise OperandDeduceError(''.join([
                 'Expected binding to be of length 2, not ',
                 '{}'.format(len(binding)), '.'
             ]))
         (name, expr) = binding
         if (not isinstance(name, Symbol)):
             raise OperandDeduceError(''.join([
                 'Expected first element of binding to be a Symbol, not ',
                 '{}'.format(name), '.'
             ]))
         new_frame.assign(
             name,
             evaluate(expr, frame, binding_holder.expression.children[1]))
     value = None
     for (i, (operand, holder)) in enumerate(
             zip(operands[1:], gui_holder.expression.children[2:])):
         value = evaluate(operand, new_frame, holder,
                          (i == (len(operands) - 2)))
     new_frame.assign(return_symbol, value)
     return value
예제 #10
0
 def execute_evaluated(self, operands: List[Expression], frame: Frame) -> Expression:
     if len(operands) == 0:
         return Nil
     exprs = []
     for operand in operands[:-1]:
         if not isinstance(operand, Pair) and operand is not Nil:
             raise OperandDeduceError(f"Expected operand to be valid list, not {operand}")
         exprs.extend(pair_to_list(operand))
     out = operands[-1]
     for expr in reversed(exprs):
         out = Pair(expr, out)
     return out
예제 #11
0
 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)
예제 #12
0
파일: lists.py 프로젝트: SallyPeng00/61a
 def execute_evaluated(self, operands: List[Expression],
                       frame: Frame) -> Expression:
     if (len(operands) == 0):
         return Nil
     out = []
     for operand in operands[:(-1)]:
         if ((not isinstance(operand, Pair)) and (operand is not Nil)):
             raise OperandDeduceError(''.join([
                 'Expected operand to be valid list, not ',
                 '{}'.format(operand)
             ]))
         out.extend(pair_to_list(operand))
     try:
         last = operands[(-1)]
         if (not isinstance(last, Pair)):
             raise OperandDeduceError()
         last = pair_to_list(last)
     except OperandDeduceError:
         return make_list(out, operands[(-1)])
     else:
         out.extend(last)
         return make_list(out)
예제 #13
0
파일: lists.py 프로젝트: SallyPeng00/61a
 def execute_evaluated(self, operands: List[Expression], frame: Frame) -> Expression:
     if (len(operands) == 0):
         return Nil
     exprs = []
     for operand in operands[:(- 1)]:
         if ((not isinstance(operand, Pair)) and (operand is not Nil)):
             raise OperandDeduceError(
                 ''.join(['Expected operand to be valid list, not ', '{}'.format(operand)]))
         exprs.extend(pair_to_list(operand))
     out = operands[(- 1)]
     for expr in reversed(exprs):
         out = Pair(expr, out)
     return out
예제 #14
0
 def execute(self, operands: List[Expression], frame: Frame, gui_holder: Holder):
     verify_min_callable_length(self, 1, len(operands))
     for cond_i, cond in enumerate(operands):
         if not isinstance(cond, Pair):
             raise OperandDeduceError(f"Unable to evaluate clause of cond, as {cond} is not a Pair.")
         expanded = pair_to_list(cond)
         cond_holder = gui_holder.expression.children[cond_i + 1]
         eval_condition = SingletonTrue
         if not isinstance(expanded[0], Symbol) or expanded[0].value != "else":
             eval_condition = evaluate(expanded[0], frame, cond_holder.expression.children[0])
         if (isinstance(expanded[0], Symbol) and expanded[0].value == "else") \
                 or eval_condition is not SingletonFalse:
             out = eval_condition
             for i, expr in enumerate(expanded[1:]):
                 out = evaluate(expr, frame, cond_holder.expression.children[i + 1], i == len(expanded) - 2)
             return out
     return Undefined
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
예제 #16
0
 def execute_simple(self, operand: Expression) -> Expression:
     if not isinstance(operand, Pair) and operand is not Nil:
         raise OperandDeduceError(f"Unable to calculate length, as {operand} is not a valid list.")
     return Number(len(pair_to_list(operand)))
예제 #17
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
예제 #18
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