+import ast
import functools
+import re
from . import islhelper
from .islhelper import mainctx, libisl, isl_set_basic_sets
+from .linexprs import Expression
__all__ = [
islset1 = libisl.isl_set_union(islset1, islset2)
return islset1
+ @classmethod
+ def _fromast(cls, node):
+ from .polyhedra import Polyhedron
+ if isinstance(node, ast.Module) and len(node.body) == 1:
+ return cls._fromast(node.body[0])
+ elif isinstance(node, ast.Expr):
+ return cls._fromast(node.value)
+ elif isinstance(node, ast.UnaryOp):
+ domain = cls._fromast(node.operand)
+ if isinstance(node.operand, ast.invert):
+ return Not(domain)
+ elif isinstance(node, ast.BinOp):
+ domain1 = cls._fromast(node.left)
+ domain2 = cls._fromast(node.right)
+ if isinstance(node.op, ast.BitAnd):
+ return And(domain1, domain2)
+ elif isinstance(node.op, ast.BitOr):
+ return Or(domain1, domain2)
+ elif isinstance(node, ast.Compare):
+ equalities = []
+ inequalities = []
+ left = Expression._fromast(node.left)
+ for i in range(len(node.ops)):
+ op = node.ops[i]
+ right = Expression._fromast(node.comparators[i])
+ if isinstance(op, ast.Lt):
+ inequalities.append(right - left - 1)
+ elif isinstance(op, ast.LtE):
+ inequalities.append(right - left)
+ elif isinstance(op, ast.Eq):
+ equalities.append(left - right)
+ elif isinstance(op, ast.GtE):
+ inequalities.append(left - right)
+ elif isinstance(op, ast.Gt):
+ inequalities.append(left - right - 1)
+ else:
+ break
+ left = right
+ else:
+ return Polyhedron(equalities, inequalities)
+ raise SyntaxError('invalid syntax')
+
+ _RE_BRACES = re.compile(r'^\{\s*|\s*\}$')
+ _RE_EQ = re.compile(r'([^<=>])=([^<=>])')
+ _RE_AND = re.compile(r'\band\b|,|&&|/\\|∧|∩')
+ _RE_OR = re.compile(r'\bor\b|;|\|\||\\/|∨|∪')
+ _RE_NOT = re.compile(r'\bnot\b|!|¬')
+ _RE_NUM_VAR = Expression._RE_NUM_VAR
+ _RE_OPERATORS = re.compile(r'(&|\||~)')
+
@classmethod
def fromstring(cls, string):
- raise NotImplementedError
+ # remove curly brackets
+ string = cls._RE_BRACES.sub(r'', string)
+ # replace '=' by '=='
+ string = cls._RE_EQ.sub(r'\1==\2', string)
+ # replace 'and', 'or', 'not'
+ string = cls._RE_AND.sub(r' & ', string)
+ string = cls._RE_OR.sub(r' | ', string)
+ string = cls._RE_NOT.sub(r' ~', string)
+ # add implicit multiplication operators, e.g. '5x' -> '5*x'
+ string = cls._RE_NUM_VAR.sub(r'\1*\2', string)
+ # add parentheses to force precedence
+ tokens = cls._RE_OPERATORS.split(string)
+ for i, token in enumerate(tokens):
+ if i % 2 == 0:
+ token = '({})'.format(token)
+ tokens[i] = token
+ string = ''.join(tokens)
+ tree = ast.parse(string, 'eval')
+ return cls._fromast(tree)
def __repr__(self):
assert len(self.polyhedra) >= 2