Source code for PySpice.Spice.Expression.Ast

####################################################################################################
#
# PySpice - A Spice Package for Python
# Copyright (C) 2017 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################

"""This module implements Abstract Syntactic Tree for Spice expressions.
"""

####################################################################################################

import logging
import os

####################################################################################################

_module_logger = logging.getLogger(__name__)

####################################################################################################

[docs]class StatementList: ############################################## def __init__(self, *statements): self._statements = list(statements) ############################################## def __nonzero__(self): return bool(self._statements) ############################################## def __iter__(self): return iter(self._statements) ##############################################
[docs] def add(self, statement): self._statements.append(statement)
############################################## def __str__(self): return os.linesep.join([str(statement) for statement in self])
####################################################################################################
[docs]class Program(StatementList): pass
####################################################################################################
[docs]class Variable: ############################################## def __init__(self, name): self._name = name ############################################## @property def name(self): return self._name ############################################## def __str__(self): return self._name
####################################################################################################
[docs]class Constant: ############################################## def __init__(self, value): self._value = value ############################################## def __str__(self): return str(self._value)
####################################################################################################
[docs]class IntConstant(Constant): ############################################## def __int__(self): return self._value
####################################################################################################
[docs]class FloatConstant(Constant): ############################################## def __float__(self): return self._value
####################################################################################################
[docs]class Expression: __number_of_operands__ = None ############################################## def __init__(self, *args, **kwargs): if (self.__number_of_operands__ is not None and len(args) != self.__number_of_operands__): raise ValueError("Wrong number of operands") self._operands = args ##############################################
[docs] def iter_on_operands(self): return iter(self._operands)
############################################## @property def operand(self): return self._operands[0] @property def operand1(self): return self._operands[0] @property def operand2(self): return self._operands[1] @property def operand3(self): return self._operands[2]
[docs]class UnaryExpression(Expression): __number_of_operands__ = 1
[docs]class BinaryExpression(Expression): __number_of_operands__ = 2
[docs]class TernaryExpression(Expression): __number_of_operands__ = 3
####################################################################################################
[docs]class OperatorMetaclass(type): """Metaclass to register operators""" __declaration_order__ = 0 __operators__ = [] __unary_operator_map__ = {} __binary_operator_map__ = {} ############################################## def __new__(meta, class_name, base_classes, attributes): cls = type.__new__(meta, class_name, base_classes, attributes) if cls.__operator__ is not None: meta.register_prefix(cls) return cls ##############################################
[docs] @classmethod def register_prefix(meta, cls): cls.__declaration_order__ = meta.__declaration_order__ meta.__declaration_order__ += 1 meta.__operators__.append(cls) if issubclass(cls, UnaryOperator): d = meta.__unary_operator_map__ elif issubclass(cls, BinaryOperator): d = meta.__binary_operator_map__ d[cls.__operator__] = cls
##############################################
[docs] @classmethod def operator_iter(cls): return iter(cls.__operators__)
##############################################
[docs] @classmethod def get_unary(cls, operator): return cls.__unary_operator_map__[operator]
##############################################
[docs] @classmethod def get_binary(cls, operator): return cls.__binary_operator_map__[operator]
####################################################################################################
[docs]class OperatorMixin(metaclass=OperatorMetaclass): __operator__ = None __declaration_order__ = 0
####################################################################################################
[docs]class UnaryOperator(UnaryExpression, OperatorMixin): def __str__(self): return ' '.join((self.__operator__, str(self.operand1)))
####################################################################################################
[docs]class BinaryOperator(BinaryExpression, OperatorMixin): def __str__(self): return ' '.join((str(self.operand1), self.__operator__, str(self.operand2)))
####################################################################################################
[docs]class Assignation(BinaryExpression): @property def variable(self): return self._operands[1] @property def value(self): return self._operands[0] def __str__(self): return ' '.join((str(self.destination), '=', str(self.value)))
####################################################################################################
[docs]class Negation(UnaryOperator): __operator__ = '-' __precedence__ = 1
[docs]class Not(UnaryOperator): __operator__ = '!' __precedence__ = 1
####################################################################################################
[docs]class power(BinaryOperator): __operator__ = '**' __precedence__ = 2
[docs]class Multiplication(BinaryOperator): __operator__ = '*' __precedence__ = 3
[docs]class Division(BinaryOperator): __operator__ = '/' __precedence__ = 3
[docs]class Modulo(BinaryOperator): __operator__ = '%' __precedence__ = 3
[docs]class IntegerDivision(BinaryOperator): __operator__ = '\\' __precedence__ = 3
[docs]class Addition(BinaryOperator): __operator__ = '+' __precedence__ = 4
[docs]class Subtraction(BinaryOperator): __operator__ = '-' __precedence__ = 4
####################################################################################################
[docs]class Equal(BinaryOperator): __operator__ = '==' __precedence__ = 5
[docs]class NotEqual(BinaryOperator): __operator__ = '!=' __precedence__ = 5
[docs]class LessEqual(BinaryOperator): __operator__ = '<='
[docs]class GreaterEqual(BinaryOperator): __operator__ = '>=' __precedence__ = 5
[docs]class Less(BinaryOperator): __operator__ = '<' __precedence__ = 5
[docs]class Greater(BinaryOperator): __operator__ = '>' __precedence__ = 5
####################################################################################################
[docs]class And(BinaryOperator): __operator__ = '&&' __precedence__ = 6
[docs]class Or(BinaryOperator): __operator__ = '||' __precedence__ = 7
####################################################################################################
[docs]class If: #(TernaryExpression) # c ? x : y __precedence__ = 8 ############################################## def __init__(self, condition, then_expression, else_expression): self._condition = condition self._then_expression = then_expression self._else_expression = else_expression ############################################## @property def condition(self): return self._condition ############################################## @property def then_expression(self): return self._then_expression ############################################## @property def else_expression(self): return self._else_expression ############################################## # def _str_compound_expression(self, expressions): # string = '(' + os.linesep # if expressions: # string += str(expressions) + os.linesep # string += ')' # return string ############################################## def __str__(self): return '{} ? {} : {}'.format(self._condition, self._then_expression, self._else_expression)
####################################################################################################
[docs]class Function(Expression): ############################################## def __init__(self, name, *args): super(Function, self).__init__(*args) self._name = name ############################################## @property def name(self): return self._name ############################################## def __str__(self): parameters = ', '.join([str(operand) for operand in self.iter_on_operands()]) return self._name + ' (' + parameters + ')'