Source code for contracts.library.arithmetic

from functools import reduce

from ..interface import RValue
from ..syntax import isnumber, W


[docs]class Binary(RValue): operations = { '+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '^': lambda x, y: x ** y, } precedence = { '+': 0, '-': 0, '*': 1, '^': 2, } def __init__(self, exprs, glyph, where=None): assert glyph in Binary.operations for e in exprs: assert isinstance(e, RValue) self.where = where self.exprs = exprs self.glyph = glyph self.precedence = Binary.precedence[glyph]
[docs] def eval(self, context): # @ReservedAssignment vals = [] for expr in self.exprs: val = expr.eval(context) if not isnumber(val): raise ValueError('I can only do math with numbers, not %r.' % val.__class__.__name__) vals.append(val) operation = Binary.operations[self.glyph] return reduce(operation, vals)
def __repr__(self): s = 'Binary(%r,%r)' % (self.exprs, self.glyph) return s def __str__(self): def convert(x): if isinstance(x, Binary) and x.precedence < self.precedence: return '(%s)' % x else: return '%s' % x s = self.glyph.join(convert(x) for x in self.exprs) return s
[docs] @staticmethod def parse_action(s, loc, tokens): where = W(s, loc) l = list(tokens[0]) exprs = [l.pop(0)] while l: glyph = l.pop(0) assert isinstance(glyph, str) expr = l.pop(0) assert isinstance(expr, RValue) exprs.append(expr) # noinspection PyUnboundLocalVariable return Binary(exprs, glyph, where=where)
[docs]class Unary(RValue): operations = { '-': lambda x: (-x), } def __init__(self, glyph, expr, where=None): assert glyph in Unary.operations assert isinstance(expr, RValue) self.where = where self.expr = expr self.glyph = glyph
[docs] def eval(self, context): # @ReservedAssignment val = self.expr.eval(context) if not isnumber(val): raise ValueError('I can only do math with numbers, not with %r.' % val.__class__.__name__) operation = Unary.operations[self.glyph] return operation(val)
def __repr__(self): s = 'Unary(%r,%r)' % (self.glyph, self.expr) return s def __str__(self): # XXX: precedence return '%s%s' % (self.glyph, self.expr)
[docs] @staticmethod def parse_action(s, loc, tokens): where = W(s, loc) glyph = tokens[0][0] assert isinstance(glyph, str) expr = tokens[0][1] assert isinstance(expr, RValue) return Unary(glyph, expr, where=where)