def for_loop(context, count, index_name, expression): value = Value(None, 'None') eval_index_name = index_name.evaluate(context).value for i in range(count.evaluate(context).value): if eval_index_name: context.set(context, eval_index_name, Value(i, 'Number')) value = expression.evaluate(context) return value
def get_allowed_argument_types(self): if not self.node: return frozenset([Value("Any", "Type")]) elif not self.path: return frozenset() tip = self.path[-1] if tip.arg and not tip.param.repeatable: return frozenset() return frozenset([Value(tip.param.element_type, "Type")])
def append_argument(tree, arg): # this modifies the argument, which is not ideal try: (success, skips_remaining) = tree.value.append_argument(arg.value, 0) if success: return tree else: return Value('Could not append argument %s to %s' % ( arg.value.element.name, tree.value.element.name), 'EvaluationError') except EvaluationError as e: return Value(e, 'EvaluationError')
def evaluate(context, node): if node.element_type == 'EvaluationError': return node try: value = node.value.evaluate(context) if isinstance(value, Value): return value else: return Value(value, node.value.element.element_type) except EvaluationError as e: return Value(e, 'EvaluationError')
def run_repl(): repl = Context() first_prompt = ": " second_prompt = "| " lines = [] index = 0 while True: if not lines: prompt = str(index) prompt = "$" + prompt line = input(prompt + first_prompt) if line: if line == "Exit": return else: lines.append(line) else: prompt = " " * len(str(index)) + " " line = input(prompt + second_prompt) if line: lines.append(line) else: print("\033[A \033[A") try: ast = ParseNode.parse("\n".join(lines)) value = ast.evaluate(repl) name = Value("$" + str(index), "ValueName") print(name.value + " = " + value.__str__()) index += 1 repl.set(name, value) except EvaluationError as e: print("EvaluationError: " + e.__str__()) lines = []
def merge_values(context): nonlocal values # what to do about name conflicts? for name in context.values: # do we want elements that a parameter of type would accept? if context.values[name].element_type == element_type.value: values.add(Value(name, 'ValueName')) return False # navigate to full depth
def merge_definitions(context): nonlocal definitions # what to do about name conflicts? for name in context.definitions: # do we want elements that a parameter of type would accept? if context.definitions[name].element_type == element_type.value: # what is the type here? symbol name? definitions.add(Value(name, 'ValueName')) return False # navigate to full depth
def for_each_loop(context, values, index_name, expression): eval_index_name = index_name.evaluate(context).value eval_values = [] for value in values: eval_values.append(value.evaluate(context)) ret = Value(None, 'None') for value in eval_values: context.set(context, eval_index_name, value) ret = value.evaluate(context) return ret
def evaluate(self, context, unevaluated_arguments): if self.handling == Handling.LAZY: args = unevaluated_arguments else: args = self.evaluate_arguments(context, unevaluated_arguments) if self.handling == Handling.UNWRAP: args = Builtin.unwrap_values(args) if self.use_context == Handling.CONTEXTUAL: result = self.func(context, *args) else: result = self.func(*args) if isinstance(result, Value): return result else: return Value(result, self.element_type)
def run_compose(compose_lines=None): # todo: can we split cursor and active_tab into their own context separate from the cursor evaluation? repl = Context() ParseNode.parse("LoadModule composition").evaluate(repl) prompt = ": " cursor = None active_tab = None tabs = frozenset() force_update_active_tab = False line_index = 0 def maybe_print(s): if compose_lines is None or len(compose_lines) < line_index: print(s) value = None while True: print(chr(27) + "[2J" + chr(27) + "[H", end="") if cursor is None: cursor = repl.parse_eval("Set cursor Cursor.Make Quote Sequence") active_tab = Value("Any", "Type") repl.set(Value("active_tab", "ValueName"), active_tab) tabs = repl.parse_eval("AllTypes") tabs = [t.value for t in tabs.value] options = repl.parse_eval("Cursor.GetAllowedArgumentTypes Get cursor") if not options.value: # None or empty frozenset maybe_print("No open parameter at cursor") elements = [] value_names = [] else: maybe_print("Allowed Types: " + " ".join([o.value for o in options.value])) if force_update_active_tab or ( active_tab != "Any" and options.value is not None and active_tab not in options.value and Value('Any', 'Type') not in options.value): active_tab = next(iter(options.value)) repl.set(Value("active_tab", "ValueName"), active_tab) force_update_active_tab = False elements = repl.parse_eval("DefinitionsOfType Get active_tab") elements = [e.value for e in elements.value] value_names = repl.parse_eval("ValuesOfType Get active_tab") value_names = [n.value for n in value_names.value] maybe_print("### Meta ###") maybe_print(" Exit Eval Skip Tab <type>") maybe_print("### Tabs ###") maybe_print(" " + " ".join(tabs)) if options.value: if elements: maybe_print("### Elements (%s) ###" % active_tab.value) maybe_print(" " + " ".join(elements)) if value_names: maybe_print("### Values (%s) ###" % active_tab.value) maybe_print(" " + " ".join(value_names)) maybe_print("### Command ###") maybe_print(cursor.value) try: if compose_lines is not None and len(compose_lines) > line_index: line = compose_lines[line_index] line_index += 1 else: line = input(prompt) if line == "Exit": break if line == "Eval": try: value = repl.parse_eval( "Evaluate Cursor.GetEvalNode Get cursor") maybe_print(value) cursor = None force_update_active_tab = True except EvaluationError as e: maybe_print(e) elif line == "Skip": success = cursor.value.increment_path_to_open_parameter( force_one=True) force_update_active_tab = True if not success: maybe_print("Cursor could not skip") elif line.startswith("Tab "): tab = Value(line.split()[-1], "Type") if options.value is None or (tab not in options.value and Value("Any", "Type") not in options.value): maybe_print("Cursor does not allow values of type %s" % tab.value) elif repl.is_known_type(tab.value): active_tab = tab repl.set(Value("active_tab", "ValueName"), active_tab) else: maybe_print("Uknown Type " + tab.value + " has no elements") elif line in elements: repl.parse_eval("Cursor.InsertArgument Get cursor Quote " + line) force_update_active_tab = True elif line in value_names: repl.parse_eval("Cursor.InsertArgument Get cursor Quote Get " + line) force_update_active_tab = True elif active_tab.value == "ValueName": repl.parse_eval("Cursor.InsertArgument Get cursor Quote " + line) force_update_active_tab = True elif active_tab.value == "Type": if repl.is_known_type(line): repl.parse_eval("Cursor.InsertArgument Get cursor Quote " + line) force_update_active_tab = True else: maybe_print("Uknown Type " + line) elif active_tab.value == "Number": repl.parse_eval("Cursor.InsertArgument Get cursor Quote " + line) force_update_active_tab = True except EvaluationError as e: print("EvaluationError: " + e.__str__()) if compose_lines is not None and line_index == len(compose_lines): return value
def quote(node): return Value(node, 'EvalNode')
def logical_any(context, expressions): for expr in expressions: if expr.evaluate(context).value: return Value(True, 'Boolean') return Value(False, 'Boolean')
def logical_not(value): return Value(not value.value, 'Boolean')
def while_loop(context, condition, expression): value = Value(None, 'None') while condition.evaluate(context).value: value = expression.evaluate(context) return value
def merge_types(context): nonlocal types for t in context.types: types.add(Value(t, 'Type')) return False # navigate to full depth