"""Implementation of openmath basic objects""" from omexceptions import UnsupportedOperationError from omexceptions import OutOfScopeError, EvaluationFailedError from exceptions import NotImplementedError from copy import copy from xml.sax.xmlreader import AttributesImpl as attr from itertools import izip import base64 raiseException=True #TODO: OMOBJ, OME, OMATTR #from cd import * try: import psyco def optimize(f): psyco.bind(f) except: def optimize(f): pass class OMCD(object): def __init__(self, name, base="http://www.openmath.org/cd"): self.name = name self.base = base def __eq__(self, other): try: return (self.name == other.name) and (self.base == other.base) except: return False def __hash__(self): return hash((self.name,self.base)) class OMCDImplementation(object): def __init__(self, cd): object.__setattr__(self,"cd",cd) def support(self,symbol): setattr(self,symbol,OMS(symbol, self.cd)) def __setattr__(self, name,value): "FIXME: implements this later safer against name conflicts" if callable(value) and (not isinstance(value, ImplementedSymbol)): object.__setattr__(self, name, ImplementedSymbol(OMS(name,self.cd), value)) else: object.__setattr__(self,name,value) class OMS(object): def __init__(self,name,cd = None): #super(OMSymbol,self).__init__() self.cd = cd self.name = name def __eq__(self, other): try: return bool(other.name == self.name and self.cd == other.cd) except: return False def __str__(self): return "OMS(" + self.name + ", " + self.cd.name + ")" def __repr__(self): return str(self) def __hash__(self):# return hash((self.name,self.cd.__hash__())) def evaluate(self,context): return context.evaluateSymbol(self) XMLtag="OMS" def getXMLAttributes(self): #return [XMLAttribute("name", self.name),\ # XMLAttribute("cdbase", self.cd.base),\ # XMLAttribute("cd", self.cd.name)] return {"name":self.name, "cdbase":self.cd.base, "cd": self.cd.name} def setXMLAttributes(self): raise UnsupportedOperationError class ImplementedSymbol(OMS): def __init__(self,symbol, func): super(ImplementedSymbol,self).__init__(symbol.name, symbol.cd) self.implementation = func def __str__(self): return "ImplementedOMS("+self.name+", " + self.cd.name +")" def __call__(self, context, *args): try: erg=self.implementation(*args) except KeyError: raise EvaluationFailedError return context.package(erg) cdFns1 = OMCD("fns1") lambdasym = OMS("lambda", cdFns1) def islambda(sym): "return True, iff sym is the lambda binder" return lambdasym == sym class OMBIND(object): """hopefully fixed possible problems: reevaluation writes new scope, if it isn't meant so, references do not work correctly because of scopes solve this by first evaluation to bounded OMBinding""" def __init__(self, binder, variables, block): #super(OMBinding, self).__init__() self.block = block self.binder = binder self.variables = variables self.bounded = False def evaluate(self, context): "evaluate the OMbinding in context" assert islambda(self.binder) if not self.bounded: mycopy = copy(self) mycopy.scope = context.scopeFromCurrentScope() mycopy.bounded = True return mycopy else: return self def bind(self, args): "bind arguments to values" #print args, self.variables assert len(args) == len(self.variables) varBindings = dict(izip([i.name for i in self.variables], args)) self.scope.push(varBindings) def unbind(self): "unbind the arguments" self.scope.pop() def calcErg(self, context): "do the actual computation" return context.evaluateInScope(self.block, self.scope) def __call__(self, context, *args): assert self.bounded self.bind(args) erg = self.calcErg(context) self.unbind() #print "__call__ erg is", erg return erg XMLtag = "OMBIND" def getChildren(self): "get children for (XML) representation" return [self.binder]+self.variables+[self.block] class OMOBJ(object): def __init__(self, children): #super(OMObject, self).__init__() self.children = children def getChildren(self): return self.__children def setChildren(self ,children): self.__children=children XMLtag = "OMOBJ" def evaluate(self, context): return OMObject([context.evaluate(c) for c in self.children]) class OMV(object): def __init__(self,name): #super(OMVar, self).__init__() self.name = name def evaluate(self, context): try: return context[self.name] except OutOfScopeError: return self def __str__(self): return "OMV(" + self.name +")" def __repr__(self): return str(self) XMLtag="OMV" class OMA(object): def __init__(self, func, args): #super(OMApply, self).__init__() self.func = func self.args = args def evaluate(self, context): efunc = context.evaluate(self.func) eargs = [context.evaluate(a) for a in self.args] if callable(efunc): if raiseException: return context.apply(efunc,eargs) else: try: return context.apply(efunc, eargs) except EvaluationFailedError, NotImplementedError: return OMA(efunc, eargs) #return self else: #print efunc return OMA(efunc, eargs) def __str__ (self): return "OMA"+"("+str(self.func)+str(self.args) def __repr__ (self): return "OMA"+"("+str(self.func)+str(self.args) XMLtag="OMA" # class OMB(SimpleValue): # def __init__(self, value): # #super(OMByteArray,self).__init__(value) # self.value=value # def __str__(self): # return "OMByteArray(" + repr(self.value) + ")" # def parse(self, value): # return value # XMLtag = "OMB" # def getBody(self): # return base64.encodestring(self.value) class OMRef(object): def __init__(self, ref): self.ref=ref def evaluate(self, context): return context.evaluate(self.ref) def XMLEncode(self, context): "FIXME: maybe it should also be able to encode as reference" return context.XMLEncodeObject(self.ref) class OMATTR(object): def __init__(self, *args): #super(OMAttribution,self).__init__() self.attr = list(args[:-1]) self.value = args[-1] def getChildren(self): #print type(self.attr) #print type(self.value) return self.attr+[self.value] def evaluate(self, context): value = copy(self.value) value.attributes = copy(value.attributes) for attribute in self.attr: attribute_evaluated=context.evaluate(attribute) value.attributes[attribute_evaluated.key] = attribute_evaluated.value return value XMLtag = "OMATTR" if __name__ == '__main__': print OMV("x") print OMA(OMV("x"),[OMV("y"),1]) #from binding import OMBinding, lambdasym context["x"] = 1 x = OMV("x") y = OMV("y") print context.evaluate(x) print context.evaluateVariable(x) print context.evaluate(y) import cd.arith1 as arith1 context.addCDImplementation(arith1.implementation) print OMA(arith1.implementation.plus, [1,2]) print context.evaluate(OMA(arith1.implementation.plus, [1,2])) application = OMA(OMS("plus", arith1.content), [1,2]) print context.evaluate(application) firstArg=OMBinding(lambdasym,[OMVar("x"), OMVar("y")], OMVar("x")) #print context.evaluate(firstArg) application = OMApply(firstArg, [x,y]) print context.evaluate(application) application = OMApply(firstArg, [y,x]) print context.evaluate(application) #print type(context.lookupImplementation(arith1.plussym)) #application=OMApply(arith1.plussym,[x]) #application=OMApply(arith1.plussym,[x,x]) application = OMApply(OMS("plus", arith1.content), [x, x]) print context.evaluate(application) application = OMApply(OMS("plus", arith1.content), [x, x, x]) print context.evaluate(application) i = OMint(22482489) print i.body print i.XMLEncode(context) print context.XMLEncodeObject(OMS("plus", arith1.content)) #i.body="dshj" #optimize(OMObjectBase.__init__) #optimize(OMObjectBase.XMLPreEncode) #optimize(SimpleValue.__init__) #optimize(OMint.__init__) #optimize(OMApply.__init__)