From 9febca7da6a730b3b3ca3a54129a9f88e5c44d14 Mon Sep 17 00:00:00 2001 From: opiopan Date: Thu, 21 Mar 2019 22:00:32 +0900 Subject: initial commit --- gerberex/am_expression.py | 183 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 gerberex/am_expression.py (limited to 'gerberex/am_expression.py') diff --git a/gerberex/am_expression.py b/gerberex/am_expression.py new file mode 100644 index 0000000..7aa95c8 --- /dev/null +++ b/gerberex/am_expression.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright 2019 Hiroshi Murayama + +from gerber.utils import * +from gerber.am_eval import OpCode +from gerber.am_statements import * + +class AMExpression(object): + CONSTANT = 1 + VARIABLE = 2 + OPERATOR = 3 + + def __init__(self, kind): + self.kind = kind + + @property + def value(self): + return self + + def optimize(self): + pass + + def to_inch(self): + return AMOperatorExpression(AMOperatorExpression.DIV, self, + AMConstantExpression(MILLIMETERS_PER_INCH)) + + def to_metric(self): + return AMOperatorExpression(AMOperatorExpression.MUL, self, + AMConstantExpression(MILLIMETERS_PER_INCH)) + + def to_gerber(self, settings=None): + pass + + def to_instructions(self): + pass + +class AMConstantExpression(AMExpression): + def __init__(self, value): + super(AMConstantExpression, self).__init__(AMExpression.CONSTANT) + self._value = value + + @property + def value(self): + return self._value + + def optimize(self): + return self + + def to_gerber(self, settings=None): + return str(self._value) + + def to_instructions(self): + return [(OpCode.PUSH, self._value)] + +class AMVariableExpression(AMExpression): + def __init__(self, number): + super(AMVariableExpression, self).__init__(AMExpression.VARIABLE) + self.number = number + + def optimize(self): + return self + + def to_gerber(self, settings=None): + return '$%d' % self.number + + def to_instructions(self): + return (OpCode.LOAD, self.number) + +class AMOperatorExpression(AMExpression): + ADD = '+' + SUB = '-' + MUL = 'X' + DIV = '/' + + def __init__(self, op, lvalue, rvalue): + super(AMOperatorExpression, self).__init__(AMExpression.OPERATOR) + self.op = op + self.lvalue = lvalue + self.rvalue = rvalue + + def optimize(self): + self.lvalue = self.lvalue.optimize() + self.rvalue = self.rvalue.optimize() + + if isinstance(self.lvalue, AMConstantExpression) and isinstance(self.rvalue, AMConstantExpression): + lvalue = float(self.lvalue.value) + rvalue = float(self.rvalue.value) + value = lvalue + rvalue if self.op == self.ADD else \ + lvalue - rvalue if self.op == self.SUB else \ + lvalue * rvalue if self.op == self.MUL else \ + lvalue / rvalue if self.op == self.DIV else None + return AMConstantExpression(value) + elif self.op == self.ADD: + if self.rvalue.value == 0: + return self.lvalue + elif self.lvalue.value == 0: + return self.rvalue + elif self.op == self.SUB: + if self.rvalue.value == 0: + return self.lvalue + elif self.lvalue.value == 0 and isinstance(self.rvalue, AMConstantExpression): + return AMConstantExpression(-self.rvalue.value) + elif self.op == self.MUL: + if self.rvalue.value == 1: + return self.lvalue + elif self.lvalue.value == 1: + return self.rvalue + elif self.lvalue == 0 or self.rvalue == 0: + return AMConstantExpression(0) + elif self.op == self.DIV: + if self.rvalue.value == 1: + return self.lvalue + elif self.lvalue.value == 0: + return AMConstantExpression(0) + + return self + + def to_gerber(self, settings=None): + return '(%s)%s(%s)' % (self.lvalue.to_gerber(settings), self.op, self.rvalue.to_gerber(settings)) + + def to_instructions(self): + for i in self.lvalue.to_instructions(): + yield i + for i in self.rvalue.to_instructions(): + yield i + op = OpCode.ADD if self.op == self.ADD else\ + OpCode.SUB if self.op == self.SUB else\ + OpCode.MUL if self.op == self.MUL else\ + OpCode.DIV + yield (op, None) + +def eval_macro(instructions): + stack = [] + + def pop(): + return stack.pop() + + def push(op): + stack.append(op) + + def top(): + return stack[-1] + + def empty(): + return len(stack) == 0 + + for opcode, argument in instructions: + if opcode == OpCode.PUSH: + push(AMConstantExpression(argument)) + + elif opcode == OpCode.LOAD: + push(AMVariableExpression(argument)) + + elif opcode == OpCode.STORE: + yield (-argument, [pop()]) + + elif opcode == OpCode.ADD: + op1 = pop() + op2 = pop() + push(AMOperatorExpression(AMOperatorExpression.ADD, op2, op1)) + + elif opcode == OpCode.SUB: + op1 = pop() + op2 = pop() + push(AMOperatorExpression(AMOperatorExpression.SUB, op2, op1)) + + elif opcode == OpCode.MUL: + op1 = pop() + op2 = pop() + push(AMOperatorExpression(AMOperatorExpression.MUL, op2, op1)) + + elif opcode == OpCode.DIV: + op1 = pop() + op2 = pop() + push(AMOperatorExpression(AMOperatorExpression.DIV, op2, op1)) + + elif opcode == OpCode.PRIM: + yield (argument, stack) + stack = [] + + -- cgit From e3c59e39cf9bc64ce9d76c324b82956a65515f16 Mon Sep 17 00:00:00 2001 From: opiopan Date: Sun, 7 Apr 2019 22:22:33 +0900 Subject: expand test and fix many issues --- gerberex/am_expression.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'gerberex/am_expression.py') diff --git a/gerberex/am_expression.py b/gerberex/am_expression.py index 7aa95c8..b758df1 100644 --- a/gerberex/am_expression.py +++ b/gerberex/am_expression.py @@ -49,7 +49,7 @@ class AMConstantExpression(AMExpression): return self def to_gerber(self, settings=None): - return str(self._value) + return '%.6g' % self._value def to_instructions(self): return [(OpCode.PUSH, self._value)] @@ -179,5 +179,3 @@ def eval_macro(instructions): elif opcode == OpCode.PRIM: yield (argument, stack) stack = [] - - -- cgit From 0854d357587c96adb881255d0af6a7d40c15153c Mon Sep 17 00:00:00 2001 From: Marin Mikaƫl <41113988+MarinMikael@users.noreply.github.com> Date: Wed, 24 Jul 2019 01:24:41 +0900 Subject: Update am_expression.py String format to %f instead of %g. Scientific notation is supportd by Kicad and Ucamco's reference viewer, but causes artefacts on Altium and pcb-tools. --- gerberex/am_expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gerberex/am_expression.py') diff --git a/gerberex/am_expression.py b/gerberex/am_expression.py index b758df1..4bb1d78 100644 --- a/gerberex/am_expression.py +++ b/gerberex/am_expression.py @@ -49,7 +49,7 @@ class AMConstantExpression(AMExpression): return self def to_gerber(self, settings=None): - return '%.6g' % self._value + return '%.6f' % self._value def to_instructions(self): return [(OpCode.PUSH, self._value)] -- cgit From f8fe16708502e0588d9d0be42d097a933d6f12d3 Mon Sep 17 00:00:00 2001 From: Hiroshi Murayama Date: Sun, 18 Aug 2019 18:33:41 +0900 Subject: zero supressing in aperture macro definition --- gerberex/am_expression.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gerberex/am_expression.py') diff --git a/gerberex/am_expression.py b/gerberex/am_expression.py index 4bb1d78..5400130 100644 --- a/gerberex/am_expression.py +++ b/gerberex/am_expression.py @@ -49,7 +49,8 @@ class AMConstantExpression(AMExpression): return self def to_gerber(self, settings=None): - return '%.6f' % self._value + gerber = '%.6g' % self._value + return '%.6f' % self._value if 'e' in gerber else gerber def to_instructions(self): return [(OpCode.PUSH, self._value)] -- cgit From 3f9295b9d0c2142c46aa238836debdd472811899 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sat, 6 Feb 2021 09:38:22 +0100 Subject: Fix support for comments in aperture definitions --- gerberex/am_expression.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'gerberex/am_expression.py') diff --git a/gerberex/am_expression.py b/gerberex/am_expression.py index 5400130..f43ba2e 100644 --- a/gerberex/am_expression.py +++ b/gerberex/am_expression.py @@ -49,6 +49,8 @@ class AMConstantExpression(AMExpression): return self def to_gerber(self, settings=None): + if isinstance(self._value, str): + return self._value gerber = '%.6g' % self._value return '%.6f' % self._value if 'e' in gerber else gerber -- cgit