def assign_elementary(self, lhs, rhs, evaluation, tags=None, upset=False): name = lhs.get_head_name() if name in system_symbols('OwnValues', 'DownValues', 'SubValues', 'UpValues', 'NValues', 'Options', 'DefaultValues', 'Attributes', 'Messages'): if len(lhs.leaves) != 1: evaluation.message_args(name, len(lhs.leaves), 1) return False tag = lhs.leaves[0].get_name() if not tag: evaluation.message(name, 'sym', lhs.leaves[0], 1) return False if tags is not None and tags != [tag]: evaluation.message(name, 'tag', Symbol(name), Symbol(tag)) return False if (name != 'System`Attributes' and 'System`Protected' # noqa in evaluation.definitions.get_attributes(tag)): evaluation.message(name, 'wrsym', Symbol(tag)) return False if name == 'System`Options': option_values = rhs.get_option_values(evaluation) if option_values is None: evaluation.message(name, 'options', rhs) return False evaluation.definitions.set_options(tag, option_values) elif name == 'System`Attributes': attributes = get_symbol_list( rhs, lambda item: evaluation.message(name, 'sym', item, 1)) if attributes is None: return False if 'System`Locked' in evaluation.definitions.get_attributes(tag): evaluation.message(name, 'locked', Symbol(tag)) return False evaluation.definitions.set_attributes(tag, attributes) else: rules = rhs.get_rules_list() if rules is None: evaluation.message(name, 'vrule', lhs, rhs) return False evaluation.definitions.set_values(tag, name, rules) return True form = '' nprec = None default = False message = False allow_custom_tag = False focus = lhs if name == 'System`N': if len(lhs.leaves) not in (1, 2): evaluation.message_args('N', len(lhs.leaves), 1, 2) return False if len(lhs.leaves) == 1: nprec = Symbol('MachinePrecision') else: nprec = lhs.leaves[1] focus = lhs.leaves[0] lhs = Expression('N', focus, nprec) elif name == 'System`MessageName': if len(lhs.leaves) != 2: evaluation.message_args('MessageName', len(lhs.leaves), 2) return False focus = lhs.leaves[0] message = True elif name == 'System`Default': if len(lhs.leaves) not in (1, 2, 3): evaluation.message_args('Default', len(lhs.leaves), 1, 2, 3) return False focus = lhs.leaves[0] default = True elif name == 'System`Format': if len(lhs.leaves) not in (1, 2): evaluation.message_args('Format', len(lhs.leaves), 1, 2) return False if len(lhs.leaves) == 2: form = lhs.leaves[1].get_name() if not form: evaluation.message('Format', 'fttp', lhs.leaves[1]) return False else: form = system_symbols( 'StandardForm', 'TraditionalForm', 'OutputForm', 'TeXForm', 'MathMLForm') lhs = focus = lhs.leaves[0] else: allow_custom_tag = True focus = focus.evaluate_leaves(evaluation) if tags is None and not upset: name = focus.get_lookup_name() if not name: evaluation.message(self.get_name(), 'setraw', focus) return False tags = [name] elif upset: if allow_custom_tag: tags = [] if focus.is_atom(): evaluation.message(self.get_name(), 'normal') return False for leaf in focus.leaves: name = leaf.get_lookup_name() tags.append(name) else: tags = [focus.get_lookup_name()] else: allowed_names = [focus.get_lookup_name()] if allow_custom_tag: for leaf in focus.get_leaves(): allowed_names.append(leaf.get_lookup_name()) for name in tags: if name not in allowed_names: evaluation.message(self.get_name(), 'tagnfd', Symbol(name)) return False ignore_protection = False rhs_int_value = rhs.get_int_value() lhs_name = lhs.get_name() if lhs_name == 'System`$RecursionLimit': # if (not rhs_int_value or rhs_int_value < 20) and not # rhs.get_name() == 'System`Infinity': if (not rhs_int_value or rhs_int_value < 20 or rhs_int_value > settings.MAX_RECURSION_DEPTH): # nopep8 evaluation.message('$RecursionLimit', 'limset', rhs) return False try: set_recursionlimit(rhs_int_value) except OverflowError: # TODO: Message return False ignore_protection = True elif lhs_name == 'System`$ModuleNumber': if not rhs_int_value or rhs_int_value <= 0: evaluation.message('$ModuleNumber', 'set', rhs) return False ignore_protection = True elif lhs_name in ('System`$Line', 'System`$HistoryLength'): if rhs_int_value is None or rhs_int_value < 0: evaluation.message(lhs_name, 'intnn', rhs) return False ignore_protection = True elif lhs_name == 'System`$RandomState': # TODO: allow setting of legal random states! # (but consider pickle's insecurity!) evaluation.message('$RandomState', 'rndst', rhs) return False elif lhs_name == 'System`$Context': new_context = rhs.get_string_value() if new_context is None or not valid_context_name( new_context, allow_initial_backquote=True): evaluation.message(lhs_name, 'cxset', rhs) return False # With $Context in Mathematica you can do some strange # things: e.g. with $Context set to Global`, something # like: # $Context = "`test`"; newsym # is accepted and creates Global`test`newsym. # Implement this behaviour by interpreting # $Context = "`test`" # as # $Context = $Context <> "test`" # if new_context.startswith('`'): new_context = (evaluation.definitions.get_current_context() + new_context.lstrip('`')) evaluation.definitions.set_current_context(new_context) ignore_protection = True return True elif lhs_name == 'System`$ContextPath': context_path = [s.get_string_value() for s in rhs.get_leaves()] if rhs.has_form('List', None) and all(valid_context_name(s) for s in context_path): evaluation.definitions.set_context_path(context_path) ignore_protection = True return True else: evaluation.message(lhs_name, 'cxlist', rhs) return False elif lhs_name == 'System`$MinPrecision': # $MinPrecision = Infinity is not allowed if rhs_int_value is not None and rhs_int_value >= 0: ignore_protection = True max_prec = evaluation.definitions.get_config_value('$MaxPrecision') if max_prec is not None and max_prec < rhs_int_value: evaluation.message('$MinPrecision', 'preccon', Symbol('$MinPrecision')) return True else: evaluation.message(lhs_name, 'precset', lhs, rhs) return False elif lhs_name == 'System`$MaxPrecision': if rhs.has_form('DirectedInfinity', 1) and rhs.leaves[0].get_int_value() == 1: ignore_protection = True elif rhs_int_value is not None and rhs_int_value > 0: ignore_protection = True min_prec = evaluation.definitions.get_config_value('$MinPrecision') if min_prec is not None and rhs_int_value < min_prec: evaluation.message('$MaxPrecision', 'preccon', Symbol('$MaxPrecision')) ignore_protection = True return True else: evaluation.message(lhs_name, 'precset', lhs, rhs) return False rhs_name = rhs.get_head_name() if rhs_name == 'System`Condition': if len(rhs.leaves) != 2: evaluation.message_args('Condition', len(rhs.leaves), 2) return False else: lhs = Expression('Condition', lhs, rhs.leaves[1]) rhs = rhs.leaves[0] rule = Rule(lhs, rhs) count = 0 defs = evaluation.definitions for tag in tags: if (not ignore_protection and 'System`Protected' # noqa in evaluation.definitions.get_attributes(tag)): if lhs.get_name() == tag: evaluation.message(self.get_name(), 'wrsym', Symbol(tag)) else: evaluation.message(self.get_name(), 'write', Symbol(tag), lhs) continue count += 1 if form: defs.add_format(tag, rule, form) elif nprec: defs.add_nvalue(tag, rule) elif default: defs.add_default(tag, rule) elif message: defs.add_message(tag, rule) else: if upset: defs.add_rule(tag, rule, position='up') else: defs.add_rule(tag, rule) if count == 0: return False return True