From: Simon Forman Date: Tue, 17 Jul 2018 19:43:24 +0000 (-0700) Subject: So fra, so good... X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=c2dd7cca0a676b0096426365585ebbf75d07e074;p=joypy%2FThun.git So fra, so good... --- diff --git a/joy/library.py b/joy/library.py index b0f0749..449c48d 100644 --- a/joy/library.py +++ b/joy/library.py @@ -34,6 +34,8 @@ from .utils.brutal_hackery import rename_code_object from .utils import generated_library as genlib from .utils.types import ( + compose, + ef, stack_effect, AnyJoyType, BooleanJoyType, @@ -42,6 +44,7 @@ from .utils.types import ( FloatJoyType, IntJoyType, TextJoyType, + _functions, ) @@ -55,6 +58,17 @@ I = i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = map(IntJoyType, _R) T = t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 = map(TextJoyType, _R) +sec0 = stack_effect(t1)() +sec1 = stack_effect(s0, i1)(s1) +sec2 = stack_effect(s0, i1)(a1) +sec_binary_cmp = stack_effect(n1, n2)(b1) +sec_binary_ints = stack_effect(i1, i2)(i3) +sec_binary_logic = stack_effect(b1, b2)(b3) +sec_binary_math = stack_effect(n1, n2)(n3) +sec_unary_logic = stack_effect(a1)(b1) +sec_unary_math = stack_effect(n1)(n2) + + _dictionary = {} @@ -74,6 +88,8 @@ ALIASES = ( ('and', ['&']), ('bool', ['truthy']), ('mul', ['*']), + ('floordiv', ['/floor', '//']), + ('floor', ['round']), ('truediv', ['/']), ('mod', ['%', 'rem', 'remainder', 'modulus']), ('eq', ['=']), @@ -111,6 +127,58 @@ def add_aliases(D, A): D[alias] = F +def yin_functions(): + ''' + Return a dict of named stack effects. + + "Yin" functions are those that only rearrange items in stacks and + can be defined completely by their stack effects. This means they + can be auto-compiled. + ''' + cons = ef(a1, s0)((a1, s0)) + ccons = compose(cons, cons) + dup = ef(a1)(a1, a1) + dupd = ef(a2, a1)(a2, a2, a1) + dupdd = ef(a3, a2, a1)(a3, a3, a2, a1) + first = ef((a1, s1),)(a1,) + over = ef(a2, a1)(a2, a1, a2) + pop = ef(a1)() + popd = ef(a2, a1,)(a1) + popdd = ef(a3, a2, a1,)(a2, a1,) + popop = ef(a2, a1,)() + popopd = ef(a3, a2, a1,)(a1) + popopdd = ef(a4, a3, a2, a1,)(a2, a1) + rest = ef((a1, s0),)(s0,) + rolldown = ef(a1, a2, a3)(a2, a3, a1) + rollup = ef(a1, a2, a3)(a3, a1, a2) + rrest = compose(rest, rest) + second = compose(rest, first) + stack = s0, (s0, s0) + swaack = (s1, s0), (s0, s1) + swap = ef(a1, a2)(a2, a1) + swons = compose(swap, cons) + third = compose(rest, second) + tuck = ef(a2, a1)(a1, a2, a1) + uncons = ef((a1, s0),)(a1, s0) + unswons = compose(uncons, swap) + stuncons = compose(stack, uncons) + stununcons = compose(stack, uncons, uncons) + unit = ef(a1)((a1, ())) + + first_two = compose(uncons, uncons, pop) + fourth = compose(rest, third) + + _Tree_add_Ee = compose(pop, swap, rolldown, rrest, ccons) + _Tree_get_E = compose(popop, second) + _Tree_delete_clear_stuff = compose(rollup, popop, rest) + _Tree_delete_R0 = compose(over, first, swap, dup) + + return { + name.rstrip('_'): stack_effect + for name, stack_effect in locals().iteritems() + } + + definitions = ('''\ of == swap at product == 1 swap [*] step @@ -289,32 +357,40 @@ def _text_to_defs(text): return (line.strip() for line in text.splitlines() if '==' in line) + +## eh = compose(dup, bool_) +## sqr = compose(dup, mul) +## of = compose(swap, at) + + # # Functions # # Load the auto-generated primitives into the dictionary. +_functions.update(yin_functions()) for name, primitive in getmembers(genlib, isfunction): inscribe(SimpleFunctionWrapper(primitive)) + @inscribe +@sec0 @FunctionWrapper -@stack_effect(t1)() def inscribe_(stack, expression, dictionary): - ''' - Create a new Joy function definition in the Joy dictionary. A - definition is given as a string with a name followed by a double - equal sign then one or more Joy functions, the body. for example: + ''' + Create a new Joy function definition in the Joy dictionary. A + definition is given as a string with a name followed by a double + equal sign then one or more Joy functions, the body. for example: - sqr == dup mul + sqr == dup mul - If you want the definition to persist over restarts, enter it into - the definitions.txt resource. - ''' - definition, stack = stack - DefinitionWrapper.add_def(definition, dictionary) - return stack, expression, dictionary + If you want the definition to persist over restarts, enter it into + the definitions.txt resource. + ''' + definition, stack = stack + DefinitionWrapper.add_def(definition, dictionary) + return stack, expression, dictionary @inscribe @@ -327,6 +403,7 @@ def parse(stack): @inscribe +@sec2 @SimpleFunctionWrapper def getitem(stack): ''' @@ -348,6 +425,7 @@ def getitem(stack): @inscribe +@sec1 @SimpleFunctionWrapper def drop(stack): ''' @@ -375,6 +453,7 @@ def drop(stack): @inscribe +@sec1 @SimpleFunctionWrapper def take(stack): ''' @@ -512,6 +591,7 @@ def sort_(S): return list_to_stack(sorted(iter_stack(tos))), stack +_functions['clear'] = s0, s1 @inscribe @SimpleFunctionWrapper def clear(stack): @@ -1319,32 +1399,39 @@ def cmp_(stack, expression, dictionary): for F in ( - BinaryBuiltinWrapper(operator.add), - BinaryBuiltinWrapper(operator.and_), - BinaryBuiltinWrapper(operator.div), - BinaryBuiltinWrapper(operator.eq), - BinaryBuiltinWrapper(operator.floordiv), - BinaryBuiltinWrapper(operator.ge), - BinaryBuiltinWrapper(operator.gt), - BinaryBuiltinWrapper(operator.le), - BinaryBuiltinWrapper(operator.lshift), - BinaryBuiltinWrapper(operator.lt), - BinaryBuiltinWrapper(operator.mod), - BinaryBuiltinWrapper(operator.mul), - BinaryBuiltinWrapper(operator.ne), - BinaryBuiltinWrapper(operator.or_), - BinaryBuiltinWrapper(operator.pow), - BinaryBuiltinWrapper(operator.rshift), - BinaryBuiltinWrapper(operator.sub), - BinaryBuiltinWrapper(operator.truediv), - BinaryBuiltinWrapper(operator.xor), - - UnaryBuiltinWrapper(abs), - UnaryBuiltinWrapper(bool), - UnaryBuiltinWrapper(floor), - UnaryBuiltinWrapper(operator.neg), - UnaryBuiltinWrapper(operator.not_), - UnaryBuiltinWrapper(sqrt), + + #divmod_ = pm = __(n2, n1), __(n4, n3) + + sec_binary_cmp(BinaryBuiltinWrapper(operator.eq)), + sec_binary_cmp(BinaryBuiltinWrapper(operator.ge)), + sec_binary_cmp(BinaryBuiltinWrapper(operator.gt)), + sec_binary_cmp(BinaryBuiltinWrapper(operator.le)), + sec_binary_cmp(BinaryBuiltinWrapper(operator.lt)), + sec_binary_cmp(BinaryBuiltinWrapper(operator.ne)), + + sec_binary_ints(BinaryBuiltinWrapper(operator.xor)), + sec_binary_ints(BinaryBuiltinWrapper(operator.lshift)), + sec_binary_ints(BinaryBuiltinWrapper(operator.rshift)), + + sec_binary_logic(BinaryBuiltinWrapper(operator.and_)), + sec_binary_logic(BinaryBuiltinWrapper(operator.or_)), + + sec_binary_math(BinaryBuiltinWrapper(operator.add)), + sec_binary_math(BinaryBuiltinWrapper(operator.floordiv)), + sec_binary_math(BinaryBuiltinWrapper(operator.mod)), + sec_binary_math(BinaryBuiltinWrapper(operator.mul)), + sec_binary_math(BinaryBuiltinWrapper(operator.pow)), + sec_binary_math(BinaryBuiltinWrapper(operator.sub)), + sec_binary_math(BinaryBuiltinWrapper(operator.truediv)), + + sec_unary_logic(UnaryBuiltinWrapper(bool)), + sec_unary_logic(UnaryBuiltinWrapper(operator.not_)), + + sec_unary_math(UnaryBuiltinWrapper(abs)), + sec_unary_math(UnaryBuiltinWrapper(operator.neg)), + sec_unary_math(UnaryBuiltinWrapper(sqrt)), + + stack_effect(n1)(i1)(UnaryBuiltinWrapper(floor)), ): inscribe(F) del F # Otherwise Sphinx autodoc will pick it up. diff --git a/joy/utils/types.py b/joy/utils/types.py index a24f519..224003a 100644 --- a/joy/utils/types.py +++ b/joy/utils/types.py @@ -275,108 +275,41 @@ def compile_(name, f, doc=None): return %s''' % (name, doc, i, o) +_functions = {} + + def __(*seq): stack = StackJoyType(23) for item in seq: stack = item, stack return stack - def stack_effect(*inputs): - def _stack_effect(*outputs): - pass + def _apply_to(function): + i, o = _functions[function.name] = __(*inputs), __(*outputs) + function.__doc__ += ( + '\nStack effect::\n\n ' # '::' for Sphinx docs. + + doc_from_stack_effect(i, o) + ) + return function + return _apply_to + return _stack_effect -return _stack_effect +def ef(*inputs): + def _ef(*outputs): + return __(*inputs), __(*outputs) + return _ef -_R = range(10) -A = a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = map(AnyJoyType, _R) -B = b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = map(BooleanJoyType, _R) -N = n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = map(NumberJoyType, _R) -S = s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = map(StackJoyType, _R) -F = f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = map(FloatJoyType, _R) -I = i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = map(IntJoyType, _R) -T = t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 = map(TextJoyType, _R) - - -def defs(): - ''' - Return a dict of named stack effects. - ''' - at = __(s0, i1), __(a1) - drop = take = __(s0, i1), __(s1) - cons = __(a1, s0), __((a1, s0),) - ccons = compose(cons, cons) - dup = __(a1,), __(a1, a1) - dupd = __(a2, a1), __(a2, a2, a1) - dupdd = __(a3, a2, a1), __(a3, a3, a2, a1) - first = __((a1, s1),), __(a1,) - inscribe = __(t1), __() - over = __(a2, a1), __(a2, a1, a2) - pop = __(a1), __() - popd = __(a2, a1,), __(a1) - popdd = __(a3, a2, a1,), __(a2, a1,) - popop = __(a2, a1,), __() - popopd = __(a3, a2, a1,), __(a1) - popopdd = __(a4, a3, a2, a1,), __(a2, a1) - rest = __((a1, s0),), __(s0,) - rolldown = __(a1, a2, a3), __(a2, a3, a1) - rollup = __(a1, a2, a3), __(a3, a1, a2) - rrest = compose(rest, rest) - second = compose(rest, first) - stack = s0, (s0, s0) - swaack = (s1, s0), (s0, s1) - swap = __(a1, a2), __(a2, a1) - swons = compose(swap, cons) - third = compose(rest, second) - tuck = __(a2, a1), __(a1, a2, a1) - uncons = __((a1, s0),), __(a1, s0) - unswons = compose(uncons, swap) - stuncons = compose(stack, uncons) - stununcons = compose(stack, uncons, uncons) - unit = __(a1), __((a1, ())) - of = compose(swap, at) - clear = s0, s1 - - eq = ge = gt = le = lt = ne = __(n1, n2), __(b1) - - and_ = __(b1, b2), __(b3) - bool_ = not_ = __(a1), __(b1) - eh = compose(dup, bool_) - - add = div = floordiv = mod = mul = pow_ = sub = truediv = \ - lshift = rshift = __(n1, n2), __(n3,) - sqr = compose(dup, mul) - abs_ = floor = sqrt = succ = pred = neg = __(n1,), __(n2,) - divmod_ = pm = __(n2, n1), __(n4, n3) - - first_two = compose(uncons, uncons, pop) - fourth = compose(rest, third) - of = compose(swap, at) - - _Tree_add_Ee = compose(pop, swap, rolldown, rrest, ccons) - _Tree_get_E = compose(popop, second) - _Tree_delete_clear_stuff = compose(rollup, popop, rest) - _Tree_delete_R0 = compose(over, first, swap, dup) - - return { - name.rstrip('_'): stack_effect - for name, stack_effect in locals().iteritems() - } - - -DEFS = defs() - - -def show(): +def show(DEFS): for name, stack_effect_comment in sorted(DEFS.iteritems()): t = ' *'[compilable(stack_effect_comment)] print name, '=', doc_from_stack_effect(*stack_effect_comment), t -def generate_library_code(f=None): +def generate_library_code(DEFS, f=None): if f is None: import sys f = sys.stdout @@ -389,5 +322,5 @@ def generate_library_code(f=None): print >> f -if __name__ == '__main__': - show() +##if __name__ == '__main__': +## show()