Switch to functions from classes for FunctionWrappers.

This commit is contained in:
Simon Forman 2018-04-21 15:20:46 -07:00
parent a682537597
commit f7e78b6050
1 changed files with 33 additions and 36 deletions

View File

@ -24,6 +24,7 @@ returns a dictionary of Joy functions suitable for use with the joy()
function.
'''
from inspect import getdoc
from functools import wraps
import operator, math
from .parser import text_to_expression, Symbol
@ -152,61 +153,52 @@ step_zero == 0 roll> step
)
class FunctionWrapper(object):
'''
Allow functions to have a nice repr().
At some point it's likely this class and its subclasses would gain
machinery to support type checking and inference.
'''
def __init__(self, f):
self.f = f
self.name = f.__name__.rstrip('_') # Don't shadow builtins.
self.__doc__ = f.__doc__ or str(f)
def __call__(self, stack, expression, dictionary):
'''
Functions in general receive and return all three.
'''
return self.f(stack, expression, dictionary)
def __repr__(self):
return self.name
def FunctionWrapper(f):
'''Set name attribute.'''
if not f.__doc__:
raise ValueError('Function %s must have doc string.' % f.__name__)
f.name = f.__name__.rstrip('_') # Don't shadow builtins.
return f
class SimpleFunctionWrapper(FunctionWrapper):
def SimpleFunctionWrapper(f):
'''
Wrap functions that take and return just a stack.
'''
def __call__(self, stack, expression, dictionary):
return self.f(stack), expression, dictionary
@FunctionWrapper
@wraps(f)
def inner(stack, expression, dictionary):
return f(stack), expression, dictionary
return inner
class BinaryBuiltinWrapper(FunctionWrapper):
def BinaryBuiltinWrapper(f):
'''
Wrap functions that take two arguments and return a single result.
'''
def __call__(self, stack, expression, dictionary):
@FunctionWrapper
@wraps(f)
def inner(stack, expression, dictionary):
(a, (b, stack)) = stack
result = self.f(b, a)
result = f(b, a)
return (result, stack), expression, dictionary
return inner
class UnaryBuiltinWrapper(FunctionWrapper):
def UnaryBuiltinWrapper(f):
'''
Wrap functions that take one argument and return a single result.
'''
def __call__(self, stack, expression, dictionary):
@FunctionWrapper
@wraps(f)
def inner(stack, expression, dictionary):
(a, stack) = stack
result = self.f(a)
result = f(a)
return (result, stack), expression, dictionary
return inner
class DefinitionWrapper(FunctionWrapper):
class DefinitionWrapper(object):
'''
Provide implementation of defined functions, and some helper methods.
'''
@ -692,12 +684,15 @@ floor.__doc__ = math.floor.__doc__
@inscribe
@SimpleFunctionWrapper
def divmod_(S):
'''
divmod(x, y) -> (quotient, remainder)
Return the tuple (x//y, x%y). Invariant: div*y + mod == x.
'''
a, (b, stack) = S
d, m = divmod(a, b)
return d, (m, stack)
divmod_.__doc__ = divmod.__doc__
def sqrt(a):
'''
@ -738,12 +733,14 @@ def rolldown(S):
@inscribe
@SimpleFunctionWrapper
def id_(stack):
'''The identity function.'''
return stack
@inscribe
@SimpleFunctionWrapper
def void(stack):
'''True if the form on TOS is void otherwise False.'''
form, stack = stack
return _void(form), stack