view arith/eval.py @ 0:e85652916197 draft

Initial commit
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 17 May 2019 22:28:13 +0200
parents
children
line wrap: on
line source

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May 17 21:55:20 2019

@author: lbo
"""

from tree import Product, Term, Power, Value, Symbol

class NotBoundError(Exception):

    def __init__(self, symbol):
        super(Exception, self).__init__('Symbol {} not bound!'.format(symbol))


class Bindings:
    _bindings = {}

    def __init__(self, bind={}):
        self._bindings = bind

    def set(self, sym, val):
        self._bindings[sym] = val

    def unset(self, sym):
        self._bindings.pop(sym)

    def get(self, sym):
        sym = sym.c
        if sym in self._bindings:
            return self._bindings[sym]
        raise NotBoundError(sym)

def evaluate(node, bindings=None):
    bindings = Bindings() if not bindings else bindings
    assert isinstance(node, Symbol) or isinstance(node, Value) or (node.left and node.right)
    if isinstance(node, Symbol):
        return bindings.get(node)
    elif isinstance(node, Value):
        return node.v
    elif isinstance(node, Product):
        if node.typ == Product.PROD:
            return evaluate(node.left, bindings) * evaluate(node.right, bindings)
        elif node.typ == Product.QUOT:
            right = evaluate(node.right, bindings)
            assert right != 0
            return evaluate(node.left, bindings) / right
    elif isinstance(node, Term):
        if node.typ == Term.PLUS:
            return evaluate(node.left, bindings) + evaluate(node.right, bindings)
        elif node.typ == Term.MINUS:
            return evaluate(node.left, bindings) - evaluate(node.right, bindings)
    elif isinstance(node, Power):
        if node.typ == Power.POWER:
            return evaluate(node.left, bindings) ** evaluate(node.right, bindings)