Package spade :: Module logic :: Class Expr
[hide private]
[frames] | no frames]

Class Expr

source code

A symbolic mathematical expression.  We use this class for logical
expressions, and for terms within logical expressions. In general, an
Expr has an op (operator) and a list of args.  The op can be:
  Null-ary (no args) op:
    A number, representing the number itself.  (e.g. Expr(42) => 42)
    A symbol, representing a variable or constant (e.g. Expr('F') => F)
  Unary (1 arg) op:
    '~', '-', representing NOT, negation (e.g. Expr('~', Expr('P')) => ~P)
  Binary (2 arg) op:
    '>>', '<<', representing forward and backward implication
    '+', '-', '*', '/', '**', representing arithmetic operators
    '<', '>', '>=', '<=', representing comparison operators
    '<=>', '^', representing logical equality and XOR
  N-ary (0 or more args) op:
    '&', '|', representing conjunction and disjunction
    A symbol, representing a function term or FOL proposition

Exprs can be constructed with operator overloading: if x and y are Exprs,
then so are x + y and x & y, etc.  Also, if F and x are Exprs, then so is 
F(x); it works by overloading the __call__ method of the Expr F.  Note 
that in the Expr that is created by F(x), the op is the str 'F', not the 
Expr F.   See http://www.python.org/doc/current/ref/specialnames.html 
to learn more about operator overloading in Python.

WARNING: x == y and x != y are NOT Exprs.  The reason is that we want
to write code that tests 'if x == y:' and if x == y were the same
as Expr('==', x, y), then the result would always be true; not what a
programmer would expect.  But we still need to form Exprs representing
equalities and disequalities.  We concentrate on logical equality (or
equivalence) and logical disequality (or XOR).  You have 3 choices:
    (1) Expr('<=>', x, y) and Expr('^', x, y)
        Note that ^ is bitwose XOR in Python (and Java and C++)
    (2) expr('x <=> y') and expr('x =/= y').  
        See the doc string for the function expr.
    (3) (x % y) and (x ^ y).
        It is very ugly to have (x % y) mean (x <=> y), but we need
        SOME operator to make (2) work, and this seems the best choice.

WARNING: if x is an Expr, then so is x + 1, because the int 1 gets
coerced to an Expr by the constructor.  But 1 + x is an error, because
1 doesn't know how to add an Expr.  (Adding an __radd__ method to Expr
wouldn't help, because int.__add__ is still called first.) Therefore,
you should use Expr(1) + x instead, or ONE + x, or expr('1 + x').

Instance Methods [hide private]
 
__init__(self, op, *args)
Op is a string or number; args are Exprs (or are coerced to Exprs).
source code
 
__call__(self, *args)
Self must be a symbol with no args, such as Expr('F').
source code
 
__repr__(self)
Show something like 'P' or 'P(x, y)', or '~P' or '(P | Q | R)'
source code
 
__eq__(self, other)
x and y are equal iff their ops and args are equal.
source code
 
__hash__(self)
Need a hash method so Exprs can live in dicts.
source code
 
__lt__(self, other) source code
 
__le__(self, other) source code
 
__ge__(self, other) source code
 
__gt__(self, other) source code
 
__add__(self, other) source code
 
__sub__(self, other) source code
 
__and__(self, other) source code
 
__div__(self, other) source code
 
__truediv__(self, other) source code
 
__invert__(self) source code
 
__lshift__(self, other) source code
 
__rshift__(self, other) source code
 
__mul__(self, other) source code
 
__neg__(self) source code
 
__or__(self, other) source code
 
__pow__(self, other) source code
 
__xor__(self, other) source code
 
__mod__(self, other) source code
Method Details [hide private]

__call__(self, *args)
(Call operator)

source code 

Self must be a symbol with no args, such as Expr('F'). Create a new Expr with 'F' as op and the args as arguments.