So fra, so good...
This commit is contained in:
parent
25b7871074
commit
c2dd7cca0a
161
joy/library.py
161
joy/library.py
|
|
@ -34,6 +34,8 @@ from .utils.brutal_hackery import rename_code_object
|
||||||
|
|
||||||
from .utils import generated_library as genlib
|
from .utils import generated_library as genlib
|
||||||
from .utils.types import (
|
from .utils.types import (
|
||||||
|
compose,
|
||||||
|
ef,
|
||||||
stack_effect,
|
stack_effect,
|
||||||
AnyJoyType,
|
AnyJoyType,
|
||||||
BooleanJoyType,
|
BooleanJoyType,
|
||||||
|
|
@ -42,6 +44,7 @@ from .utils.types import (
|
||||||
FloatJoyType,
|
FloatJoyType,
|
||||||
IntJoyType,
|
IntJoyType,
|
||||||
TextJoyType,
|
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)
|
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 = {}
|
_dictionary = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -74,6 +88,8 @@ ALIASES = (
|
||||||
('and', ['&']),
|
('and', ['&']),
|
||||||
('bool', ['truthy']),
|
('bool', ['truthy']),
|
||||||
('mul', ['*']),
|
('mul', ['*']),
|
||||||
|
('floordiv', ['/floor', '//']),
|
||||||
|
('floor', ['round']),
|
||||||
('truediv', ['/']),
|
('truediv', ['/']),
|
||||||
('mod', ['%', 'rem', 'remainder', 'modulus']),
|
('mod', ['%', 'rem', 'remainder', 'modulus']),
|
||||||
('eq', ['=']),
|
('eq', ['=']),
|
||||||
|
|
@ -111,6 +127,58 @@ def add_aliases(D, A):
|
||||||
D[alias] = F
|
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 = ('''\
|
definitions = ('''\
|
||||||
of == swap at
|
of == swap at
|
||||||
product == 1 swap [*] step
|
product == 1 swap [*] step
|
||||||
|
|
@ -289,32 +357,40 @@ def _text_to_defs(text):
|
||||||
return (line.strip() for line in text.splitlines() if '==' in line)
|
return (line.strip() for line in text.splitlines() if '==' in line)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## eh = compose(dup, bool_)
|
||||||
|
## sqr = compose(dup, mul)
|
||||||
|
## of = compose(swap, at)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Functions
|
# Functions
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
# Load the auto-generated primitives into the dictionary.
|
# Load the auto-generated primitives into the dictionary.
|
||||||
|
_functions.update(yin_functions())
|
||||||
for name, primitive in getmembers(genlib, isfunction):
|
for name, primitive in getmembers(genlib, isfunction):
|
||||||
inscribe(SimpleFunctionWrapper(primitive))
|
inscribe(SimpleFunctionWrapper(primitive))
|
||||||
|
|
||||||
|
|
||||||
@inscribe
|
@inscribe
|
||||||
|
@sec0
|
||||||
@FunctionWrapper
|
@FunctionWrapper
|
||||||
@stack_effect(t1)()
|
|
||||||
def inscribe_(stack, expression, dictionary):
|
def inscribe_(stack, expression, dictionary):
|
||||||
'''
|
'''
|
||||||
Create a new Joy function definition in the Joy dictionary. A
|
Create a new Joy function definition in the Joy dictionary. A
|
||||||
definition is given as a string with a name followed by a double
|
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:
|
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
|
If you want the definition to persist over restarts, enter it into
|
||||||
the definitions.txt resource.
|
the definitions.txt resource.
|
||||||
'''
|
'''
|
||||||
definition, stack = stack
|
definition, stack = stack
|
||||||
DefinitionWrapper.add_def(definition, dictionary)
|
DefinitionWrapper.add_def(definition, dictionary)
|
||||||
return stack, expression, dictionary
|
return stack, expression, dictionary
|
||||||
|
|
||||||
|
|
||||||
@inscribe
|
@inscribe
|
||||||
|
|
@ -327,6 +403,7 @@ def parse(stack):
|
||||||
|
|
||||||
|
|
||||||
@inscribe
|
@inscribe
|
||||||
|
@sec2
|
||||||
@SimpleFunctionWrapper
|
@SimpleFunctionWrapper
|
||||||
def getitem(stack):
|
def getitem(stack):
|
||||||
'''
|
'''
|
||||||
|
|
@ -348,6 +425,7 @@ def getitem(stack):
|
||||||
|
|
||||||
|
|
||||||
@inscribe
|
@inscribe
|
||||||
|
@sec1
|
||||||
@SimpleFunctionWrapper
|
@SimpleFunctionWrapper
|
||||||
def drop(stack):
|
def drop(stack):
|
||||||
'''
|
'''
|
||||||
|
|
@ -375,6 +453,7 @@ def drop(stack):
|
||||||
|
|
||||||
|
|
||||||
@inscribe
|
@inscribe
|
||||||
|
@sec1
|
||||||
@SimpleFunctionWrapper
|
@SimpleFunctionWrapper
|
||||||
def take(stack):
|
def take(stack):
|
||||||
'''
|
'''
|
||||||
|
|
@ -512,6 +591,7 @@ def sort_(S):
|
||||||
return list_to_stack(sorted(iter_stack(tos))), stack
|
return list_to_stack(sorted(iter_stack(tos))), stack
|
||||||
|
|
||||||
|
|
||||||
|
_functions['clear'] = s0, s1
|
||||||
@inscribe
|
@inscribe
|
||||||
@SimpleFunctionWrapper
|
@SimpleFunctionWrapper
|
||||||
def clear(stack):
|
def clear(stack):
|
||||||
|
|
@ -1319,32 +1399,39 @@ def cmp_(stack, expression, dictionary):
|
||||||
|
|
||||||
|
|
||||||
for F in (
|
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),
|
#divmod_ = pm = __(n2, n1), __(n4, n3)
|
||||||
UnaryBuiltinWrapper(bool),
|
|
||||||
UnaryBuiltinWrapper(floor),
|
sec_binary_cmp(BinaryBuiltinWrapper(operator.eq)),
|
||||||
UnaryBuiltinWrapper(operator.neg),
|
sec_binary_cmp(BinaryBuiltinWrapper(operator.ge)),
|
||||||
UnaryBuiltinWrapper(operator.not_),
|
sec_binary_cmp(BinaryBuiltinWrapper(operator.gt)),
|
||||||
UnaryBuiltinWrapper(sqrt),
|
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)
|
inscribe(F)
|
||||||
del F # Otherwise Sphinx autodoc will pick it up.
|
del F # Otherwise Sphinx autodoc will pick it up.
|
||||||
|
|
|
||||||
|
|
@ -275,108 +275,41 @@ def compile_(name, f, doc=None):
|
||||||
return %s''' % (name, doc, i, o)
|
return %s''' % (name, doc, i, o)
|
||||||
|
|
||||||
|
|
||||||
|
_functions = {}
|
||||||
|
|
||||||
|
|
||||||
def __(*seq):
|
def __(*seq):
|
||||||
stack = StackJoyType(23)
|
stack = StackJoyType(23)
|
||||||
for item in seq: stack = item, stack
|
for item in seq: stack = item, stack
|
||||||
return stack
|
return stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def stack_effect(*inputs):
|
def stack_effect(*inputs):
|
||||||
|
|
||||||
def _stack_effect(*outputs):
|
def _stack_effect(*outputs):
|
||||||
pass
|
def _apply_to(function):
|
||||||
|
i, o = _functions[function.name] = __(*inputs), __(*outputs)
|
||||||
return _stack_effect
|
function.__doc__ += (
|
||||||
|
'\nStack effect::\n\n ' # '::' for Sphinx docs.
|
||||||
|
+ doc_from_stack_effect(i, o)
|
||||||
|
)
|
||||||
|
return function
|
||||||
|
return _apply_to
|
||||||
|
return _stack_effect
|
||||||
|
|
||||||
|
|
||||||
|
def ef(*inputs):
|
||||||
_R = range(10)
|
def _ef(*outputs):
|
||||||
A = a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = map(AnyJoyType, _R)
|
return __(*inputs), __(*outputs)
|
||||||
B = b0, b1, b2, b3, b4, b5, b6, b7, b8, b9 = map(BooleanJoyType, _R)
|
return _ef
|
||||||
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():
|
def show(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():
|
|
||||||
for name, stack_effect_comment in sorted(DEFS.iteritems()):
|
for name, stack_effect_comment in sorted(DEFS.iteritems()):
|
||||||
t = ' *'[compilable(stack_effect_comment)]
|
t = ' *'[compilable(stack_effect_comment)]
|
||||||
print name, '=', doc_from_stack_effect(*stack_effect_comment), t
|
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:
|
if f is None:
|
||||||
import sys
|
import sys
|
||||||
f = sys.stdout
|
f = sys.stdout
|
||||||
|
|
@ -389,5 +322,5 @@ def generate_library_code(f=None):
|
||||||
print >> f
|
print >> f
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
##if __name__ == '__main__':
|
||||||
show()
|
## show()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue