diff options
Diffstat (limited to 'gerbonara/gerber/aperture_macros/expression.py')
-rw-r--r-- | gerbonara/gerber/aperture_macros/expression.py | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/gerbonara/gerber/aperture_macros/expression.py b/gerbonara/gerber/aperture_macros/expression.py deleted file mode 100644 index 0cf055a..0000000 --- a/gerbonara/gerber/aperture_macros/expression.py +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright 2021 Jan Götte <gerbonara@jaseg.de> - -import operator -import re -import ast - -from ..utils import MM, Inch, MILLIMETERS_PER_INCH - - -def expr(obj): - return obj if isinstance(obj, Expression) else ConstantExpression(obj) - - -class Expression: - def optimized(self, variable_binding={}): - return self - - def __str__(self): - return f'<{self.to_gerber()}>' - - def __repr__(self): - return f'<E {self.to_gerber()}>' - - def converted(self, unit): - return self - - def calculate(self, variable_binding={}, unit=None): - expr = self.converted(unit).optimized(variable_binding) - if not isinstance(expr, ConstantExpression): - raise IndexError(f'Cannot fully resolve expression due to unresolved variables: {expr} with variables {variable_binding}') - return expr.value - - def __add__(self, other): - return OperatorExpression(operator.add, self, expr(other)).optimized() - - def __radd__(self, other): - return expr(other) + self - - def __sub__(self, other): - return OperatorExpression(operator.sub, self, expr(other)).optimized() - - def __rsub__(self, other): - return expr(other) - self - - def __mul__(self, other): - return OperatorExpression(operator.mul, self, expr(other)).optimized() - - def __rmul__(self, other): - return expr(other) * self - - def __truediv__(self, other): - return OperatorExpression(operator.truediv, self, expr(other)).optimized() - - def __rtruediv__(self, other): - return expr(other) / self - - def __neg__(self): - return 0 - self - - def __pos__(self): - return self - -class UnitExpression(Expression): - def __init__(self, expr, unit): - self._expr = expr - self.unit = unit - - def to_gerber(self, unit=None): - return self.converted(unit).optimized().to_gerber() - - def __eq__(self, other): - return type(other) == type(self) and \ - self.unit == other.unit and\ - self._expr == other._expr - - def __str__(self): - return f'<{self._expr.to_gerber()} {self.unit}>' - - def __repr__(self): - return f'<UE {self._expr.to_gerber()} {self.unit}>' - - def converted(self, unit): - if self.unit is None or unit is None or self.unit == unit: - return self._expr - - elif MM == unit: - return self._expr * MILLIMETERS_PER_INCH - - elif Inch == unit: - return self._expr / MILLIMETERS_PER_INCH - - else: - raise ValueError(f'invalid unit {unit}, must be "inch" or "mm".') - - def __add__(self, other): - if not isinstance(other, UnitExpression): - raise ValueError('Unit mismatch: Can only add/subtract UnitExpression from UnitExpression, not scalar.') - - if self.unit == other.unit or self.unit is None or other.unit is None: - return UnitExpression(self._expr + other._expr, self.unit) - - if other.unit == 'mm': # -> and self.unit == 'inch' - return UnitExpression(self._expr + (other._expr / MILLIMETERS_PER_INCH), self.unit) - else: # other.unit == 'inch' and self.unit == 'mm' - return UnitExpression(self._expr + (other._expr * MILLIMETERS_PER_INCH), self.unit) - - def __radd__(self, other): - # left hand side cannot have been an UnitExpression or __radd__ would not have been called - raise ValueError('Unit mismatch: Can only add/subtract UnitExpression from UnitExpression, not scalar.') - - def __sub__(self, other): - return (self + (-other)).optimize() - - def __rsub__(self, other): - # see __radd__ above - raise ValueError('Unit mismatch: Can only add/subtract UnitExpression from UnitExpression, not scalar.') - - def __mul__(self, other): - return UnitExpression(self._expr * other, self.unit) - - def __rmul__(self, other): - return UnitExpression(other * self._expr, self.unit) - - def __truediv__(self, other): - return UnitExpression(self._expr / other, self.unit) - - def __rtruediv__(self, other): - return UnitExpression(other / self._expr, self.unit) - - def __neg__(self): - return UnitExpression(-self._expr, self.unit) - - def __pos__(self): - return self - - -class ConstantExpression(Expression): - def __init__(self, value): - self.value = value - - def __float__(self): - return float(self.value) - - def __eq__(self, other): - return type(self) == type(other) and self.value == other.value - - def to_gerber(self, _unit=None): - return f'{self.value:.6f}'.rstrip('0').rstrip('.') - - -class VariableExpression(Expression): - def __init__(self, number): - self.number = number - - def optimized(self, variable_binding={}): - if self.number in variable_binding: - return ConstantExpression(variable_binding[self.number]) - return self - - def __eq__(self, other): - return type(self) == type(other) and \ - self.number == other.number - - def to_gerber(self, _unit=None): - return f'${self.number}' - - -class OperatorExpression(Expression): - def __init__(self, op, l, r): - self.op = op - self.l = ConstantExpression(l) if isinstance(l, (int, float)) else l - self.r = ConstantExpression(r) if isinstance(r, (int, float)) else r - - def __eq__(self, other): - return type(self) == type(other) and \ - self.op == other.op and \ - self.l == other.l and \ - self.r == other.r - - def optimized(self, variable_binding={}): - l = self.l.optimized(variable_binding) - r = self.r.optimized(variable_binding) - - if self.op in (operator.add, operator.mul): - if id(r) < id(l): - l, r = r, l - - if isinstance(l, ConstantExpression) and isinstance(r, ConstantExpression): - return ConstantExpression(self.op(float(l), float(r))) - - return OperatorExpression(self.op, l, r) - - def to_gerber(self, unit=None): - lval = self.l.to_gerber(unit) - rval = self.r.to_gerber(unit) - - if isinstance(self.l, OperatorExpression): - lval = f'({lval})' - if isinstance(self.r, OperatorExpression): - rval = f'({rval})' - - op = {operator.add: '+', - operator.sub: '-', - operator.mul: 'X', - operator.truediv: '/'} [self.op] - - return f'{lval}{op}{rval}' - |