def contribute(definitions): # let MakeBoxes contribute first builtins['System`MakeBoxes'].contribute(definitions) for name, item in builtins.items(): if name != 'System`MakeBoxes': item.contribute(definitions) # Is there another way to Unprotect these symbols at initialization? definitions.get_attributes('System`$PreRead').clear() definitions.get_attributes('System`$Pre').clear() definitions.get_attributes('System`$Post').clear() definitions.get_attributes('System`$PrePrint').clear() definitions.get_attributes('System`$SyntaxHandler').clear() from mathics.core.expression import ensure_context from mathics.core.parser import all_operator_names from mathics.core.definitions import Definition # All builtins are loaded. Create dummy builtin definitions for # any remaining operators that don't have them. This allows # operators like \[Cup] to behave correctly. for operator in all_operator_names: if not definitions.have_definition(ensure_context(operator)): op = ensure_context(operator) definitions.builtin[op] = Definition(name=op)
def has_form(self, heads, *leaf_counts): """ leaf_counts: (,): no leaves allowed (None,): no constraint on number of leaves (n, None): leaf count >= n (n1, n2, ...): leaf count in {n1, n2, ...} """ head_name = self.get_name() if isinstance(heads, (tuple, list, set)): if head_name not in [ensure_context(h) for h in heads]: return False else: if head_name != ensure_context(heads): return False if not leaf_counts: return False if leaf_counts and leaf_counts[0] is not None: count = len(self._leaves) if count not in leaf_counts: if ( len(leaf_counts) == 2 and leaf_counts[1] is None # noqa and count >= leaf_counts[0] ): return True else: return False return True
def __init__(self, *args, **kwargs): super(BinaryOperator, self).__init__(*args, **kwargs) name = self.get_name() # Prevent pattern matching symbols from gaining meaning here using # Verbatim name = 'Verbatim[%s]' % name # For compatibility, allow grouping symbols in builtins to be # specified without System`. self.grouping = ensure_context(self.grouping) if self.grouping in ('System`None', 'System`NonAssociative'): op_pattern = '%s[items__]' % name replace_items = 'items' else: op_pattern = '%s[x_, y_]' % name replace_items = 'x, y' if self.default_formats: operator = self.get_operator_display() formatted = 'MakeBoxes[Infix[{%s},"%s",%d,%s], form]' % ( replace_items, operator, self.precedence, self.grouping) formatted_output = 'MakeBoxes[Infix[{%s}," %s ",%d,%s], form]' % ( replace_items, operator, self.precedence, self.grouping) default_rules = { 'MakeBoxes[{0}, form:StandardForm|TraditionalForm]'.format(op_pattern): formatted, 'MakeBoxes[{0}, form:InputForm|OutputForm]'.format(op_pattern): formatted_output, } default_rules.update(self.rules) self.rules = default_rules
def tmp(args, op=flat_infix_op): op = ensure_context(op) if args[1].get_head_name() == op: args[1].leaves.append(args[3]) args[0] = args[1] else: args[0] = Expression(op, args[1], args[3])
def get_option(self, options, name, evaluation, pop=False): name = ensure_context(name) value = options.pop(name, None) if pop else options.get(name) if value is not None: return value.evaluate(evaluation) else: return None
def __init__(self, *args, **kwargs): super(BinaryOperator, self).__init__(*args, **kwargs) name = self.get_name() # Prevent pattern matching symbols from gaining meaning here using # Verbatim name = 'Verbatim[%s]' % name # For compatibility, allow grouping symbols in builtins to be # specified without System`. self.grouping = ensure_context(self.grouping) if self.grouping in ('System`None', 'System`NonAssociative'): op_pattern = '%s[items__]' % name replace_items = 'items' else: op_pattern = '%s[x_, y_]' % name replace_items = 'x, y' if self.default_formats: operator = self.get_operator_display() formatted = 'MakeBoxes[Infix[{%s},"%s",%d,%s], form]' % ( replace_items, operator, self.precedence, self.grouping) formatted_output = 'MakeBoxes[Infix[{%s}," %s ",%d,%s], form]' % ( replace_items, operator, self.precedence, self.grouping) default_rules = { 'MakeBoxes[{0}, form:StandardForm|TraditionalForm]'.format( op_pattern): formatted, 'MakeBoxes[{0}, form:InputForm|OutputForm]'.format( op_pattern): formatted_output, } default_rules.update(self.rules) self.rules = default_rules
def get_functions(self, prefix="apply", is_pymodule=False): from mathics.core.parser import parse_builtin_rule unavailable_function = self._get_unavailable_function() for name in dir(self): if name.startswith(prefix): function = getattr(self, name) pattern = function.__doc__ if pattern is None: # Fixes PyPy bug continue else: m = re.match(r"([\w,]+)\:\s*(.*)", pattern) if m is not None: attrs = m.group(1).split(",") pattern = m.group(2) else: attrs = [] if is_pymodule: name = ensure_context(self.get_name(short=True), "Pymathics") else: name = self.get_name() pattern = pattern % {"name": name} definition_class = ( PyMathicsDefinitions() if is_pymodule else SystemDefinitions() ) pattern = parse_builtin_rule(pattern, definition_class) if unavailable_function: function = unavailable_function if attrs: yield (attrs, pattern), function else: yield (pattern, function)
def message(self, symbol, tag, *args): from mathics.core.expression import String, Symbol, Expression, from_python # Allow evaluation.message('MyBuiltin', ...) (assume # System`MyBuiltin) symbol = ensure_context(symbol) quiet_messages = set(self.get_quiet_messages()) pattern = Expression("MessageName", Symbol(symbol), String(tag)) if pattern in quiet_messages or self.quiet_all: return # Shorten the symbol's name according to the current context # settings. This makes sure we print the context, if it would # be necessary to find the symbol that this message is # attached to. symbol_shortname = self.definitions.shorten_name(symbol) if settings.DEBUG_PRINT: print("MESSAGE: %s::%s (%s)" % (symbol_shortname, tag, args)) text = self.definitions.get_value(symbol, "System`Messages", pattern, self) if text is None: pattern = Expression("MessageName", Symbol("General"), String(tag)) text = self.definitions.get_value("System`General", "System`Messages", pattern, self) if text is None: text = String("Message %s::%s not found." % (symbol_shortname, tag)) text = self.format_output(Expression("StringForm", text, *(from_python(arg) for arg in args)), "text") self.out.append(Message(symbol_shortname, tag, text)) self.output.out(self.out[-1])
def contribute(definitions): # let MakeBoxes contribute first builtins['System`MakeBoxes'].contribute(definitions) for name, item in builtins.items(): if name != 'System`MakeBoxes': item.contribute(definitions) from mathics.core.expression import ensure_context from mathics.core.parser import all_operator_names from mathics.core.definitions import Definition # All builtins are loaded. Create dummy builtin definitions for # any remaining operators that don't have them. This allows # operators like \[Cup] to behave correctly. for operator in all_operator_names: if not definitions.have_definition(ensure_context(operator)): op = ensure_context(operator) definitions.builtin[op] = Definition(name=op)
def tmp(args, op=innequality_op): head = args[1].get_head_name() if head == ensure_context(op): args[1].leaves.append(args[3]) args[0] = args[1] elif head == 'System`Inequality': args[1].leaves.append(Symbol(op)) args[1].leaves.append(args[3]) args[0] = args[1] elif head in [ensure_context(k) for k in innequality_operators.keys()]: leaves = [] for i, leaf in enumerate(args[1].leaves): if i != 0: leaves.append(Symbol(head)) leaves.append(leaf) leaves.append(Symbol(op)) leaves.append(args[3]) args[0] = Expression('Inequality', *leaves) else: args[0] = Expression(op, args[1], args[3])
def apply_3(self, f, optvals, optname, evaluation): "OptionValue[f_, optvals_, optname_]" if type(optname) is String: name = optname.to_python()[1:-1] else: name = optname.get_name() if not name: name = optname.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message("OptionValue", "sym", optname, 1) return # Look first in the explicit list if optvals: val = get_option(optvals.get_option_values(evaluation), name, evaluation) else: val = None # then, if not found, look at $f$. It could be a symbol, or a list of symbols, rules, and list of rules... if val is None: if f.is_symbol(): val = get_option( evaluation.definitions.get_options(f.get_name()), name, evaluation) else: if f.get_head_name() in ("System`Rule", "System`RuleDelayed"): f = Expression("List", f) if f.get_head_name() == "System`List": for leave in f.get_leaves(): if leave.is_symbol(): val = get_option( evaluation.definitions.get_options( leave.get_name()), name, evaluation, ) if val: break else: values = leave.get_option_values(evaluation) val = get_option(values, name, evaluation) if val: break if val is None and evaluation.options: val = get_option(evaluation.options, name, evaluation) if val is None: evaluation.message("OptionValue", "optnf", optname) return Symbol(name) return val
def get_option_values(self, leaves, **options): evaluation = options.get("evaluation", None) if evaluation: default = evaluation.definitions.get_options(self.get_name()).copy() options = Expression("List", *leaves).get_option_values(evaluation) default.update(options) else: from mathics.core.parser import parse_builtin_rule default = {} for option, value in self.options.items(): option = ensure_context(option) default[option] = parse_builtin_rule(value) return default
def apply_2(self, f, optname, evaluation): 'OptionValue[f_, optname_]' name = optname.get_name() if not name: name = optname.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message('OptionValue', 'sym', optname, 1) return Expression('OptionValue', optname) val = evaluation.definitions.get_options(f.get_name()).get(name, None) if val is None: evaluation.message('OptionValue', 'optnf', optname) return Expression('OptionValue', optname) return val
def apply(self, symbol, evaluation): 'OptionValue[symbol_]' if evaluation.options is None: return name = symbol.get_name() if not name: name = symbol.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message('OptionValue', 'sym', symbol, 1) return value = evaluation.options.get(name) if value is None: evaluation.message('OptionValue', 'optnf', symbol) return return value
def apply_1(self, optname, evaluation): 'OptionValue[optname_]' if evaluation.options is None: return name = optname.get_name() if not name: name = optname.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message('OptionValue', 'sym', optname, 1) return Expression('OptionValue', optname) val = evaluation.options.get(name) if val is None: evaluation.message('OptionValue', 'optnf', optname) return Expression('OptionValue', optname) return val
def message(self, symbol, tag, *args) -> None: from mathics.core.expression import (String, Symbol, Expression, from_python) # Allow evaluation.message('MyBuiltin', ...) (assume # System`MyBuiltin) symbol = ensure_context(symbol) quiet_messages = set(self.get_quiet_messages()) pattern = Expression('MessageName', Symbol(symbol), String(tag)) if pattern in quiet_messages or self.quiet_all: return # Shorten the symbol's name according to the current context # settings. This makes sure we print the context, if it would # be necessary to find the symbol that this message is # attached to. symbol_shortname = self.definitions.shorten_name(symbol) if settings.DEBUG_PRINT: print('MESSAGE: %s::%s (%s)' % (symbol_shortname, tag, args)) text = self.definitions.get_value(symbol, 'System`Messages', pattern, self) if text is None: pattern = Expression('MessageName', Symbol('General'), String(tag)) text = self.definitions.get_value('System`General', 'System`Messages', pattern, self) if text is None: text = String("Message %s::%s not found." % (symbol_shortname, tag)) text = self.format_output( Expression('StringForm', text, *(from_python(arg) for arg in args)), 'text') self.out.append(Message(symbol_shortname, tag, text)) self.output.out(self.out[-1])
def apply_1(self, optname, evaluation): "OptionValue[optname_]" if evaluation.options is None: return if type(optname) is String: name = optname.to_python()[1:-1] else: name = optname.get_name() name = optname.get_name() if not name: name = optname.get_string_value() if name: name = ensure_context(name) if not name: evaluation.message("OptionValue", "sym", optname, 1) return val = get_option(evaluation.options, name, evaluation) if val is None: evaluation.message("OptionValue", "optnf", optname) return Symbol(name) return val
def lookup_name(self, name): assert isinstance(name, six.string_types) return ensure_context(name)
def lookup_name(self, name): assert isinstance(name, str) return ensure_context(name)
def lookup_name(self, name): assert isinstance(name, str) context = "System`" if name in SYSTEM_LIST else "Pymathics`" # print("XXX", name, context) return ensure_context(name, context)
def lookup_name(self, name): assert isinstance(name, basestring) return ensure_context(name)
def contribute(self, definitions): from mathics.core.parser import parse_builtin_rule name = self.get_name() rules = [] for pattern, function in self.get_functions(): rules.append(BuiltinRule(pattern, function, system=True)) for pattern, replace in self.rules.items(): if not isinstance(pattern, BaseExpression): pattern = pattern % {'name': name} pattern = parse_builtin_rule(pattern) replace = replace % {'name': name} rules.append(Rule(pattern, parse_builtin_rule(replace), system=True)) box_rules = [] if name != 'System`MakeBoxes': new_rules = [] for rule in rules: if rule.pattern.get_head_name() == 'System`MakeBoxes': box_rules.append(rule) else: new_rules.append(rule) rules = new_rules def extract_forms(name, pattern): # Handle a tuple of (forms, pattern) as well as a pattern # on the left-hand side of a format rule. 'forms' can be # an empty string (=> the rule applies to all forms), or a # form name (like 'System`TraditionalForm'), or a sequence # of form names. def contextify_form_name(f): # Handle adding 'System`' to a form name, unless it's # '' (meaning the rule applies to all forms). return '' if f == '' else ensure_context(f) if isinstance(pattern, tuple): forms, pattern = pattern if isinstance(forms, str): forms = [contextify_form_name(forms)] else: forms = [contextify_form_name(f) for f in forms] else: forms = [''] return forms, pattern formatvalues = {'': []} for pattern, function in self.get_functions('format_'): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] formatvalues[form].append(BuiltinRule( pattern, function, system=True)) for pattern, replace in self.formats.items(): forms, pattern = extract_forms(name, pattern) for form in forms: if not form in formatvalues: formatvalues[form] = [] if not isinstance(pattern, BaseExpression): pattern = parse_builtin_rule(pattern) formatvalues[form].append(Rule( pattern, parse_builtin_rule(replace), system=True)) for form, formatrules in formatvalues.items(): formatrules.sort() messages = [Rule(Expression('MessageName', Symbol(name), String(msg)), String(value), system=True) for msg, value in self.messages.items()] if name == 'System`MakeBoxes': attributes = [] else: attributes = ['System`Protected'] attributes += list(ensure_context(a) for a in self.attributes) options = {} for option, value in self.options.iteritems(): option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith('System`'): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition( name=name, attributes=set()) defaults = [] for spec, value in self.defaults.iteritems(): value = parse_builtin_rule(value) pattern = None if spec is None: pattern = Expression('Default', Symbol(name)) elif isinstance(spec, int): pattern = Expression('Default', Symbol(name), Integer(spec)) if pattern is not None: defaults.append(Rule(pattern, value, system=True)) definition = Definition( name=name, rules=rules, formatvalues=formatvalues, messages=messages, attributes=attributes, options=options, defaultvalues=defaults) definitions.builtin[name] = definition makeboxes_def = definitions.builtin['System`MakeBoxes'] for rule in box_rules: makeboxes_def.add_rule(rule)
def contextify_form_name(f): # Handle adding 'System`' to a form name, unless it's # '' (meaning the rule applies to all forms). return '' if f == '' else ensure_context(f)
def contribute(self, definitions): from mathics.core.parser import parse_builtin_rule name = self.get_name() rules = [] for pattern, function in self.get_functions(): rules.append(BuiltinRule(pattern, function, system=True)) for pattern, replace in self.rules.items(): if not isinstance(pattern, BaseExpression): pattern = pattern % {'name': name} pattern = parse_builtin_rule(pattern) replace = replace % {'name': name} rules.append( Rule(pattern, parse_builtin_rule(replace), system=True)) box_rules = [] if name != 'System`MakeBoxes': new_rules = [] for rule in rules: if rule.pattern.get_head_name() == 'System`MakeBoxes': box_rules.append(rule) else: new_rules.append(rule) rules = new_rules def extract_forms(name, pattern): # Handle a tuple of (forms, pattern) as well as a pattern # on the left-hand side of a format rule. 'forms' can be # an empty string (=> the rule applies to all forms), or a # form name (like 'System`TraditionalForm'), or a sequence # of form names. def contextify_form_name(f): # Handle adding 'System`' to a form name, unless it's # '' (meaning the rule applies to all forms). return '' if f == '' else ensure_context(f) if isinstance(pattern, tuple): forms, pattern = pattern if isinstance(forms, str): forms = [contextify_form_name(forms)] else: forms = [contextify_form_name(f) for f in forms] else: forms = [''] return forms, pattern formatvalues = {'': []} for pattern, function in self.get_functions('format_'): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] formatvalues[form].append( BuiltinRule(pattern, function, system=True)) for pattern, replace in self.formats.items(): forms, pattern = extract_forms(name, pattern) for form in forms: if not form in formatvalues: formatvalues[form] = [] if not isinstance(pattern, BaseExpression): pattern = parse_builtin_rule(pattern) formatvalues[form].append( Rule(pattern, parse_builtin_rule(replace), system=True)) for form, formatrules in formatvalues.items(): formatrules.sort() messages = [ Rule(Expression('MessageName', Symbol(name), String(msg)), String(value), system=True) for msg, value in self.messages.items() ] if name == 'System`MakeBoxes': attributes = [] else: attributes = ['System`Protected'] attributes += list(ensure_context(a) for a in self.attributes) options = {} for option, value in self.options.iteritems(): option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith('System`'): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition(name=name, attributes=set()) defaults = [] for spec, value in self.defaults.iteritems(): value = parse_builtin_rule(value) pattern = None if spec is None: pattern = Expression('Default', Symbol(name)) elif isinstance(spec, int): pattern = Expression('Default', Symbol(name), Integer(spec)) if pattern is not None: defaults.append(Rule(pattern, value, system=True)) definition = Definition(name=name, rules=rules, formatvalues=formatvalues, messages=messages, attributes=attributes, options=options, defaultvalues=defaults) definitions.builtin[name] = definition makeboxes_def = definitions.builtin['System`MakeBoxes'] for rule in box_rules: makeboxes_def.add_rule(rule)
def filter_leaves(self, head_name): head_name = ensure_context(head_name) return [leaf for leaf in self.leaves if leaf.get_head_name() == head_name]
def contribute(self, definitions, pymodule=False): from mathics.core.parser import parse_builtin_rule name = self.get_name() options = {} option_syntax = 'Warn' for option, value in self.options.items(): if option == '$OptionSyntax': option_syntax = value continue option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith('System`'): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition(name=name, attributes=set()) # Check if the given options are actually supported by the Builtin. # If not, we might issue an optx error and abort. Using '$OptionSyntax' # in your Builtin's 'options', you can specify the exact behaviour # using one of the following values: # - 'Strict': warn and fail with unsupported options # - 'Warn': warn about unsupported options, but continue # - 'Ignore': allow unsupported options, do not warn if option_syntax in ('Strict', 'Warn', 'System`Strict', 'System`Warn'): def check_options(options_to_check, evaluation): name = self.get_name() for key, value in options_to_check.items(): short_key = strip_context(key) if not has_option(options, short_key, evaluation): evaluation.message( name, 'optx', Expression('Rule', short_key, value), strip_context(name)) if option_syntax in ('Strict', 'System`Strict'): return False return True elif option_syntax in ("Ignore", "System`Ignore"): check_options = None else: raise ValueError('illegal option mode %s; check $OptionSyntax.' % option_syntax) rules = [] for pattern, function in self.get_functions(): rules.append( BuiltinRule(name, pattern, function, check_options, system=True)) for pattern, replace in self.rules.items(): if not isinstance(pattern, BaseExpression): pattern = pattern % {'name': name} pattern = parse_builtin_rule(pattern) replace = replace % {'name': name} rules.append( Rule(pattern, parse_builtin_rule(replace), system=True)) box_rules = [] if name != 'System`MakeBoxes': new_rules = [] for rule in rules: if rule.pattern.get_head_name() == 'System`MakeBoxes': box_rules.append(rule) else: new_rules.append(rule) rules = new_rules def extract_forms(name, pattern): # Handle a tuple of (forms, pattern) as well as a pattern # on the left-hand side of a format rule. 'forms' can be # an empty string (=> the rule applies to all forms), or a # form name (like 'System`TraditionalForm'), or a sequence # of form names. def contextify_form_name(f): # Handle adding 'System`' to a form name, unless it's # '' (meaning the rule applies to all forms). return '' if f == '' else ensure_context(f) if isinstance(pattern, tuple): forms, pattern = pattern if isinstance(forms, str): forms = [contextify_form_name(forms)] else: forms = [contextify_form_name(f) for f in forms] else: forms = [''] return forms, pattern formatvalues = {'': []} for pattern, function in self.get_functions('format_'): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] formatvalues[form].append( BuiltinRule(name, pattern, function, None, system=True)) for pattern, replace in self.formats.items(): forms, pattern = extract_forms(name, pattern) for form in forms: if form not in formatvalues: formatvalues[form] = [] if not isinstance(pattern, BaseExpression): pattern = pattern % {'name': name} pattern = parse_builtin_rule(pattern) replace = replace % {'name': name} formatvalues[form].append( Rule(pattern, parse_builtin_rule(replace), system=True)) for form, formatrules in formatvalues.items(): formatrules.sort() messages = [ Rule(Expression('MessageName', Symbol(name), String(msg)), String(value), system=True) for msg, value in self.messages.items() ] messages.append( Rule(Expression('MessageName', Symbol(name), String('optx')), String('`1` is not a supported option for `2`[].'), system=True)) if name == 'System`MakeBoxes': attributes = [] else: attributes = ['System`Protected'] attributes += list(ensure_context(a) for a in self.attributes) options = {} for option, value in self.options.items(): option = ensure_context(option) options[option] = parse_builtin_rule(value) if option.startswith('System`'): # Create a definition for the option's symbol. # Otherwise it'll be created in Global` when it's # used, so it won't work. if option not in definitions.builtin: definitions.builtin[option] = Definition(name=name, attributes=set()) defaults = [] for spec, value in self.defaults.items(): value = parse_builtin_rule(value) pattern = None if spec is None: pattern = Expression('Default', Symbol(name)) elif isinstance(spec, int): pattern = Expression('Default', Symbol(name), Integer(spec)) if pattern is not None: defaults.append(Rule(pattern, value, system=True)) definition = Definition(name=name, rules=rules, formatvalues=formatvalues, messages=messages, attributes=attributes, options=options, defaultvalues=defaults) if pymodule: definitions.pymathics[name] = definition else: definitions.builtin[name] = definition makeboxes_def = definitions.builtin['System`MakeBoxes'] for rule in box_rules: makeboxes_def.add_rule(rule)
def filter_leaves(self, head_name): head_name = ensure_context(head_name) return [ leaf for leaf in self.leaves if leaf.get_head_name() == head_name ]