def full(code, symlist = None): return complete(proton_parser.parse(lexer.tokenize(code)), symlist = symlist)
def evaluate(tree, symlist = None, comma_mode = tuple, looped = False, func = False): if not isinstance(tree, proton_parser.ASTNode): return tree setevalp(lambda k: complete(proton_parser.parse(lexer.tokenize(k)), symlist = symlist or default)[0]) symlist = symlist or default treetype = tree.type.split('/') tokentype = tree.token.type.replace(':', '/').split('/') if 'literal' in tokentype: return h(tree.token.content) elif 'identifier' in tokentype: def getter(): return None if tree.token.content not in symlist else symlist[tree.token.content] def setter(*args): if 'const' in symlist and tree.token.content in symlist['const']: raise RuntimeError('Cannot set constant value ' + tree.token.content) symlist[tree.token.content] = args[0] return Identifier(tree.token.content, getter, setter) elif 'const' in treetype: left = evaluate(tree.children[0], symlist, looped = looped, func = func) right = evaluate(tree.children[1], symlist, looped = looped, func = func) if not all(isinstance(node, Identifier) for node in walk(left)): left, right = right, left assign(left, right) if 'const' not in symlist: symlist['const'] = [] for node in walk(left): symlist['const'] += node.name elif 'comp' in treetype: result = [] for val in hardeval(tree.children[2], symlist, looped = looped, func = func): assign(evaluate(tree.children[1], symlist, looped = looped, func = func), val) if len(tree.children) < 4 or hardeval(tree.children[3], symlist, looped = looped, func = func): result.append(_hardeval(tree.children[0], symlist, looped = looped, func = func)) return result elif tree.token.content == 'unless': if hardeval(tree.children[1], symlist, looped = looped, func = func): return _evaluate(tree.children[2], symlist, looped = looped, func = func) else: return _evaluate(tree.children[0], symlist, looped = looped, func = func) elif tree.token.content == 'if': if hardeval(tree.children[0], symlist, looped = looped, func = func): return _evaluate(tree.children[1], symlist, looped = looped, func = func) elif len(tree.children) > 2: return _evaluate(tree.children[2], symlist, looped = looped, func = func) elif tree.token.content == 'while': if 'whileas' in treetype: sidelist = clone_scope(symlist) value = hardeval(tree.children[0], sidelist, looped = looped, func = func) result = None while value: assign(evaluate(tree.children[1], sidelist, looped = looped, func = func), value) result = evaluate(tree.children[2], sidelist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': break if result.name == 'continue': continue if result.name == 'return': return result value = hardeval(tree.children[0], sidelist, looped = looped, func = func) else: if len(tree.children) > 3: evaluate(tree.children[3]) del sidelist[evaluate(tree.children[1], looped = looped, func = func).name] merge(sidelist, symlist) return result else: result = None while hardeval(tree.children[0], symlist, looped = looped, func = func): result = _evaluate(tree.children[1], symlist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': break if result.name == 'continue': continue if result.name == 'return': return result else: if len(tree.children) > 2: evaluate(tree.children[2]) return result elif tree.token.content == 'repeat': if 'repeatinto' in treetype: sidelist = clone_scope(symlist) value = f(hardeval(tree.children[0], sidelist, looped = looped, func = func)) index = 0 result = None while index < value: assign(evaluate(tree.children[1], sidelist, looped = looped, func = func), index) result = evaluate(tree.children[2], sidelist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': break if result.name == 'continue': continue if result.name == 'return': return result index += 1 del sidelist[evaluate(tree.children[1], looped = looped, func = func).name] merge(sidelist, symlist) return result else: result = None value = f(hardeval(tree.children[0], symlist, looped = looped, func = func)) while value: result = _evaluate(tree.children[1], symlist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': break if result.name == 'continue': continue if result.name == 'return': return result value -= 1 return result elif tree.token.content == 'for': if 'foreach' in treetype: sidelist = clone_scope(symlist) result = None for val in hardeval(tree.children[1], sidelist, looped = looped, func = func): assign(evaluate(tree.children[0], sidelist, looped = looped, func = func), val) result = evaluate(tree.children[2], sidelist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': break if result.name == 'continue': continue if result.name == 'return': try: del sidelist[evaluate(tree.children[0], looped = looped, func = func).name] except: pass merge(sidelist, symlist) return result else: if len(tree.children) > 3: evaluate(tree.children[3]) try: del sidelist[evaluate(tree.children[0], looped = looped, func = func).name] except: pass merge(sidelist, symlist) return result else: sidelist = clone_scope(symlist) evaluate(tree.children[0], sidelist, looped = looped, func = func) result = None broken = False while not tree.children[1].children or hardeval(tree.children[1], sidelist, looped = looped, func = func): result = evaluate(tree.children[-1], sidelist, looped = True, func = func) if isinstance(result, Statement): if result.name == 'break': broken = True; break if result.name == 'continue': continue if result.name == 'return': try: del sidelist[evaluate(tree.children[0], looped = looped, func = func).name] except: pass merge(sidelist, symlist) return result if len(tree.children) >= 4: evaluate(tree.children[2], sidelist, looped = looped, func = func) if not broken: if len(tree.children) > 3: evaluate(tree.children[3]) merge(sidelist, symlist) return result elif tree.token.content == 'try': try: return _hardeval(tree.children[0], symlist, looped = looped, func = func) except Exception as e: sidelist = clone_scope(symlist) assign(evaluate(tree.children[1], sidelist), e, looped = looped, func = func) return evaluate(tree.children[2], sidelist, looped = looped, func = func) elif 'prebinopfunc' in treetype: def inner(*args, **kwargs): arguments = args[:1] + (evaluate(tree.children[0], symlist, looped = looped, func = func), symlist) value = infix_operators[tree.token.content](*arguments) return args[1:] and (value,) + args[1:] or value return inner elif 'postbinopfunc' in treetype: def inner(*args, **kwargs): arguments = (evaluate(tree.children[0], symlist, looped = looped, func = func),) + args[:1] + (symlist,) value = infix_operators[tree.token.content](*arguments) return args[1:] and (value,) + args[1:] or value return inner elif 'binary_operator' in tokentype or 'binary_RTL' in tokentype: if tree.token.content in infix_operators: return infix_operators[tree.token.content](tree.children[0], tree.children[1], symlist) else: raise NotImplementedError(tree.token.content + ' not yet implemented') elif 'prefix' in treetype: if tree.token.content in prefix_operators: return prefix_operators[tree.token.content](tree.children[0], symlist) else: raise NotImplementedError(tree.token.content + ' not yet implemented') elif 'postfix' in treetype: if tree.token.content in postfix_operators: return postfix_operators[tree.token.content](tree.children[0], symlist) else: raise NotImplementedError(tree.token.content + ' not yet implemented') elif tree.token.content == 'import': _import(tree.children[0], symlist) elif tree.token.content == 'include': __include__(tree.children[0], symlist, include) elif tree.token.content in ['exist', 'exists']: return exists(tree.children[0], symlist) elif tree.token.content in ['exist not', 'exists not']: return not exists(tree.children[0], symlist) elif 'break_statement' in treetype: if looped: return Statement('break') else: raise SyntaxError('break outside of loop') elif 'continue_statement' in treetype: if looped: return Statement('continue') else: raise SyntaxError('continue outside of loop') elif 'return_statement' in treetype: if func: return Statement('return', f(evaluate(tree.children[0], symlist))) else: raise SyntaxError('return outside of function') elif 'comma_expr' in treetype: result = comma_mode(evaluate(child, symlist, looped = looped, func = func) for child in tree.children) def flatten(array): result = comma_mode() if isinstance(array, (list, tuple, set)): for element in array: result += flatten(element) else: result = comma_mode([array]) return result if all(isinstance(f(element), Function) for element in flatten(result)): return getfunction(lambda *args, **kwargs: call(f(result), *args, **kwargs)) return result elif 'mapping' in treetype: return MapExpr(*[evaluate(child, symlist, looped = looped, func = func) for child in tree.children]) elif 'binopfunc' in treetype: def inner(*args, **kwargs): arguments = args[:2] + (symlist,) value = infix_operators[tree.token.content](*arguments) return args[2:] and (value,) + args[2:] or value return getfunction(inner, False) elif 'unopfunc' in treetype: def inner(*args, **kwargs): arguments = args[:2] + (symlist,) value = prefix_operators[tree.token.content](*arguments) return args[1:] and (value,) + args[1:] or value return getfunction(inner, False) elif 'bracket_expr' in treetype: if 'bracket' in treetype: return evaluate(tree.children[0], symlist, tuple, looped = looped, func = func) elif 'list' in treetype: if tree.children: result = evaluate(tree.children[0], symlist, list, looped = looped, func = func) innertype = tree.children[0].type.split('/') if 'comma_expr' not in innertype and 'comp' not in innertype: result = [result] maps = [isinstance(element, MapExpr) for element in result] if any(maps): if not all(maps): raise SyntaxError('Mixed mappings and non-mappings in list expression') return dict([(element.key, element.value) for element in result]) return result return [] elif 'codeblock' in treetype: sidelist = clone_scope(symlist) result = None for statement in tree.children: result = evaluate(statement, sidelist, looped = looped, func = True) if isinstance(result, Statement): merge(sidelist, symlist) if result.name == 'return': return result return result merge(sidelist, symlist) return result elif tree.token.type == 'ternary': return evaluate(tree.children[1], symlist, looped = looped, func = func) if hardeval(tree.children[0], symlist, looped = looped, func = func) else evaluate(tree.children[2], symlist, looped = looped, func = func) elif 'call' in treetype: if tree.children[0].token.content in ['eval']: return symlist['eval'](*([symlist] + [evaluate(child, symlist, looped = looped, func = func) for child in tree.children[1:]]))[0] else: args = [] for argument in tree.children[1:]: if argument.token.type == 'unifix_operator' and argument.token.content == '*': for arg in f(hardeval(argument.children[0], symlist, looped = looped, func = func)): args.append(arg) else: args.append(evaluate(argument, symlist, looped = looped, func = func)) func = f(evaluate(tree.children[0], symlist, looped = looped, func = func)) return call(func, *args) elif 'getitem' in treetype: if 'comma_expr' in tree.children[1].type.split('/') or 'slice' in tree.children[1].type.split('/'): ref = evaluate(tree.children[0], symlist, looped = looped, func = func) array = f(ref) index_list = indices(array, tree.children[1], symlist) def getter(): return get_indices(array, index_list) def setter(*args): set_indices(ref, array, index_list, args[0]) return Identifier('.getitem', getter, setter) else: ref = evaluate(tree.children[0], symlist, looped = looped, func = func) array = f(ref) index = f(hardeval(tree.children[1], symlist)) def getter(): return get_index(array, index) def setter(*args): set_index(ref, array, index, args[0]) return Identifier('.getitem', getter, setter) elif 'anonfunc' in treetype: def inner(*values): scope = clone_scope(symlist) try: assign_method_parameters(values, tree.children[0], scope) value = f(hardeval(tree.children[1], scope, func = True)) merge(scope, symlist) if isinstance(value, Statement): if value.name == 'return': return value.value raise SystemExit('huh?') return value except IndexError: if getfunction(inner).partial: def _inner(*args): return inner(*(values + args)) return _inner else: raise return getfunction(inner) elif 'del' in treetype: delete(evaluate(tree.children[0]), symlist) elif 'expression' in treetype: return evaluate(tree.children[0], symlist, looped = looped, func = func)
pass default["int"] = getfunction(sympy.Integer) default["float"] = getfunction(sympy.Rational) # TODO default["complex"] class proton_str(str): def __init__(self, obj): if isinstance(obj, dict): self = '[%s]' % ', '.join(sorted([ascii(key) + ' :> ' + ascii(obj[key]) for key in obj])) elif isinstance(obj, Function): self = proton_str(obj.function) else: self = str(obj) default['eval'] = getfunction(lambda s, x: complete(proton_parser.parse(lexer.tokenize(x)), s)) default['Function'] = Function default['str'] = proton_str default['type'] = lambda x: x['__type__'] if isinstance(x, dict) and '__type__' in x else type(x) default['class'] = make_type def merge(d1, d2): for x in d1: if x in d2 or x.startswith('!'): if d1[x] != d2[x]: d2[x] = d1[x] def indices(array, ref, symlist): reftype = ref.type.split('/') tokentype = ref.token.type.replace(':', '/').split('/') if 'comma_expr' in reftype:
def include(name): filename = ((path) and (path + '/')) + name + '.proton' with open(filename, 'r') as f: return complete(proton_parser.parse(lexer.tokenize(f.read())))[1]
# TODO default["complex"] class proton_str(str): def __init__(self, obj): if isinstance(obj, dict): self = '[%s]' % ', '.join( sorted([ascii(key) + ' :> ' + ascii(obj[key]) for key in obj])) elif isinstance(obj, Function): self = proton_str(obj.function) else: self = str(obj) default['eval'] = getfunction( lambda s, x: complete(proton_parser.parse(lexer.tokenize(x)), s)) default['Function'] = Function default['str'] = proton_str default['type'] = lambda x: x['__type__'] if isinstance( x, dict) and '__type__' in x else type(x) def merge(d1, d2): for x in d1: if x in d2 or x.startswith('!'): if d1[x] != d2[x]: d2[x] = d1[x] def indices(array, ref, symlist): reftype = ref.type.split('/')