diff --git a/docs/trace.txt b/docs/trace.txt new file mode 100644 index 0000000..62c6c37 --- /dev/null +++ b/docs/trace.txt @@ -0,0 +1,165 @@ +Phase 0: build the initial program: + + 5 • range_to_zero + 5 • unit [down_to_zero] infra + [5] • [down_to_zero] infra + [5] [down_to_zero] • infra + +Phase 1: Build a while loop: + + 5 • down_to_zero [] swaack + 5 • [0 >] [dup --] while [] swaack + 5 [0 >] • [dup --] while [] swaack + 5 [0 >] [dup --] • while [] swaack + +Phase 2: While loop converts to loop loop: + + 5 [0 >] [dup --] • swap nulco dupdipd concat loop [] swaack + 5 [dup --] [0 >] • nulco dupdipd concat loop [] swaack + 5 [dup --] [0 >] • [nullary] cons dupdipd concat loop [] swaack + 5 [dup --] [0 >] [nullary] • cons dupdipd concat loop [] swaack + 5 [dup --] [[0 >] nullary] • dupdipd concat loop [] swaack + 5 [dup --] [[0 >] nullary] • dup dipd concat loop [] swaack +5 [dup --] [[0 >] nullary] [[0 >] nullary] • dipd concat loop [] swaack + 5 • [0 >] nullary [dup --] [[0 >] nullary] concat loop [] swaack + +Phase 3: Compute first loop Boolean: + + 5 [0 >] • nullary [dup --] [[0 >] nullary] concat loop [] swaack + 5 [0 >] • [stack] dip infra first [dup --] [[0 >] nullary] concat loop [] swaack + 5 [0 >] [stack] • dip infra first [dup --] [[0 >] nullary] concat loop [] swaack + 5 • stack [0 >] infra first [dup --] [[0 >] nullary] concat loop [] swaack + 5 [5] • [0 >] infra first [dup --] [[0 >] nullary] concat loop [] swaack + 5 [5] [0 >] • infra first [dup --] [[0 >] nullary] concat loop [] swaack + 5 • 0 > [5] swaack first [dup --] [[0 >] nullary] concat loop [] swaack + 5 0 • > [5] swaack first [dup --] [[0 >] nullary] concat loop [] swaack + 5 0 • gt [5] swaack first [dup --] [[0 >] nullary] concat loop [] swaack + true • [5] swaack first [dup --] [[0 >] nullary] concat loop [] swaack + true [5] • swaack first [dup --] [[0 >] nullary] concat loop [] swaack + 5 [true] • first [dup --] [[0 >] nullary] concat loop [] swaack + 5 true • [dup --] [[0 >] nullary] concat loop [] swaack + +Phase 4a: Finish constructing main body of loop (this function [dup -- [0 >] nullary] seems easily compilable.): + + 5 true [dup --] • [[0 >] nullary] concat loop [] swaack + 5 true [dup --] [[0 >] nullary] • concat loop [] swaack + 5 true [dup -- [0 >] nullary] • loop [] swaack + +Phase 4b: Enter main body of loop: + + 5 • dup -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 5 • -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 5 • 1 - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 5 1 • - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 5 1 • sub [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 • [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 [0 >] • nullary [dup -- [0 >] nullary] loop [] swaack + + 5 4 [0 >] • [stack] dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 [0 >] [stack] • dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 • stack [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 [4 5] • [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 [4 5] [0 >] • infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 • 0 > [4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 0 • > [4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 0 • gt [4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 true • [4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 true [4 5] • swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 [true 5] • first [dup -- [0 >] nullary] loop [] swaack + 5 4 true • [dup -- [0 >] nullary] loop [] swaack + + 5 4 true [dup -- [0 >] nullary] • loop [] swaack + + 5 4 • dup -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 4 • -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 4 • 1 - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 4 1 • - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 4 1 • sub [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 • [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [0 >] • nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [0 >] • [stack] dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [0 >] [stack] • dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 • stack [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [3 4 5] • [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [3 4 5] [0 >] • infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 • 0 > [3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 0 • > [3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 0 • gt [3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 true • [3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 true [3 4 5] • swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 [true 4 5] • first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 true • [dup -- [0 >] nullary] loop [] swaack + + 5 4 3 true [dup -- [0 >] nullary] • loop [] swaack + + 5 4 3 • dup -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 3 • -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 3 • 1 - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 3 1 • - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 3 1 • sub [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 • [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [0 >] • nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [0 >] • [stack] dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [0 >] [stack] • dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 • stack [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [2 3 4 5] • [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [2 3 4 5] [0 >] • infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 • 0 > [2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 0 • > [2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 0 • gt [2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 true • [2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 true [2 3 4 5] • swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 [true 3 4 5] • first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 true • [dup -- [0 >] nullary] loop [] swaack + + 5 4 3 2 true [dup -- [0 >] nullary] • loop [] swaack + + 5 4 3 2 • dup -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 2 • -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 2 • 1 - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 2 1 • - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 2 1 • sub [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 • [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [0 >] • nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [0 >] • [stack] dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [0 >] [stack] • dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 • stack [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [1 2 3 4 5] • [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [1 2 3 4 5] [0 >] • infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 • 0 > [1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 • > [1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 • gt [1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 true • [1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 true [1 2 3 4 5] • swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 [true 2 3 4 5] • first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 true • [dup -- [0 >] nullary] loop [] swaack + + 5 4 3 2 1 true [dup -- [0 >] nullary] • loop [] swaack + + 5 4 3 2 1 • dup -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 1 • -- [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 1 • 1 - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 1 1 • - [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 1 1 • sub [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 • [0 >] nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [0 >] • nullary [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [0 >] • [stack] dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [0 >] [stack] • dip infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 • stack [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [0 1 2 3 4 5] • [0 >] infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [0 1 2 3 4 5] [0 >] • infra first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 • 0 > [0 1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 0 • > [0 1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 0 • gt [0 1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 false • [0 1 2 3 4 5] swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 false [0 1 2 3 4 5] • swaack first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 [false 1 2 3 4 5] • first [dup -- [0 >] nullary] loop [] swaack + 5 4 3 2 1 0 false • [dup -- [0 >] nullary] loop [] swaack + + 5 4 3 2 1 0 false [dup -- [0 >] nullary] • loop [] swaack + +Phase 5: Loop finished, complete original infra: + + 5 4 3 2 1 0 • [] swaack + 5 4 3 2 1 0 [] • swaack + [0 1 2 3 4 5] • diff --git a/implementations/Python/generated_library.py b/implementations/Python/generated_library.py deleted file mode 100644 index 2e51422..0000000 --- a/implementations/Python/generated_library.py +++ /dev/null @@ -1,414 +0,0 @@ -# GENERATED FILE. DO NOT EDIT. -# The code that generated these functions is in the repo history -# at the v0.4.0 tag. -from .errors import NotAListError, StackUnderflowError - - -def _Tree_add_Ee(stack): - """ - :: - - ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) - - """ - (a1, (a2, (a3, ((a4, (a5, s1)), s2)))) = stack - return ((a2, (a3, s1)), s2) - - -def _Tree_delete_R0(stack): - """ - :: - - ([a2 ...1] a1 -- [a2 ...1] a2 a1 a1) - - """ - (a1, ((a2, s1), s2)) = stack - return (a1, (a1, (a2, ((a2, s1), s2)))) - - -def _Tree_delete_clear_stuff(stack): - """ - :: - - (a3 a2 [a1 ...1] -- [...1]) - - """ - ((a1, s1), (a2, (a3, s2))) = stack - return (s1, s2) - - -def _Tree_get_E(stack): - """ - :: - - ([a3 a4 ...1] a2 a1 -- a4) - - """ - (a1, (a2, ((a3, (a4, s1)), s2))) = stack - return (a4, s2) - - -def ccons(stack): - """ - :: - - (a2 a1 [...1] -- [a2 a1 ...1]) - - """ - (s1, (a1, (a2, s2))) = stack - return ((a2, (a1, s1)), s2) - - -def cons(stack): - """ - :: - - (a1 [...0] -- [a1 ...0]) - - """ - try: s0, stack = stack - except ValueError: raise StackUnderflowError('Not enough values on stack.') - if not isinstance(s0, tuple): raise NotAListError('Not a list.') - try: a1, s23 = stack - except ValueError: raise StackUnderflowError('Not enough values on stack.') - return ((a1, s0), s23) - - -def dup(stack): - """ - :: - - (a1 -- a1 a1) - - """ - (a1, s23) = stack - return (a1, (a1, s23)) - - -def dupd(stack): - """ - :: - - (a2 a1 -- a2 a2 a1) - - """ - (a1, (a2, s23)) = stack - return (a1, (a2, (a2, s23))) - - -def dupdd(stack): - """ - :: - - (a3 a2 a1 -- a3 a3 a2 a1) - - """ - (a1, (a2, (a3, s23))) = stack - return (a1, (a2, (a3, (a3, s23)))) - - -def first(stack): - """ - :: - - ([a1 ...1] -- a1) - - """ - ((a1, s1), s23) = stack - return (a1, s23) - - -def first_two(stack): - """ - :: - - ([a1 a2 ...1] -- a1 a2) - - """ - ((a1, (a2, s1)), s2) = stack - return (a2, (a1, s2)) - - -def fourth(stack): - """ - :: - - ([a1 a2 a3 a4 ...1] -- a4) - - """ - ((a1, (a2, (a3, (a4, s1)))), s2) = stack - return (a4, s2) - - -def over(stack): - """ - :: - - (a2 a1 -- a2 a1 a2) - - """ - (a1, (a2, s23)) = stack - return (a2, (a1, (a2, s23))) - - -def pop(stack): - """ - :: - - (a1 --) - - """ - try: - (a1, s23) = stack - except ValueError: - raise StackUnderflowError('Cannot pop empty stack.') - return s23 - - -def popd(stack): - """ - :: - - (a2 a1 -- a1) - - """ - (a1, (a2, s23)) = stack - return (a1, s23) - - -def popdd(stack): - """ - :: - - (a3 a2 a1 -- a2 a1) - - """ - (a1, (a2, (a3, s23))) = stack - return (a1, (a2, s23)) - - -def popop(stack): - """ - :: - - (a2 a1 --) - - """ - (a1, (a2, s23)) = stack - return s23 - - -def popopd(stack): - """ - :: - - (a3 a2 a1 -- a1) - - """ - (a1, (a2, (a3, s23))) = stack - return (a1, s23) - - -def popopdd(stack): - """ - :: - - (a4 a3 a2 a1 -- a2 a1) - - """ - (a1, (a2, (a3, (a4, s23)))) = stack - return (a1, (a2, s23)) - - -def rest(stack): - """ - :: - - ([a1 ...0] -- [...0]) - - """ - try: - s0, stack = stack - except ValueError: - raise StackUnderflowError - if not isinstance(s0, tuple): - raise NotAListError('Not a list.') - try: - _, s1 = s0 - except ValueError: - raise StackUnderflowError('Cannot take rest of empty list.') - return (s1, stack) - - -def rolldown(stack): - """ - :: - - (a1 a2 a3 -- a2 a3 a1) - - """ - (a3, (a2, (a1, s23))) = stack - return (a1, (a3, (a2, s23))) - - -def rollup(stack): - """ - :: - - (a1 a2 a3 -- a3 a1 a2) - - """ - (a3, (a2, (a1, s23))) = stack - return (a2, (a1, (a3, s23))) - - -def rrest(stack): - """ - :: - - ([a1 a2 ...1] -- [...1]) - - """ - ((a1, (a2, s1)), s2) = stack - return (s1, s2) - - -def second(stack): - """ - :: - - ([a1 a2 ...1] -- a2) - - """ - ((a1, (a2, s1)), s2) = stack - return (a2, s2) - - -def stack(stack): - """ - :: - - (... -- ... [...]) - - """ - s0 = stack - return (s0, s0) - - -def stuncons(stack): - """ - :: - - (... a1 -- ... a1 a1 [...]) - - """ - (a1, s1) = stack - return (s1, (a1, (a1, s1))) - - -def stununcons(stack): - """ - :: - - (... a2 a1 -- ... a2 a1 a1 a2 [...]) - - """ - (a1, (a2, s1)) = stack - return (s1, (a2, (a1, (a1, (a2, s1))))) - - -def swaack(stack): - """ - :: - - ([...1] -- [...0]) - - """ - try: - (s1, s0) = stack - except ValueError: - raise StackUnderflowError('Not enough values on stack.') - if not isinstance(s1, tuple): - raise NotAListError('Not a list.') - return (s0, s1) - - -def swap(stack): - """ - :: - - (a1 a2 -- a2 a1) - - """ - try: - (a2, (a1, s23)) = stack - except ValueError: - raise StackUnderflowError('Not enough values on stack.') - return (a1, (a2, s23)) - - -def swons(stack): - """ - :: - - ([...1] a1 -- [a1 ...1]) - - """ - (a1, (s1, s2)) = stack - return ((a1, s1), s2) - - -def third(stack): - """ - :: - - ([a1 a2 a3 ...1] -- a3) - - """ - ((a1, (a2, (a3, s1))), s2) = stack - return (a3, s2) - - -def tuck(stack): - """ - :: - - (a2 a1 -- a1 a2 a1) - - """ - (a1, (a2, s23)) = stack - return (a1, (a2, (a1, s23))) - - -def uncons(stack): - """ - :: - - ([a1 ...0] -- a1 [...0]) - - """ - ((a1, s0), s23) = stack - return (s0, (a1, s23)) - - -def unit(stack): - """ - :: - - (a1 -- [a1 ]) - - """ - (a1, s23) = stack - return ((a1, ()), s23) - - -def unswons(stack): - """ - :: - - ([a1 ...1] -- [...1] a1) - - """ - ((a1, s1), s2) = stack - return (a1, (s1, s2)) - diff --git a/implementations/Python/joy/utils/pretty_print.py b/implementations/Python/joy/utils/pretty_print.py deleted file mode 100644 index c191765..0000000 --- a/implementations/Python/joy/utils/pretty_print.py +++ /dev/null @@ -1,124 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright © 2016 Simon Forman -# -# This file is part of Thun. -# -# Thun is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Thun is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Thun. If not see . -# -''' -Pretty printing support, e.g.:: - - Joy? [23 18 * 99 +] trace - • 23 18 mul 99 add - 23 • 18 mul 99 add - 23 18 • mul 99 add - 414 • 99 add - 414 99 • add - 513 • - - 513 <-top - - joy? - -On each line the stack is printed with the top to the left, then a -bullet symbol, •, to represent the current locus of processing, then -the pending expression to the right. -''' -# (Kinda clunky and hacky. This should be swapped out in favor of much -# smarter stuff.) -from traceback import print_exc -from .stack import expression_to_string, stack_to_string -from ..joy import joy -from ..library import FunctionWrapper - - -@FunctionWrapper -def trace(stack, expression, dictionary): - '''Evaluate a Joy expression on a stack and print a trace. - - This function is just like the `i` combinator but it also prints a - trace of the evaluation - - :param stack stack: The stack. - :param stack expression: The expression to evaluate. - :param dict dictionary: A ``dict`` mapping names to Joy functions. - :rtype: (stack, (), dictionary) - - ''' - tp = TracePrinter() - quote, stack = stack - try: - s, _, d = joy(stack, quote, dictionary, tp.viewer) - except: - tp.print_() - print('-' * 73) - raise - else: - tp.print_() - return s, expression, d - - -class TracePrinter(object): - ''' - This is what does the formatting. You instantiate it and pass the ``viewer()`` - method to the :py:func:`joy.joy.joy` function, then print it to see the - trace. - ''' - - def __init__(self): - self.history = [] - - def viewer(self, stack, expression): - ''' - Record the current stack and expression in the TracePrinter's history. - Pass this method as the ``viewer`` argument to the :py:func:`joy.joy.joy` function. - - :param stack quote: A stack. - :param stack expression: A stack. - ''' - self.history.append((stack, expression)) - - def __str__(self): - return '\n'.join(self.go()) - - def go(self): - ''' - Return a list of strings, one for each entry in the history, prefixed - with enough spaces to align all the interpreter dots. - - This method is called internally by the ``__str__()`` method. - - :rtype: list(str) - ''' - max_stack_length = 0 - lines = [] - for stack, expression in self.history: - stack = stack_to_string(stack) - expression = expression_to_string(expression) - n = len(stack) - if n > max_stack_length: - max_stack_length = n - lines.append((n, '%s • %s' % (stack, expression))) - for i in range(len(lines)): # Prefix spaces to line up '•'s. - length, line = lines[i] - lines[i] = (' ' * (max_stack_length - length) + line) - return lines - - def print_(self): - try: - print(self) - except: - print_exc() - print('Exception while printing viewer.') diff --git a/implementations/Python/simplejoy.py b/implementations/Python/simplejoy.py index 664071d..1ea536b 100755 --- a/implementations/Python/simplejoy.py +++ b/implementations/Python/simplejoy.py @@ -307,9 +307,9 @@ def joy(stack, expression, dictionary): ''' expr = push_quote(expression) # We keep a stack-of-stacks, see below. while expr: - print( - f'{stack_to_string(stack)} • {expr_to_string(expr)}' - ) + #print( + # f'{stack_to_string(stack)} • {expr_to_string(expr)}' + # ) term, expr = next_term(expr) if isinstance(term, Symbol): try: @@ -1351,6 +1351,57 @@ inscribe(UnaryWrapper(isnt_stack)) ''' +@inscribe +def trace(stack, expr, dictionary): + '''Evaluate a Joy expression on a stack and print a trace. + + This function is just like the `i` combinator but it also prints a + trace of the evaluation + + :param stack stack: The stack. + :param stack expression: The expression to evaluate. + :param dict dictionary: A ``dict`` mapping names to Joy functions. + :rtype: (stack, (), dictionary) + + ''' + quote, stack = get_n_items(1, stack) + isnt_stack(quote) + history = [] + append = history.append + local_expr = push_quote(quote) + while local_expr: + append((stack, local_expr)) + term, local_expr = next_term(local_expr) + if isinstance(term, Symbol): + try: + func = dictionary[term] + except KeyError: + print(trace_to_string(history)) + raise UnknownSymbolError(term) from None + stack, local_expr, dictionary = func(stack, local_expr, dictionary) + else: + stack = term, stack + append((stack, local_expr)) + print(trace_to_string(history)) + return stack, expr, dictionary + + +def trace_to_string(history): + max_stack_length = 0 + lines = [] + for stack, expression in history: + stack = stack_to_string(stack) + expression = expr_to_string(expression) + length = len(stack) + max_stack_length = max(max_stack_length, length) + lines.append((length, stack, expression)) + return '\n'.join( + # Prefix spaces to line up '•'s. + (' ' * (max_stack_length - length) + f'{stack} • {expression}') + for i, (length, stack, expression) in enumerate(lines) + ) + + S_swaack = Symbol('swaack') S_genrec = Symbol('genrec') S_ifte = Symbol('ifte') @@ -2226,6 +2277,471 @@ def times(stack, expr, dictionary): return stack, expr, dictionary +@inscribe +@SimpleFunctionWrapper +def _Tree_add_Ee(stack): + """ + :: + + ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) + + """ + (a1, (a2, (a3, ((a4, (a5, s1)), s2)))) = stack + return ((a2, (a3, s1)), s2) + + +@inscribe +@SimpleFunctionWrapper +def _Tree_delete_R0(stack): + """ + :: + + ([a2 ...1] a1 -- [a2 ...1] a2 a1 a1) + + """ + (a1, ((a2, s1), s2)) = stack + return (a1, (a1, (a2, ((a2, s1), s2)))) + + +@inscribe +@SimpleFunctionWrapper +def _Tree_delete_clear_stuff(stack): + """ + :: + + (a3 a2 [a1 ...1] -- [...1]) + + """ + ((a1, s1), (a2, (a3, s2))) = stack + return (s1, s2) + + +@inscribe +@SimpleFunctionWrapper +def _Tree_get_E(stack): + """ + :: + + ([a3 a4 ...1] a2 a1 -- a4) + + """ + (a1, (a2, ((a3, (a4, s1)), s2))) = stack + return (a4, s2) + + +@inscribe +@SimpleFunctionWrapper +def ccons(stack): + """ + :: + + (a2 a1 [...1] -- [a2 a1 ...1]) + + """ + (s1, (a1, (a2, s2))) = stack + return ((a2, (a1, s1)), s2) + + +##def cons(stack): +## """ +## :: +## +## (a1 [...0] -- [a1 ...0]) +## +## """ +## try: s0, stack = stack +## except ValueError: raise StackUnderflowError('Not enough values on stack.') +## if not isinstance(s0, tuple): raise NotAListError('Not a list.') +## try: a1, s23 = stack +## except ValueError: raise StackUnderflowError('Not enough values on stack.') +## return ((a1, s0), s23) + + +##def dup(stack): +## """ +## :: +## +## (a1 -- a1 a1) +## +## """ +## (a1, s23) = stack +## return (a1, (a1, s23)) + + +@inscribe +@SimpleFunctionWrapper +def dupd(stack): + """ + :: + + (a2 a1 -- a2 a2 a1) + + """ + (a1, (a2, s23)) = stack + return (a1, (a2, (a2, s23))) + + +@inscribe +@SimpleFunctionWrapper +def dupdd(stack): + """ + :: + + (a3 a2 a1 -- a3 a3 a2 a1) + + """ + (a1, (a2, (a3, s23))) = stack + return (a1, (a2, (a3, (a3, s23)))) + + +##def first(stack): +## """ +## :: +## +## ([a1 ...1] -- a1) +## +## """ +## ((a1, s1), s23) = stack +## return (a1, s23) + + +@inscribe +@SimpleFunctionWrapper +def first_two(stack): + """ + :: + + ([a1 a2 ...1] -- a1 a2) + + """ + ((a1, (a2, s1)), s2) = stack + return (a2, (a1, s2)) + + +@inscribe +@SimpleFunctionWrapper +def fourth(stack): + """ + :: + + ([a1 a2 a3 a4 ...1] -- a4) + + """ + ((a1, (a2, (a3, (a4, s1)))), s2) = stack + return (a4, s2) + + +@inscribe +@SimpleFunctionWrapper +def over(stack): + """ + :: + + (a2 a1 -- a2 a1 a2) + + """ + (a1, (a2, s23)) = stack + return (a2, (a1, (a2, s23))) + + +##def pop(stack): +## """ +## :: +## +## (a1 --) +## +## """ +## try: +## (a1, s23) = stack +## except ValueError: +## raise StackUnderflowError('Cannot pop empty stack.') +## return s23 + + +@inscribe +@SimpleFunctionWrapper +def popd(stack): + """ + :: + + (a2 a1 -- a1) + + """ + (a1, (a2, s23)) = stack + return (a1, s23) + + +@inscribe +@SimpleFunctionWrapper +def popdd(stack): + """ + :: + + (a3 a2 a1 -- a2 a1) + + """ + (a1, (a2, (a3, s23))) = stack + return (a1, (a2, s23)) + + +@inscribe +@SimpleFunctionWrapper +def popop(stack): + """ + :: + + (a2 a1 --) + + """ + (a1, (a2, s23)) = stack + return s23 + + +@inscribe +@SimpleFunctionWrapper +def popopd(stack): + """ + :: + + (a3 a2 a1 -- a1) + + """ + (a1, (a2, (a3, s23))) = stack + return (a1, s23) + + +@inscribe +@SimpleFunctionWrapper +def popopdd(stack): + """ + :: + + (a4 a3 a2 a1 -- a2 a1) + + """ + (a1, (a2, (a3, (a4, s23)))) = stack + return (a1, (a2, s23)) + + +##def rest(stack): +## """ +## :: +## +## ([a1 ...0] -- [...0]) +## +## """ +## try: +## s0, stack = stack +## except ValueError: +## raise StackUnderflowError +## if not isinstance(s0, tuple): +## raise NotAListError('Not a list.') +## try: +## _, s1 = s0 +## except ValueError: +## raise StackUnderflowError('Cannot take rest of empty list.') +## return (s1, stack) + + +@inscribe +@SimpleFunctionWrapper +def rolldown(stack): + """ + :: + + (a1 a2 a3 -- a2 a3 a1) + + """ + (a3, (a2, (a1, s23))) = stack + return (a1, (a3, (a2, s23))) + + +@inscribe +@SimpleFunctionWrapper +def rollup(stack): + """ + :: + + (a1 a2 a3 -- a3 a1 a2) + + """ + (a3, (a2, (a1, s23))) = stack + return (a2, (a1, (a3, s23))) + + +@inscribe +@SimpleFunctionWrapper +def rrest(stack): + """ + :: + + ([a1 a2 ...1] -- [...1]) + + """ + ((a1, (a2, s1)), s2) = stack + return (s1, s2) + + +@inscribe +@SimpleFunctionWrapper +def second(stack): + """ + :: + + ([a1 a2 ...1] -- a2) + + """ + ((a1, (a2, s1)), s2) = stack + return (a2, s2) + + +@inscribe +@SimpleFunctionWrapper +def stack(stack): + """ + :: + + (... -- ... [...]) + + """ + s0 = stack + return (s0, s0) + + +@inscribe +@SimpleFunctionWrapper +def stuncons(stack): + """ + :: + + (... a1 -- ... a1 a1 [...]) + + """ + (a1, s1) = stack + return (s1, (a1, (a1, s1))) + + +@inscribe +@SimpleFunctionWrapper +def stununcons(stack): + """ + :: + + (... a2 a1 -- ... a2 a1 a1 a2 [...]) + + """ + (a1, (a2, s1)) = stack + return (s1, (a2, (a1, (a1, (a2, s1))))) + + +##def swaack(stack): +## """ +## :: +## +## ([...1] -- [...0]) +## +## """ +## try: +## (s1, s0) = stack +## except ValueError: +## raise StackUnderflowError('Not enough values on stack.') +## if not isinstance(s1, tuple): +## raise NotAListError('Not a list.') +## return (s0, s1) + + +##def swap(stack): +## """ +## :: +## +## (a1 a2 -- a2 a1) +## +## """ +## try: +## (a2, (a1, s23)) = stack +## except ValueError: +## raise StackUnderflowError('Not enough values on stack.') +## return (a1, (a2, s23)) + + +@inscribe +@SimpleFunctionWrapper +def swons(stack): + """ + :: + + ([...1] a1 -- [a1 ...1]) + + """ + (a1, (s1, s2)) = stack + return ((a1, s1), s2) + + +@inscribe +@SimpleFunctionWrapper +def third(stack): + """ + :: + + ([a1 a2 a3 ...1] -- a3) + + """ + ((a1, (a2, (a3, s1))), s2) = stack + return (a3, s2) + + +@inscribe +@SimpleFunctionWrapper +def tuck(stack): + """ + :: + + (a2 a1 -- a1 a2 a1) + + """ + (a1, (a2, s23)) = stack + return (a1, (a2, (a1, s23))) + + +@inscribe +@SimpleFunctionWrapper +def uncons(stack): + """ + :: + + ([a1 ...0] -- a1 [...0]) + + """ + ((a1, s0), s23) = stack + return (s0, (a1, s23)) + + +@inscribe +@SimpleFunctionWrapper +def unit(stack): + """ + :: + + (a1 -- [a1 ]) + + """ + (a1, s23) = stack + return ((a1, ()), s23) + + +@inscribe +@SimpleFunctionWrapper +def unswons(stack): + """ + :: + + ([a1 ...1] -- [...1] a1) + + """ + ((a1, s1), s2) = stack + return (a1, (s1, s2)) + + def default_defs(dictionary): Def.load_definitions(__doc__.splitlines(), dictionary)