Source code for pycropml.transpiler.api_transform

# coding: utf8
##########################################

# inspired from pseudo-python

from __future__ import absolute_import
from __future__ import print_function
from pycropml.transpiler.builtin_typed_api import builtin_type_check
from pycropml.transpiler.errors import PseudoCythonTypeCheckError
from pycropml.transpiler.pseudo_tree import  Node
from datetime import datetime

[docs] class Standard: ''' Standard classes should respond to expand and to return valid nodes on expand ''' pass
[docs] class StandardCall(Standard): ''' converts to a standard call of the given namespace and function ''' def __init__(self, namespace, function, expander=None): self.namespace = namespace self.function = function self.expander = expander
[docs] def expand(self, args): if not self.expander: q = builtin_type_check(self.namespace, self.function, None, args)[-1] return {'type': 'standard_call', 'namespace': self.namespace, 'function': self.function, 'args': args, 'pseudo_type': q} else: return self.expander(self.namespace, self.function, args)
[docs] class StandardCallAttrib(Standard): ''' converts to a standard call of the given namespace and function ''' def __init__(self, namespace, function, expander=None): self.namespace = namespace self.function = function self.expander = expander
[docs] def expand(self, args=[]): if not self.expander: q = builtin_type_check(self.namespace, self.function, None, args=[])[-1] return {'type': 'standard_call', 'namespace': self.namespace, 'function': self.function, 'args': [], 'pseudo_type': q} else: return self.expander(self.namespace, self.function, args)
[docs] class StandardMethodCall(Standard): ''' converts to a method call of the same class ''' def __init__(self, type, message, default=None, expander=None): self.type = type self.message = message self.default = default self.expander = expander
[docs] def expand(self, args): if self.default and len(args) - 1 in self.default: args += self.default[len(args) - 1] if not self.expander: q = builtin_type_check(self.type, self.message, args[0], args[1:])[-1] return {'type': 'standard_method_call', 'receiver': args[0], 'message': self.message, 'args': args[1:], 'pseudo_type': q} else: return self.expander(self.type, self.message, args)
[docs] class StandardSwapper(Standard): def __init__(self, type, message): self.type = type self.message = message
[docs] def expand(self, args): if len(args) < 2: raise PseudoCythonTypeCheckError('%s expects more args' % self.message) q = builtin_type_check(self.type, self.message, args[1], [args[0]])[-1] return {'type': 'standard_method_call', 'receiver': args[1], 'args': [args[0]], 'message': self.message, 'pseudo_type': q}
[docs] def int_expander(type, message, args): return len_expander(type, message, args)
[docs] def float_expander(type, message, args): return len_expander(type, message, args)
[docs] def len_expander(type, message, args): receiver_type = args[0]['pseudo_type'] if isinstance(receiver_type, list): a = receiver_type[0] else: a = receiver_type # print(a, message, args[0], args[1:]) # input(0) if message == 'len' and 'special' in args[0]: # len(sys.argv) return {'type': 'standard_call', 'namespace': 'system', 'function': 'arg_count', 'args': [], 'pseudo_type': 'Int'} else: q = builtin_type_check(a, message, args[0], args[1:]) if a =="str" and message =="float" and args[0].get("value")==b"nan": return {"type":'notAnumber', 'value' : 'nan', 'pseudo_type':'float'} else: return {'type': 'standard_method_call', 'receiver':args[0], 'args': [], 'message': message, 'pseudo_type': q[-1]}
[docs] def min_expander(type, message, args): if len(args)==1: return {'type': 'standard_call', 'namespace': 'system', 'function': 'min', 'args': args, 'pseudo_type': args[0]["pseudo_type"][1]} else: for i in range(len(args)-1): if args[i]["pseudo_type"]!=args[i+1]["pseudo_type"]: pseudo = "float" break else: pseudo = args[i]["pseudo_type"] return {'type': 'standard_call', 'namespace': 'system', 'function': 'min', 'args': args, 'pseudo_type': pseudo}
[docs] def max_expander(type, message, args): if len(args)==1: return {'type': 'standard_call', 'namespace': 'system', 'function': 'max', 'args': args, 'pseudo_type': args[0]["pseudo_type"][1]} else: for i in range(len(args)-1): if args[i]["pseudo_type"]!=args[i+1]["pseudo_type"]: pseudo = "float" break else: pseudo = args[i]["pseudo_type"] return {'type': 'standard_call', 'namespace': 'system', 'function': 'max', 'args': args, 'pseudo_type':pseudo}
[docs] def abs_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function': 'abs', 'args': args, 'pseudo_type': args[0]["pseudo_type"]}
[docs] def list_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function': 'list', 'args': args, 'pseudo_type': ['list',args[0]["pseudo_type"][-1]]}
[docs] def range_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function': 'range', 'args': args, 'pseudo_type': ['list', args[0]["pseudo_type"]]}
[docs] def datetime_expander(type, message, args): if len(args)==3: a = datetime(eval(args[0]["value"]),eval(args[1]["value"]),eval(args[2]["value"]) ) elif len(args)==4: a = datetime(eval(args[0]["value"]),eval(args[1]["value"]),eval(args[2]["value"]),eval(args[3]["value"]) ) elif len(args)==5: a = datetime(eval(args[0]["value"]),eval(args[1]["value"]),eval(args[2]["value"]),eval(args[3]["value"]),eval(args[4]["value"]) ) elif len(args)==6: a = datetime(eval(args[0]["value"]),eval(args[1]["value"]),eval(args[2]["value"]),eval(args[3]["value"]),eval(args[4]["value"]),eval(args[5]["value"]) ) else: raise PseudoCythonTypeCheckError('datetime expects 3, 4, 5 or 6 args') return {'type': 'standard_call', 'namespace': 'datetime', 'function': 'datetime', 'args': args, 'pseudo_type': 'datetime'}
[docs] def array_expander(type, message, args): if args[-1]["type"]=="list": res = {'type': 'array', 'elements': args[-1]["elements"], 'dim': len(args[-1]["elements"]), 'pseudo_type': ['array',args[-1]["pseudo_type"][-1]]} else: res = {'type': 'array', 'elements': args[-1], 'pseudo_type': ['array',args[-1]["pseudo_type"][-1]]} return res
[docs] def copy_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function':'copy', 'args': args[0], 'pseudo_type': args[0]["pseudo_type"]}
[docs] def pow_expander(type, message, args): x1 = args[0]["pseudo_type"] x2 = args[1]["pseudo_type"] if x1=="int" and x2=="int" : if "value" in dir(args[1]): val = -(int(args[1]["value"]["value"])) if args[1]["type"]=="unary_op" else args[1]["value"] if int(val)<0: q="float" else: q="int" else: if args[1]["pseudo_type"]=="int": q = "int" else: q="float" else: q="float" return {'type': 'standard_call', 'namespace': 'system', 'function': 'pow', 'args': args, 'pseudo_type':q}
[docs] def modulo_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function': 'modulo', 'args': args, 'pseudo_type':"int"}
[docs] def round_expander(type, message, args): return {'type': 'standard_call', 'namespace': 'system', 'function': 'round', 'args': args, 'pseudo_type':"float"}
[docs] def integr_expander(type, message, args): if isinstance(args[0]["pseudo_type"], list) and isinstance(args[1]["pseudo_type"] ,list): if args[1]["pseudo_type"][1] != args[0]["pseudo_type"][1]: raise PseudoCythonTypeCheckError('wrong usage of %s integr') if isinstance(args[0]["pseudo_type"], list) and not isinstance(args[1]["pseudo_type"] ,list): if args[1]["pseudo_type"] != args[0]["pseudo_type"][1]: raise PseudoCythonTypeCheckError('wrong usage of %s integr') return {'type': 'standard_call', 'namespace': 'system', 'function': 'integr', 'args': args, 'pseudo_type':args[0]["pseudo_type"]}
FUNCTION_API = { 'global': { 'input': StandardCall('io', 'read'), 'print': StandardCall('io', 'display'), "round": StandardCall('global', 'round',expander=round_expander ), 'str': StandardCall('global', 'to_string'), 'min': StandardCall('global', 'min', expander=min_expander), 'max': StandardCall('global', 'max', expander=max_expander), 'abs': StandardCall('global', 'abs', expander = abs_expander), 'len': StandardMethodCall('list', 'len', expander=len_expander), 'int': StandardMethodCall('float', 'int', expander=int_expander), 'float': StandardMethodCall('int', 'float', expander=float_expander), 'pow': StandardCall('global', 'pow', expander = pow_expander), 'modulo': StandardCall('global', 'modulo', expander = modulo_expander), 'copy': StandardCall('global', 'copy', expander = copy_expander), 'integr': StandardCall('global', 'integr', expander = integr_expander), 'array': StandardCall('global', 'integr', expander = array_expander), "range": StandardCall('global', 'range', expander = range_expander), "list": StandardCall('global', 'list', expander = list_expander) }, 'math': { 'log': { 1: StandardCall('math', 'ln'), 2: StandardCall('math', 'log') }, 'sin': StandardCall('math', 'sin'), 'cos': StandardCall('math', 'cos'), 'tan': StandardCall('math', 'tan'), 'acos': StandardCall('math', 'acos'), 'asin': StandardCall('math', 'asin'), 'atan': StandardCall('math', 'atan'), 'sqrt': StandardCall('math', 'sqrt'), 'ceil': StandardCall('math', 'ceil'), 'exp': StandardCall('math', 'exp'), 'floor': StandardCall('math', 'floor'), 'isnan': StandardCall('math', 'isnan') }, 'datetime':{ 'datetime': StandardMethodCall('datetime', 'datetime', expander = datetime_expander ) }, 'array':{ 'array': StandardMethodCall('numpy', 'array', expander = array_expander ) } } METHOD_API = { 'str': { 'split': StandardMethodCall('str', 'split'), 'join': StandardSwapper('str', 'join'), 'upper': StandardMethodCall('str', 'upper'), 'lower': StandardMethodCall('str', 'lower'), 'title': StandardMethodCall('str', 'title'), 'center': StandardMethodCall('str', 'center', default={1: [{'type': 'str', 'value': ' ', 'pseudo_type': 'str'}]}), 'index': StandardMethodCall('str', 'index'), 'find': { 1: StandardMethodCall('str', 'find'), 2: StandardMethodCall('str', 'find_from') } }, 'list': { 'append': StandardMethodCall('list', 'append'), 'pop': StandardMethodCall('list', 'pop'), 'insert': { 1: StandardMethodCall('list', 'insert'), 2: StandardMethodCall('list', 'insert_at') }, 'remove': StandardMethodCall('list', 'remove'), 'extend': StandardMethodCall('list', 'extend'), 'map': StandardMethodCall('list', 'map'), 'filter': StandardMethodCall('list', 'filter'), 'copy': StandardMethodCall('list', 'copy'), 'index': StandardMethodCall('list', 'index'), 'allocate': StandardMethodCall('list', 'allocate') }, 'dict': { 'keys': StandardMethodCall('dict', 'keys'), 'values': StandardMethodCall('dict', 'values'), 'get': StandardMethodCall('dict', 'get'), '[]': StandardMethodCall('dict', 'getitem'), '[]=': StandardMethodCall('dict', 'setitem') }, 'datetime': { 'year': StandardCallAttrib('datetime', 'year'), 'month': StandardCallAttrib('datetime', 'month'), 'day': StandardCallAttrib('datetime', 'day'), 'hour': StandardCallAttrib('datetime', 'hour'), 'minute': StandardCallAttrib('datetime', 'minute'), 'second': StandardCallAttrib('datetime', 'second') }, 'array': { 'append': StandardMethodCall('array', 'append'), 'allocate': StandardMethodCall('array', 'allocate') }, 'tuple': { } } CONSTANT_API = { 'math':{ 'pi':{'type':'constant', 'library':'math', 'pseudo_type':'float', 'name':'pi'} } } OPERATOR_API = { 'list': { '+': 'concat', '*': 'repeat' }, 'str': { '+': 'concat', '*': 'repeat', '%': 'c_format' } }