diff --git a/include/actions.js b/include/actions.js index 7fe2b446..68f0d832 100644 --- a/include/actions.js +++ b/include/actions.js @@ -902,10 +902,8 @@ CodeBootVM.prototype.reset = function () { CodeBootVM.prototype.showReason = function (reason) { // reason can be a string or an Error object - var vm = this; - var elem = $(''); var withStepCounter = vm.showingStepCounter(); var loc = null; var kind = null; @@ -925,7 +923,24 @@ CodeBootVM.prototype.showReason = function (reason) { } } - if (msg !== '' || withStepCounter) { + if (withStepCounter){ + var counter = '' + + vm.escapeHTML(vm.HTMLStepCounter()) + '' + + if (msg === '') { + msg = counter; + } else { + msg = new TFormat("{0} after {1}", [msg, counter]) + } + vm.hideStepCounter(); //TODO: belongs elsewhere + } + + if (msg instanceof TFormat) { + msg = vm.polyglotHTML_from_tformat(msg) + } + + if (msg !== '') { if (loc) { loc = vm.lang.relativeLocation(loc); // convert to relative loc @@ -933,17 +948,8 @@ CodeBootVM.prototype.showReason = function (reason) { vm.showReasonHighlight(loc); // and highlight location } - if (withStepCounter) { - if (msg !== '') msg += ' after '; - elem.text(msg); - var counter = $(''); - counter.html(vm.HTMLStepCounter()); - elem.append(counter); - vm.hideStepCounter(); //TODO: belongs elsewhere - } else { - elem.text(msg); - } - + var elem = $(''); + elem.html(msg); vm.replAddLineWidgetTranscript(elem.get(0)); } }; diff --git a/include/i18n.js b/include/i18n.js index 5bedce09..68a1bdad 100644 --- a/include/i18n.js +++ b/include/i18n.js @@ -217,13 +217,408 @@ CodeBootVM.prototype.translateDict = { 'fr': 'Cloner', }, + '{0} after {1}': { + 'fr': '{0} après {1}', + }, + + // Python exceptions + + 'unsupported operand type(s) for {0}: {1}': { + 'fr': "types des opérandes non supportés pour {0}: {1}", + }, + '{0}() missing {1} required positional argument: {2}': { + 'fr': '{0}() requiert {1} argument positionnel supplémentaire: {2}', + }, + '{0}() missing {1} required positional arguments: {2}': { + 'fr': '{0}() requiert {1} arguments positionnels supplémentaires: {2}', + }, + '{0}() missing {1} required keyword-only argument: {2}': { + 'fr': '{0}() requiert {1} argument nommé supplémentaire: {2}', + }, + '{0}() missing {1} required keyword-only arguments: {2}': { + 'fr': '{0}() requiert {1} arguments nommés supplémentaires: {2}', + }, + 'int() base must be >= 2 and <= 36, or 0': {}, + + 'an integer is required': {}, + + "can't multiply sequence by non-int": {}, + + 'division by zero': {}, + + '{0}() height argument must be a finite number': {}, + + 'I/O operation on closed file.': {}, + + 'dialect must be a string': {}, + + '{0}() takes {1} positional arguments but {2} was given': {}, + + '{0}() takes exactly {1} arguments ({2} given)': {}, + + 'ord() expected string of length 1': {}, + + 'expected {0} argument, got {1}': {}, + + 'argument should be integer or None': {}, + + 'float modulo': {}, + + '{0}() takes 0 or 1 argument': {}, + + 'isinstance() tuple classinfo is not supported yet': {}, + + "free variable '{0}' referenced before assignment in enclosing scope": {}, + + 'attempt to assign sequence of size {0} to extended slice of size {1}': {}, + + '{0}() argument must be a finite number': {}, + + 'expected one argument, got {0}': {}, + + 'expected at most 3 arguments, got {0}': {}, + + 'object cannot be interpreted as a float': {}, + + 'float division or modulo by zero': {}, + + "int() can't convert non-string with explicit base": {}, + + 'pop item from empty list': {}, + + 'cannot convert float NaN to integer': {}, + + '{0}() takes at most {1} argument, got {2}': {}, + + "innerHTML descriptor expected a 'DOMElement'": {}, + + 'No such file: {0}': {}, + + 'attribute name must be string': {}, + + '{0}() arguments must be between 0 and 1': {}, + + 'sleep length must be non-negative': {}, + + "derived metaclass must be 'type'": {}, + + 'first argument must be callable': {}, + + 'iterable expected': {}, + + 'method takes no keyword arguments': {}, + + 'unexpected end of data': {}, + + '__len__() should return >= 0': {}, + + 'expected at least {0} positional arguments, got {1}': {}, + + '{0}() scale argument must be a finite number': {}, + + '{0} parameter of fillRectangle must be a non-negative integer': {}, + + 'No active exception to reraise': {}, + + 'expected at least {0} positional argument(s), got {1}': {}, + + 'length should not be negative': {}, + + '{0} attribute must be set to a string': {}, + + 'write() argument must be str': {}, + + 'x, y, width and height must be of type int': {}, + + 'slice takes from 1 to 3 arguments, got {0}': {}, + + 'object.__new__({0}) is not safe, use {0}.__new__()': {}, + + '{0} parameter of {1} must be a non-negative integer such that {2} + {0} <= {3}': {}, + + 'must be str': {}, + + "'in ' requires string as left operand": {}, + + 'color must be of type str or struct': {}, + + 'only extended ascii characters are supported for now': {}, + + '{0} returned non-string': {}, + + 'invalid literal for int() with base {0}: {1}': {}, + + 'unsupported operand type(s) for pow()': {}, + + "{0} argument '{1}' must be {2}": {}, + + 'slice indices must be integers or None or have an __index__ method': {}, + + 'iterator should return strings': {}, + + 'lineterminator must be a string': {}, + + 'filename must be a str': {}, + + '{0}() takes {1} positional argument but {2} was given': {}, + + 'escapechar must be a string or None': {}, + + 'pensize() argument must be a non-negative number': {}, + + '{0}() argument {1} must be {2}': {}, + + 'catching classes that do not inherit from BaseException is not allowed': {}, + + 'class keyword arguments not yet supported': {}, + + '__float__ returned non-float': {}, + + 'bad quoting value': {}, + + 'HTML element selector must be a string': {}, + + 'first argument must have a "{0}" method': {}, + + "'{0}' is an invalid keyword argument for {1}": {}, + + 'not writable': {}, + + '{0} expected at most 1 argument, got {1}': {}, + + "cannot set reserved attribute '{0}}' of {1}": {}, + + 'reduce() of empty sequence with no initial value': {}, + + "'{0}' object cannot be interpreted as an integer": {}, + + 'object does not support item assignment': {}, + + '{0}(object): object is not a subtype of {1}': {}, + + "name '{0}' is not defined": {}, + + '{0} expected 1 argument, got 0': {}, + + 'a number is required': {}, + + 'struct takes no positional argument, got {0}': {}, + + '{0} returned non-int': {}, + + 'strip arg must be None or str': {}, + + '{0} takes exactly one argument ({1} given)': {}, + + '{0}() arg is an empty sequence': {}, + + '{0} index out of range': {}, + + '{0}() expected {1} arguments, got {2}': {}, + + '{0}() takes {1} positional arguments but {2} were given': {}, + + 'function takes no keyword arguments': {}, + + 'pow() 3rd argument cannot be 0': {}, + + 'object is not an iterator': {}, + + '{0} assignment unsupported': {}, + + 'arguments {0} and {1} must be of type int': {}, + + 'too many values to unpack': {}, + + 'empty separator': {}, + + 'rounded value too large to represent': {}, + + 'object.__new__(): not enough arguments': {}, + + '{0} expected 1 to 3 arguments, got {1}': {}, + + 'float() argument must be a string or a number': {}, + + 'need to escape, but no escapechar set': {}, + + 'must be real number': {}, + + "'{0}' object has no attribute '{1}'": {}, + + 'range() arg 3 must not be zero': {}, + + 'expected at least 1 argument, got {0}': {}, + + 'modulo by zero': {}, + + 'int() argument must be a string, a bytes-like object or a number': {}, + + 'new-line character seen in unquoted field': {}, + + 'color must be of type {0} or {1}': {}, + + "'{0}' attribute must be set to a string": {}, + + 'expected {0} arguments, got {1}': {}, + + 'cannot convert float infinity to integer': {}, + + "argument for {0} given by name ('{1}') and position ({2})": {}, + + 'object is not subscriptable': {}, + + 'invalid HTML color {0} format': {}, + + '{0} is not in {1}': {}, + + 'type() takes 1 or 3 arguments': {}, + + 'not enough values to unpack': {}, + + '3rd argument not allowed unless all arguments are integers': {}, + + "{0} must have at least two arguments": {}, + + 'pow() 3rd argument not allowed unless all arguments are integers': {}, + + "'{0}' object is not callable": {}, + + 'filename must be a non-empty str': {}, + + "bad operand type for unary {0}: '{1}'": {}, + + 'expected no argument, got {0}': {}, + + 'object is not iterable': {}, + + 'isinstance() arg 2 must be a type or tuple of types': {}, + + 'quoting must be an interger': {}, + + 'bad operand type for abs()': {}, + + 'separator must be str or None': {}, + + "local variable '{0}' referenced before assignment": {}, + + 'index() expected between 1 and 3 arguments, got {0}': {}, + + '{0}() takes exactly {1} argument ({2} given)': {}, + + 'mapping unpacking is not yet supported for non-dict objects': {}, + + 'expected 2 or 3 arguments, got {0}': {}, + + 'not readable': {}, + + 'content must be a str': {}, + + '{0} takes {1} argument ({2} given)': {}, + + 'substring not found': {}, + + '__bool__ should return bool': {}, + + 'int too large to convert to float': {}, + + 'list.remove(x): x not in list': {}, + + 'quotechar must be a 1-character string': {}, + + "descriptor '{0}' for '{1}' objects doesn't apply to a '{2}' object": {}, + + '{0}() takes no argument ({1} given)': {}, + + 'chr() arg not in range(0x110000)': {}, + + 'math domain error': {}, + + "value descriptor expected a '{0}'": {}, + + 'single empty field record must be quoted': {}, + + '{0} attribute value must be a string': {}, + + 'could not convert string to float: {0}': {}, + + 'sequence item {0}: expected str instance': {}, + + 'expected between 1 and 3 arguments arguments, got {0}': {}, + + 'modular inverse unimplemented': {}, + + '{0}() takes at most {1} arguments, got {2}': {}, + + "{0}() got an unexpected keyword argument '{1}'": {}, + + "{0}() got multiple values for argument '{1}'": {}, + + "type doesn't define {0} method": {}, + + 'Could not convert JavaScript type to Python': {}, + + "No module named '{0}'": {}, + + 'append() takes exactly one argument ({0} given)': {}, + + '{0}() arguments must be finite numbers': {}, + + '{0}() width argument must be a finite number': {}, + + 'ord() expected a character, but string of length {0} found': {}, + + 'int too large to multiply sequence': {}, + + "object of type '{0}' has no len()": {}, + + '{0}({1}): {1} is not a type object': {}, + + 'extend() takes one argument ({0} given)': {}, + + 'object.__new__(X): X is not a type object': {}, + + '{0}() takes {1} positional argument but {2} were given': {}, + + "type has no attribute '{0}'": {}, + + '{0}(): not enough arguments': {}, + + "invalid mode: '{0}'": {}, + + 'range object index out of range': {}, + + 'expected at least {0} positional argument, got {1}': {}, + + 'string index out of range': {}, + + "'DOMElement' attribute must be a string": {}, + + "can't set attributes of built-in/extension type '{0}'": {}, + + 'dict type not implemented': {}, + + 'delimiter must be a 1-character string': {}, + + 'Cannot create a consistent method resolution order (MRO) for bases': {}, + + '{0} first arg must be str or a tuple of str': {}, + + '{0} attribute must be a string': {}, + + '{0} parameter of setPixel must be a non-negative integer less than {1}': {}, + + 'slice step cannot be 0': {}, + + 'math range error': {}, + + "'{0}' expected after '{1}'": {}, + }; CodeBootVM.prototype.translate = function (lang, str) { - var vm = this; - - var x = vm.translateDict[str]; + var x = CodeBootVM.prototype.translateDict[str]; if (x !== void 0) { x = x[lang]; @@ -232,60 +627,242 @@ CodeBootVM.prototype.translate = function (lang, str) { } } + if (lang && lang !== "en") console.warn("no translation found", lang, str); + return str; }; CodeBootVM.prototype.polyglotHTML = function (str, args) { + var vm = this; - var vm = this; + if (!args) args = []; - var HTML = ''; + return vm.polyglotHTML_from_tformat(new TFormat(str, args)); +}; - if (!args) args = []; +CodeBootVM.prototype.polyglotHTML_from_tformat = function (tformat) { + var vm = this; + var HTML = ''; - for (var i=0; i' + - CodeBoot.prototype.escapeHTML(vm.format(vm.translate(lang, str), args)) + - ''; - } + for (var i=0; i' + + vm.escapeHTML(tformat.translate(lang)) + + ''; + } + + return HTML; +}; + +CodeBootVM.prototype.format = function format(str, args) { + var result = ''; + var i = 0; + + while (i < str.length) { + var c = str[i++]; + if (c !== '{') { + result += c; + } else { + var j = i; + while (j < str.length) { + c = str[j]; + if (!(c >= '0' && c <= '9')) break; + j++; + } + var n = (j === i) ? 1 : parseInt(str.slice(i, j)); + i = j; + if (i < str.length && c == '}') { + result += args[n]; + i++; + } + } + } + return result; +} + +CodeBootVM.prototype.escapeHTML = function (str) { + + var vm = this; - return HTML; + return str.replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); }; -CodeBootVM.prototype.format = function (str, args) { +CodeBootVM.prototype.confirmHTML = function (html, cont) { var vm = this; - var result = ''; - var i = 0; - - while (i < str.length) { - var c = str[i++]; - if (c !== '{') { - result += c; - } else { - var j = i; - while (j < str.length) { - c = str[j]; - if (!(c >= '0' && c <= '9')) break; - j++; - } - var n = (j === i) ? 1 : parseInt(str.slice(i, j)); - i = j; - if (i < str.length && c == '}') { - result += arguments[n]; - i++; - } + var dialog = vm.root.querySelector('.cb-modal-dialog'); + var body = dialog && dialog.querySelector('.modal-body'); + var footer = dialog && dialog.querySelector('.modal-footer'); + + if (!body || !footer) { + // use the builtin confirm dialog, which is unfortunately synchronous + // and doesn't handle HTML + cont(window.confirm(html)); + } else { + + body.innerHTML = html; + + var has_confirmed_ok = false; + + function confirm_ok() { + has_confirmed_ok = true; + $(dialog).modal('hide'); } - } - return result; + var cancel = document.createElement('button'); + cancel.className = 'btn btn-secondary'; + cancel.setAttribute('data-dismiss', 'modal'); + cancel.innerHTML = vm.polyglotHTML('Cancel'); + + var ok = document.createElement('button'); + ok.className = 'btn btn-primary'; + ok.innerHTML = vm.polyglotHTML('OK'); + + ok.addEventListener('click', confirm_ok); + + footer.innerHTML = ''; + footer.appendChild(cancel); + footer.appendChild(ok); + + $(dialog).on('hidden.bs.modal', function (event) { + $(dialog).modal('dispose'); + cont(has_confirmed_ok); + }); + + $(dialog).modal({}); // show the modal dialog + } }; -CodeBootVM.prototype.tformat = function (str) { +CodeBootVM.prototype.alertHTML = function (html, cont) { var vm = this; - return vm.format(vm.translate('fr', str), arguments); + var dialog = vm.root.querySelector('.cb-modal-dialog'); + var body = dialog && dialog.querySelector('.modal-body'); + var footer = dialog && dialog.querySelector('.modal-footer'); + + if (!cont) cont = function () { }; + + if (!body || !footer) { + // use the builtin alert, which is unfortunately synchronous + // and doesn't handle HTML + window.alert(html); + cont(); + } else { + + body.innerHTML = html; + + function done() { + $(dialog).modal('hide'); + } + + var ok = document.createElement('button'); + ok.className = 'btn btn-primary'; + ok.innerHTML = vm.polyglotHTML('OK'); + + ok.addEventListener('click', done); + + footer.innerHTML = ''; + footer.appendChild(ok); + + $(dialog).on('hidden.bs.modal', function (event) { + $(dialog).modal('dispose'); + cont(); + }); + + $(dialog).modal({}); // show the modal dialog + } }; + +function TFormat(template, fields) { + var tformat = this; + + tformat.template = template; + tformat.fields = fields; +} + +TFormat.prototype.format = function() { + return this.translate(null) +} + +TFormat.prototype.translate = function(lang) { + var fields = this.fields; + var formatted_fields = []; + + for (let i = 0; i < fields.length; i ++) { + var s = fields[i]; + if (typeof s == "string") { + formatted_fields.push(s) + } else { + // can be TFormat or TEnum, or other object with the translate interface + formatted_fields.push(s.translate(lang)) + } + } + + return CodeBootVM.prototype.format(CodeBootVM.prototype.translate(lang, this.template), formatted_fields); +} + +function TEnum(elements) { + var tenum = this + + tenum.elements = elements +} + +TEnum.prototype.format = function() { + var tenum = this + + return tenum.translate(null) +} + +TEnum.prototype.translate = function(lang) { + var tenum = this + var elements = tenum.elements + + var formatted_elements = []; + + for (let i = 0; i < elements.length; i ++) { + var s = elements[i]; + if (typeof s == "string") { + formatted_elements.push(s) + } else { + // object with the translate interface + formatted_elements.push(s.translate(lang)) + } + } + + switch (lang) { + case "fr": + // 1 item: "chien" + // 2 items "chien et chat" + // 2+ items "chien, chat et souris" + return formatted_elements.slice(0, -2).concat(formatted_elements.slice(-2).join(" et ")).join(", "); + + case "en": + default: + // 1 item: "dog" + // 2 items "dog and cat" + // 2+ items "dog, cat, and mouse" + if (formatted_elements.length > 2) { + return formatted_elements.slice(0, -2).concat(formatted_elements.slice(-2).join(", and ")).join(", "); + } else { + return formatted_elements.join(" and "); + } + } +} + +function tformat(template, fields){ + if (!fields) fields = []; + + return new TFormat(template, fields); +} + +function tenum(elements){ + return new TEnum(elements); +} diff --git a/pyinterp/etc/apply_tformat.py b/pyinterp/etc/apply_tformat.py new file mode 100644 index 00000000..2df68d63 --- /dev/null +++ b/pyinterp/etc/apply_tformat.py @@ -0,0 +1,88 @@ +import ast +import argparse +import itertools + +class PyinterpTraverser(ast.NodeVisitor): + def __init__(self): + self.to_translate = [] + + def visit_Call(self, node): + func = node.func + + if isinstance(func, ast.Name) and func.id == "sem_raise_with_message": + args = node.args + arg_msg = args[2] + + if isinstance(arg_msg, ast.Constant) \ + or isinstance(arg_msg, ast.BinOp) and isinstance(arg_msg.op, ast.Add): + + flattened_msg = self.flatten_msg(arg_msg) + + if all(not isinstance(a, ast.Name) for a in flattened_msg) \ + and any(isinstance(a, ast.Constant) for a in flattened_msg): + # Safe to replace + + template_args = [a for a in flattened_msg if not isinstance(a, ast.Constant)] + counter = itertools.count() + + template = "".join(a.value if isinstance(a, ast.Constant) else f"{{{next(counter)}}}" for a in flattened_msg) + + tformat_args = [ast.Constant(template), ast.List(template_args, ast.Load())] if template_args else [ast.Constant(template)] + + tformat_call = ast.Call(ast.Name("tformat", ast.Load()), + tformat_args, + []) + + replacement = ast.Call(ast.Name("sem_raise_with_tformat", ast.Load()), + [args[0], args[1], tformat_call], + []) + + + self.to_translate.append((node, replacement)) + + def flatten_msg(self, msg): + if isinstance(msg, ast.BinOp) and isinstance(msg.op, ast.Add): + return [*self.flatten_msg(msg.left), *self.flatten_msg(msg.right)] + else: + return [msg] + + +def main(file): + with open(file) as f: + content = f.read() + file_ast = ast.parse(content) + + traverser = PyinterpTraverser() + traverser.visit(file_ast) + + to_translate = sorted(traverser.to_translate, + key=lambda pair: (pair[0].lineno, pair[0].col_offset), + reverse=True) + + lines = content.splitlines() + + for source, replacement in to_translate: + lineno = source.lineno + end_lineno = source.end_lineno + offset = source.col_offset + end_offset = source.end_col_offset + + source_lines = lines[lineno-1:end_lineno] + + head = source_lines[0][:offset] + tail = source_lines[-1][end_offset:] + + new_code = head + ast.unparse(replacement) + tail + + lines[lineno-1:end_lineno] = [new_code] + + new_content = "\n".join(lines) + + print(new_content) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Helper script to convert pyinterp error messages to translatable ones.') + + parser.add_argument('file') + + main(parser.parse_args().file) diff --git a/pyinterp/etc/find_missing_translations.py b/pyinterp/etc/find_missing_translations.py new file mode 100644 index 00000000..35ba3931 --- /dev/null +++ b/pyinterp/etc/find_missing_translations.py @@ -0,0 +1,97 @@ +import ast +import argparse +import difflib +import logging +import re + +class PyinterpTraverser(ast.NodeVisitor): + def __init__(self): + self.templates = set() + + def visit_Call(self, node): + func = node.func + + if isinstance(func, ast.Name) and func.id == "tformat": + args = node.args + template = args[0] + + if isinstance(template, ast.Constant) and isinstance(template.value, str): + self.templates.add(template.value) + else: + logging.warning(f"tformat with non-literal template at line {node.lineno}") + else: + self.generic_visit(node) + + +def extract_translate_dict(i18n_content): + # TODO: this function is a single big hack! + + start_marker = "CodeBootVM.prototype.translateDict = " + end_marker = ";" # TODO: that's kind of cheating + + start = i18n_content.index(start_marker) + len(start_marker) + end = i18n_content.index(end_marker, start) + + # TODO: hack which uses the fact our translation dict is readable as a Python dict except for comments + translation_dict_as_text = i18n_content[start:end] + translation_dict_as_text = re.sub(r"//.*", "", translation_dict_as_text) + translation_dict = ast.literal_eval(translation_dict_as_text) + + return translation_dict + + +def main(pyinterp_file, i18n_file): + with open(pyinterp_file) as f: + pyinterp_content = f.read() + file_ast = ast.parse(pyinterp_content) + + with open(i18n_file) as f: + i18n_content = f.read() + + traverser = PyinterpTraverser() + traverser.visit(file_ast) + + translation_dict = extract_translate_dict(i18n_content) + + templates = list(traverser.templates) + untranslated_templates = [] + + for t in traverser.templates: + if t not in translation_dict: + untranslated_templates.append(t) + + similar_templates = [] + + for i, t1 in enumerate(templates): + for t2 in templates[i+1:]: + matcher = difflib.SequenceMatcher(None, t1, t2, autojunk=False) + ratio = matcher.ratio() + if 0.85 < ratio < 0.91: + similar_templates.append((ratio, t1, t2)) + + similar_templates.sort() + + #for t in similar_templates: + # print(*t, sep="\n\t- ") + + #for t in templates: + # for i in range(10): + # if t.count(f"{{{i}}}") > 1: + # print(t) + + for t in untranslated_templates: + print(f"{repr(t)}: {{}},\n") + + + print(f"Found {len(templates)} distinct translations") + print(f"Found {len(untranslated_templates)} distinct translations") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Helper script to convert pyinterp error messages to translatable ones.') + + parser.add_argument('pyinterp_file') + parser.add_argument('i18n_file') + + args = parser.parse_args() + + main(args.pyinterp_file, args.i18n_file) diff --git a/pyinterp/pyinterp/pyinterp/__init__.py b/pyinterp/pyinterp/pyinterp/__init__.py index d2fdc7a3..82833e19 100644 --- a/pyinterp/pyinterp/pyinterp/__init__.py +++ b/pyinterp/pyinterp/pyinterp/__init__.py @@ -492,6 +492,33 @@ def make_loop_rte(rte, break_cont, continue_cont): return new_rte +def om_get_exception_msg(ctx, exc): + exc_name = OM_get_object_class_qualname(exc) + exc_args = OM_get(exc, 'args') + + if exc_args is absent or not om_isinstance(exc_args, class_tuple): + msg = "" + else: + seq = OM_get_tuple_seq(exc_args) + if len(seq) == 0: + return exc_name + elif len(seq) == 1: + el = seq[0] + if om_isinstance(el, class_str): + # Strings can have a tformat parameter which indicate from which template + # they were created. When this happens, we return the tformat instead of + # the boxed string so that codeBoot can translate the error message + exc_tformat = OM_get_str_tformat(el) + + if exc_tformat is None: + return exc_name + ": " + OM_get_boxed_value(el) + else: + return tformat("{0}: {1}", [exc_name, exc_tformat]) + else: + return exc_name + ": " + om_simple_repr(ctx, seq[0]) + else: + return exc_name + ": " + om_simple_repr(ctx, exc_args) + def make_new_rte(globals_env, locals_env, builtins, builtins_module, options): def main_handler(exc): locations = OM_get_BaseException_locations(exc) @@ -499,8 +526,9 @@ def main_handler(exc): dummy_ctx = Context(new_rte, lambda rte: None, last_location) - exc_msg = om_simple_exception_format(dummy_ctx, exc) - return expr_end_with_error(dummy_ctx, exc_msg) + msg = om_get_exception_msg(dummy_ctx, exc) + + return expr_end_with_error(dummy_ctx, msg) serial_counter = [0] sys_modules = make_dict() @@ -873,12 +901,12 @@ def align_args_with_signature(ctx, funcname, caller_args, caller_kwargs, signatu # harder to implement than this abstraction. def format_missing_arguments_names(names): - last_index = len(names) - 1 - if last_index == 0: - return "'" + names[0] + "'" - else: - comma_separated = "'" + "', '".join(names[0:len(names) - 1]) + "'" - return comma_separated + " and '" + names[last_index] + "'" + formatted_names = [] + + for n in names: + formatted_names.append(tformat("'{0}'", [n])) + + return formatted_names def raise_missing_arguments(arg_choices): # Recover positional names to figure out if missing values are arguments or keyword-only @@ -907,37 +935,56 @@ def raise_missing_arguments(arg_choices): missing_kws_len = len(missing_kws) if missing_args_len > 0: + missing_names = tenum(format_missing_arguments_names(missing_args)) if missing_args_len == 1: - error_msg = funcname + "() missing 1 required positional argument: '" + missing_args[0] + "'" + error_msg = tformat("{0}() missing {1} required positional argument: {2}", + [funcname, "1", missing_names]) else: - missing_names = format_missing_arguments_names(missing_args) - error_msg = funcname + "() missing " + str(missing_args_len) + " required positional arguments: " + missing_names - elif missing_kws_len == 1: - error_msg = funcname + "() missing 1 required keyword-only argument: '" + missing_kws[0] + "'" + error_msg = tformat("{0}() missing {1} required positional arguments: {2}", + [funcname, str(missing_args_len), missing_names]) else: - missing_names = format_missing_arguments_names(missing_kws) - error_msg = funcname + "() missing " + str(missing_kws_len) + " required keyword-only arguments: " + missing_names + missing_names = tenum(format_missing_arguments_names(missing_kws)) - return sem_raise_with_message(ctx, class_TypeError, error_msg) + if missing_kws_len == 1: + error_msg = tformat("{0}() missing {1} required keyword-only argument: {2}", + [funcname, str(missing_kws_len), missing_names]) + else: + error_msg = tformat("{0}() missing {1} required keyword-only arguments: {2}", + [funcname, str(missing_kws_len), missing_names]) + + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) def raise_missing_positional_arguments(provided, min_required, names): missing_args = names[provided:min_required] missing_args_len = len(missing_args) + missing_names = tenum(format_missing_arguments_names(missing_args)) + if missing_args_len == 1: - error_msg = funcname + "() missing 1 required positional argument: '" + missing_args[0] + "'" + error_msg = tformat("{0}() missing {1} required positional argument: {2}", + [funcname, "1", missing_names]) else: - missing_names = format_missing_arguments_names(missing_args) - error_msg = funcname + "() missing " + str(missing_args_len) + " required positional arguments: " + missing_names + error_msg = tformat("{0}() missing {1} required positional arguments: {2}", + [funcname, str(missing_args_len), missing_names]) - return sem_raise_with_message(ctx, class_TypeError, error_msg) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) def raise_too_many_positional_arguments(provided, required): - verb = "was" if provided == 1 else "were" - s = "" if required == 1 else "s" + required_str = str(required) + provided_str = str(provided) + + if provided <= 1: + if required <= 1: + error_msg = tformat("{0}() takes {1} positional argument but {2} was given", [funcname, required_str, provided_str]) + else: + error_msg = tformat("{0}() takes {1} positional arguments but {2} was given", [funcname, required_str, provided_str]) + else: + if required <= 1: + error_msg = tformat("{0}() takes {1} positional argument but {2} were given", [funcname, required_str, provided_str]) + else: + error_msg = tformat("{0}() takes {1} positional arguments but {2} were given", [funcname, required_str, provided_str]) - error_msg = funcname + "() takes " + str(required) + " positional argument" + s + " but " + str(provided) + " " + verb + " given" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) args = signature_args(signature) posonlyargs = signature_posonlyargs(signature) @@ -994,8 +1041,8 @@ def raise_too_many_positional_arguments(provided, required): if val_from_args is not None: if val_from_kws is not None: - error_msg = funcname + "() got multiple values for argument '" + name + "'" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("{0}() got multiple values for argument '{1}'", [funcname, name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: dict_set(locals_env, name, val_from_args) elif val_from_kws is not None: @@ -1010,8 +1057,8 @@ def raise_too_many_positional_arguments(provided, required): dict_set(locals_env, kwarg, om_dict(caller_kwargs)) elif dict_len(caller_kwargs) > 0: wrong_key = dict_keys(caller_kwargs)[0] - error_msg = funcname + "() got an unexpected keyword argument '" + wrong_key + "'" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("{0}() got an unexpected keyword argument '{1}'", [funcname, wrong_key]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) if vararg is not None: rest = list_get_slice(caller_args, caller_args_len - rest_size, caller_args_len, 1) @@ -1665,8 +1712,16 @@ def om_dict(val): return om_boxval(class_dict, val) def om_str(val): - # assert isinstance(val, str), 'om_str expected str' - return om_boxval(class_str, val) + obj = om_boxval(class_str, val) + OM_set_str_tformat(obj, None) + return obj + +def om_str_from_tformat(tformat_obj): + text = tformat_obj.format() + + obj = om_boxval(class_str, text) + OM_set_str_tformat(obj, tformat_obj) + return obj def om_int(val): return om_boxval(class_int, val) @@ -1977,6 +2032,14 @@ def OM_set_boxed_value(o, value): def OM_get_boxed_value(o): return o.value +def OM_set_str_tformat(o, tformat): + # tformat is a TFormat object when the string has been generated + # with tformat, otherwise it should be None + o.tformat = tformat + +def OM_get_str_tformat(o): + return o.tformat + def OM_get_tuple_seq(o): return o.seq @@ -2335,13 +2398,13 @@ def error(rte): val1_type = OM_get_object_class(val1) val2_type = OM_get_object_class(val2) - type1_name = OM_get(val1_type, "__name__") - type2_name = OM_get(val2_type, "__name__") + type1_name = OM_get_class_name(val1_type) + type2_name = OM_get_class_name(val2_type) - msg = "unsupported operand type(s) for " + op_symbol + ": " + om_format_str_repr(type1_name, rte) + " and "\ - + om_format_str_repr(type2_name, rte) + msg = tformat("unsupported operand type(s) for {0}: {1}", + (op_symbol, tenum([type1_name, type2_name]))) - return sem_raise_with_message(ctx, class_TypeError, msg) + return sem_raise_with_tformat(ctx, class_TypeError, msg) # A: Does val1 have method? val1_method = getattribute_from_obj_mro(val1, method) @@ -2435,7 +2498,7 @@ def sem_Round(ctx, obj, ndigits): obj_round = getattribute_from_obj_mro(obj, "__round__") if obj_round is absent: - return sem_raise_with_message(ctx, class_TypeError, "type doesn't define __round__ method") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("type doesn't define {0} method", ["__round__"])) elif ndigits is absent: return sem_simple_call(ctx, obj_round, [obj, ]) else: @@ -2451,7 +2514,7 @@ def test_method_result(rte, val): def test_rmethod_result(rte, val): if om_is(val, om_NotImplemented): - return sem_raise_with_message(ctx, class_TypeError, "unsupported operand type(s) for pow()") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("unsupported operand type(s) for pow()")) else: return ctx.cont(rte, val) @@ -2463,7 +2526,7 @@ def call_rmethod(rte): ctx2 = with_cont(ctx, test_rmethod_result) return sem_simple_call(ctx2, power_rmethod, [power, base, mod]) else: - return sem_raise_with_message(ctx, class_TypeError, "unsupported operand type(s) for pow()") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("unsupported operand type(s) for pow()")) base_method = getattribute_from_obj_mro(base, "__pow__") @@ -2557,62 +2620,65 @@ def call_rmethod(rte): # Helper to build magic_methods def do_check_method_self_arg(self_expected_cls, method_name): - cls_name = OM_get_boxed_value(OM_get(self_expected_cls, "__name__")) + cls_name = OM_get_class_name(self_expected_cls) method_qualname = cls_name + "." + method_name - not_enough_arguments_msg = method_qualname + "(): not enough arguments" - not_a_subtype_msg = method_qualname + "(object): object is not a subtype of " + cls_name def check_method_self_arg(ctx, cont, args): args_len = len(args) if args_len == 0: - return sem_raise_with_message(ctx, class_TypeError, not_enough_arguments_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(): not enough arguments", [method_qualname])) cls = args[0] if not om_isinstance(cls, self_expected_cls): - return sem_raise_with_message(ctx, class_TypeError, not_a_subtype_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(object): object is not a subtype of {1}", + [method_qualname, cls_name])) else: return cont(ctx, args) return check_method_self_arg def do_check_method_with_kwargs_self_arg(self_expected_cls, method_name): - cls_name = OM_get_boxed_value(OM_get(self_expected_cls, "__name__")) + cls_name = OM_get_class_name(self_expected_cls) method_qualname = cls_name + "." + method_name - not_enough_arguments_msg = method_qualname + "(): not enough arguments" - not_a_subtype_msg = method_qualname + "(object): object is not a subtype of " + cls_name def check_method_self_arg(ctx, cont, args, kwargs): args_len = len(args) if args_len == 0: - return sem_raise_with_message(ctx, class_TypeError, not_enough_arguments_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(): not enough arguments", [method_qualname])) cls = args[0] if not om_isinstance(cls, self_expected_cls): - return sem_raise_with_message(ctx, class_TypeError, not_a_subtype_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(object): object is not a subtype of {1}", + [method_qualname, cls_name])) else: return cont(ctx, args, kwargs) return check_method_self_arg def do_check_static_method_cls_arg(expected_cls, method_name): - cls_name = OM_get_boxed_value(OM_get(expected_cls, "__name__")) - not_enough_arguments_msg = method_name + "(): not enough arguments" - not_a_type_object_msg = method_name + "(X): X is not a type object" - not_a_subtype_msg = method_name + "(object): object is not a subtype of " + cls_name + cls_name = OM_get_class_name(expected_cls) def check_new_cls_arg(ctx, cont, args): args_len = len(args) if args_len == 0: - return sem_raise_with_message(ctx, class_TypeError, not_enough_arguments_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(): not enough arguments", [method_qualname])) cls = args[0] if not om_isinstance(cls, class_type): - return sem_raise_with_message(ctx, class_TypeError, not_a_type_object_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}({1}): {1} is not a type object", [method_name, "X"])) elif not om_issubclass(cls, expected_cls): - return sem_raise_with_message(ctx, class_TypeError, not_a_subtype_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(object): object is not a subtype of {1}", + [method_name, cls_name])) else: return cont(ctx, args) @@ -2620,22 +2686,23 @@ def check_new_cls_arg(ctx, cont, args): def do_check_static_method_with_kwargs_cls_arg(expected_cls, method_name): - cls_name = OM_get_boxed_value(OM_get(expected_cls, "__name__")) - not_enough_arguments_msg = method_name + "(): not enough arguments" - not_a_type_object_msg = method_name + "(X): X is not a type object" - not_a_subtype_msg = method_name + "(object): object is not a subtype of " + cls_name + cls_name = OM_get_class_name(expected_cls) def check_new_cls_arg(ctx, cont, args, kwargs): args_len = len(args) if args_len == 0: - return sem_raise_with_message(ctx, class_TypeError, not_enough_arguments_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(): not enough arguments", [method_qualname])) cls = args[0] if not om_isinstance(cls, class_type): - return sem_raise_with_message(ctx, class_TypeError, not_a_type_object_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}({1}): {1} is not a type object", [method_name, "X"])) elif not om_issubclass(cls, expected_cls): - return sem_raise_with_message(ctx, class_TypeError, not_a_subtype_msg) + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}(object): object is not a subtype of {1}", + [method_name, cls_name])) else: return cont(ctx, args, kwargs) @@ -2661,8 +2728,6 @@ def magic_method(ctx, args): def do_magic_method_with_defaults(cls, method_name, code, n_no_defaults, defaults): check_method_self_arg = do_check_method_self_arg(cls, method_name) - - msg_expected_at_least = "expected at least " + str(n_no_defaults) + " positional argument(s), got " defaults_len = len(defaults) def magic_method(ctx, args): @@ -2674,7 +2739,8 @@ def push_defaults(ctx, args): i += 1 return code(ctx, args) else: - return sem_raise_with_message(ctx, class_TypeError, msg_expected_at_least + str(len(args) - 1)) + error_msg = tformat("expected at least {0} positional argument(s), got {1}", [str(n_no_defaults), str(len(args) - 1)]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) return check_method_self_arg(ctx, push_defaults, args) @@ -2701,8 +2767,6 @@ def magic_method(ctx, args, kwargs): def do_magic_method_with_aligned_kwargs(cls, method_name, code, n_posonly, kwarg_names, defaults): check_method_self_arg = do_check_method_with_kwargs_self_arg(cls, method_name) - msg_expected_at_least = "expected at least " + str(n_posonly) + " positional argument(s), got " - def magic_method(ctx, args, kwargs): def align_code(ctx, args, kwargs): if len(args) > n_posonly: @@ -2714,20 +2778,24 @@ def align_code(ctx, args, kwargs): if i >= len(args): args.append(defaults[j] if value_from_kwarg is absent else value_from_kwarg) elif value_from_kwarg is not absent: - error_msg = "argument for " + method_name + " given by name ('" + name + "') and position (" + str(i) + ")" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("argument for {0} given by name ('{1}') and position ({2})", [method_name, name, str(i)]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) i += 1 j += 1 if dict_len(kwargs) > 0: unknown_name = dict_keys(kwargs)[0] - error_msg = "'" + unknown_name + "' is an invalid keyword argument for " + method_name - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("'{0}' is an invalid keyword argument for {1}", [unknown_name, method_name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: return code(ctx, args) + elif n_posonly == 1: + error_msg = tformat("expected at least {0} positional argument, got {1}", ["1", str(len(args) - 1)]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: - return sem_raise_with_message(ctx, class_TypeError, msg_expected_at_least + str(len(args) - 1)) + error_msg = tformat("expected at least {0} positional arguments, got {1}", [str(n_posonly), str(len(args) - 1)]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) return check_method_self_arg(ctx, align_code, args, kwargs) @@ -2783,7 +2851,7 @@ def om_type_new_code(ctx, args): elif args_len == 4: return sem_raise(ctx, class_NotImplementedError) else: - return sem_raise_with_message(ctx, class_TypeError, "type() takes 1 or 3 arguments") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("type() takes 1 or 3 arguments")) om_type_new = do_magic_method(class_type, "__new__", om_type_new_code) @@ -2815,7 +2883,9 @@ def om_type_getattribute_code(ctx, args): # Get field name attr = getattribute_from_class_mro(self, name_value) if attr is absent: - return sem_raise_with_message(ctx, class_AttributeError, "type has no attribute '" + name_value + "'") + return sem_raise_with_tformat(ctx, + class_AttributeError, + tformat("type has no attribute '{0}'", [name_value])) # attr.__get__ attr_get = getattribute_from_obj_mro(attr, '__get__') @@ -2832,7 +2902,7 @@ def om_type_getattribute_code(ctx, args): else: return sem_simple_call(ctx, attr_get, [attr, om_None, self]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected one argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected one argument, got {0}', [str(len(args) - 1)])) om_type_getattribute = do_magic_method(class_type, "__getattribute__", om_type_getattribute_code) @@ -2843,7 +2913,7 @@ def om_type_setattr_code(ctx, args): value = args[2] if not om_isinstance(name, class_str): - return sem_raise_with_message(ctx, class_TypeError, "attribute name must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) name_value = OM_get_boxed_value(name) class_attr = getattribute_from_obj_mro(self, name_value) @@ -2853,8 +2923,8 @@ def set_on_self(): if is_builtin: # Prevent setting attribute on a builtin class cls_name = OM_get_boxed_value(OM_get(self, '__name__')) - msg = "can't set attributes of built-in/extension type '" + cls_name + "'" - return sem_raise_with_message(ctx, class_TypeError, msg) + msg = tformat("can't set attributes of built-in/extension type '{0}'", [cls_name]) + return sem_raise_with_tformat(ctx, class_TypeError, msg) else: OM_set(self, name_value, value) return cont_obj(ctx, om_None) @@ -2869,7 +2939,7 @@ def set_on_self(): else: return sem_simple_call(ctx, attr_set, [class_attr, self, value]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(len(args) - 1)])) om_type_setattr = do_magic_method(class_type, "__setattr__", om_type_setattr_code) @@ -2964,21 +3034,22 @@ def om_object_new(ctx, args, kwargs): args_len = len(args) if args_len == 0: - return sem_raise_with_message(ctx, class_TypeError, "object.__new__(): not enough arguments") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("object.__new__(): not enough arguments")) cls = args[0] if om_is(cls, class_object): if args_len > 1 or dict_len(kwargs) > 1: - return sem_raise_with_message(ctx, class_TypeError, "object() takes no argument") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0}() takes no argument ({1} given)", ["object", str(args_len - 1)])) else: return cont_obj(ctx, om(class_object)) elif not om_isinstance(cls, class_type): - return sem_raise_with_message(ctx, class_TypeError, "object.__new__(X): X is not a type object") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("object.__new__(X): X is not a type object")) elif OM_get_type_is_builtin(cls): # Builtin types should all have and use their own __new__ method due to populting hiddden attributes cls_name = OM_get_class_name(cls) - return sem_raise_with_message(ctx, class_TypeError, "object.__new__(" + cls_name + ") is not safe, use " + cls_name + ".__new__()") + error_msg = tformat("object.__new__({0}) is not safe, use {0}.__new__()", [cls_name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: return cont_obj(ctx, om(cls)) @@ -2996,7 +3067,7 @@ def om_object_getattribute_code(ctx, args): name = args[1] if not om_isinstance(name, class_str): - return sem_raise_with_message(ctx, class_TypeError, "attribute name must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) name_value = OM_get_boxed_value(name) @@ -3011,8 +3082,8 @@ def om_object_getattribute_code(ctx, args): self_clsname = OM_get(OM_get_object_class(self), '__name__') self_clsname_value = OM_get_boxed_value(self_clsname) - msg = "'" + self_clsname_value + "' object has no attribute '" + name_value + "'" - return sem_raise_with_message(ctx, class_AttributeError, msg) + msg = tformat("'{0}' object has no attribute '{1}'", [self_clsname_value, name_value]) + return sem_raise_with_tformat(ctx, class_AttributeError, msg) attr_get = getattribute_from_obj_mro(attr, '__get__') if attr_get is absent: @@ -3021,7 +3092,7 @@ def om_object_getattribute_code(ctx, args): # TODO: this might be a problem when self is actually "None" return sem_simple_call(ctx, attr_get, [attr, self, owner]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_object_getattribute = do_magic_method(class_object, "__getattribute__", om_object_getattribute_code) @@ -3034,7 +3105,7 @@ def om_object_setattr_code(ctx, args): value = args[2] if not om_isinstance(name, class_str): - return sem_raise_with_message(ctx, class_TypeError, "attribute name must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) name_value = OM_get_boxed_value(name) class_attr = getattribute_from_obj_mro(self, name_value) @@ -3053,7 +3124,7 @@ def set_on_self(): else: return sem_simple_call(ctx, attr_set, [class_attr, self, value]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(len(args) - 1)])) om_object_setattr = do_magic_method(class_object, "__setattr__", om_object_setattr_code) @@ -3062,7 +3133,7 @@ def om_object_str_code(ctx, args): if len(args) == 1: return sem_repr(ctx, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_object_str = do_magic_method(class_object, "__repr__", om_object_str_code) @@ -3079,7 +3150,7 @@ def om_object_repr_code(ctx, args): if len(args) == 1: return cont_str(ctx, om_format_object_repr(args[0], ctx.rte)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_object_repr = do_magic_method(class_object, "__repr__", om_object_repr_code) @@ -3087,7 +3158,7 @@ def om_object_eq_code(ctx, args): if len(args) == 2: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_object_eq = do_magic_method(class_object, "__eq__", om_object_eq_code) @@ -3110,7 +3181,7 @@ def invert_result(invert_rte, bool_res): return sem_bool(with_cont(ctx, invert_result), res) return sem_simple_call(with_cont(ctx, check_result), self_eq, [self, other]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_object_ne = do_magic_method(class_object, "__ne__", om_object_ne_code) @@ -3123,7 +3194,7 @@ def getter(ctx, instance): return cont_obj(ctx, om_getter(instance)) def setter(ctx, instance, value): - return sem_raise_with_message(ctx, class_AttributeError, name + " assignment unsupported") + return sem_raise_with_tformat(ctx, class_AttributeError, tformat("{0} assignment unsupported", [name])) return om_getset_descriptor(name, objclass, getter, setter) @@ -3148,10 +3219,10 @@ def om_getset_descriptor_get_code(ctx, args): name = OM_get_getset_descriptor_name(self) wrong_cls_name = OM_get_object_class_name(instance) expected_cls_name = OM_get_boxed_value(OM_get(objclass, "__name__")) - error_msg = "descriptor '" + name + "' for '" + expected_cls_name + "' objects doesn't apply to a '" + wrong_cls_name + "' object" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("descriptor '{0}' for '{1}' objects doesn't apply to a '{2}' object", [name, expected_cls_name, wrong_cls_name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(args_len - 1)])) om_getset_descriptor_get = do_magic_method(class_getset_descriptor, "__get__", om_getset_descriptor_get_code) @@ -3173,17 +3244,17 @@ def om_getset_descriptor_set_code(ctx, args): name = OM_get_getset_descriptor_name(self) wrong_cls_name = OM_get_object_class_name(instance) expected_cls_name = OM_get_boxed_value(OM_get(objclass, "__name__")) - error_msg = "descriptor '" + name + "' for '" + expected_cls_name + "' objects doesn't apply to a '" + wrong_cls_name + "' object" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("descriptor '{0}' for '{1}' objects doesn't apply to a '{2}' object", [name, expected_cls_name, wrong_cls_name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(args_len - 1)])) om_getset_descriptor_set = do_magic_method(class_getset_descriptor, "__set__", om_getset_descriptor_set_code) # class_TextIOWrapper def raise_operation_on_closed_file(ctx): - return sem_raise_with_message(ctx, class_ValueError, "I/O operation on closed file.") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("I/O operation on closed file.")) def is_read_file_mode(mode): return mode == 'r' @@ -3200,14 +3271,14 @@ def om_TextIOWrapper_repr(ctx, args): self = args[0] return cont_str(ctx, om_format_TextIOWrapper(self)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_enter(ctx, args): if len(args) == 1: self = args[0] return cont_obj(ctx, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_exit(ctx, args): if len(args) > 0: @@ -3215,7 +3286,7 @@ def om_TextIOWrapper_exit(ctx, args): OM_set_TextIOWrapper_opened(self, False) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "expected at least 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at least 1 argument, got {0}', [str(len(args) - 1)])) def om_TextIOWrapper_close(ctx, args): if len(args) == 1: @@ -3223,7 +3294,7 @@ def om_TextIOWrapper_close(ctx, args): OM_set_TextIOWrapper_opened(self, False) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_read(ctx, args): if len(args) == 1: @@ -3238,9 +3309,9 @@ def om_TextIOWrapper_read(ctx, args): elif om_isinstance(size, class_int): read_size = int_to_num(OM_get_boxed_value(size)) else: - return sem_raise_with_message(ctx, class_TypeError, "argument should be integer or None") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("argument should be integer or None")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) opened = OM_get_TextIOWrapper_opened(self) if opened: @@ -3269,7 +3340,7 @@ def om_TextIOWrapper_read(ctx, args): # no longer exists at a read() after being opened return cont_str(ctx, "") else: - return sem_raise_with_message(ctx, class_UnsupportedOperation, "not readable") + return sem_raise_with_tformat(ctx, class_UnsupportedOperation, tformat("not readable")) else: return raise_operation_on_closed_file(ctx) @@ -3303,7 +3374,7 @@ def TextIOWrapper_read_next_line(ctx, textiowrapper): # no longer exists at a read() after being opened return cont_obj(ctx, "") else: - return sem_raise_with_message(ctx, class_UnsupportedOperation, "not readable") + return sem_raise_with_tformat(ctx, class_UnsupportedOperation, tformat("not readable")) else: return raise_operation_on_closed_file(ctx) @@ -3316,7 +3387,7 @@ def convert_str(rte, s): return TextIOWrapper_read_next_line(with_cont(ctx, convert_str), self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_next(ctx, args): if len(args) == 1: @@ -3331,14 +3402,14 @@ def check_result(rte, s): return TextIOWrapper_read_next_line(with_cont(ctx, check_result), self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_iter(ctx, args): if len(args) == 1: self = args[0] return cont_obj(ctx, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_TextIOWrapper_write(ctx, args): @@ -3373,13 +3444,13 @@ def om_TextIOWrapper_write(ctx, args): # fix that once we have a better filesystem in codeBoot? return cont_int(ctx, int_from_num(content_length)) else: - return sem_raise_with_message(ctx, class_UnsupportedOperation, "not writable") + return sem_raise_with_tformat(ctx, class_UnsupportedOperation, tformat("not writable")) else: return raise_operation_on_closed_file(ctx) else: - return sem_raise_with_message(ctx, class_TypeError, "write() argument must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("write() argument must be str")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) # class _cvs.reader def om_csv_reader_iter(ctx, args): @@ -3387,7 +3458,7 @@ def om_csv_reader_iter(ctx, args): self = args[0] return cont_obj(ctx, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) def om_csv_parse_line(ctx, self, init_line, fetch_line): # IF YOU NEED HELP DEBUGGING THIS FUNCTION, ASK Olivier Melançon @@ -3411,8 +3482,8 @@ def om_csv_parse_line(ctx, self, init_line, fetch_line): # Since this requires a call to sem_next, we have no choice but to write the loop over # characters in CPS. - unexpected_end_of_data_msg = "unexpected end of data" - unquoted_newline_msg = "new-line character seen in unquoted field" + unexpected_end_of_data_msg = tformat("unexpected end of data") + unquoted_newline_msg = tformat("new-line character seen in unquoted field") dialect = OM_get_csv_reader_dialect(self) @@ -3489,7 +3560,7 @@ def do_break(): escaped_c = line[i] if strict and not quoted_element and is_lineterminator(escaped_c): # In strict mode, escapechar cannot be used to escape unquoted linebreaks - return sem_raise_with_message(ctx, class_csv_Error, unexpected_end_of_data_msg) + return sem_raise_with_tformat(ctx, class_csv_Error, unexpected_end_of_data_msg) else: chars.append(escaped_c) escaping = False @@ -3507,7 +3578,7 @@ def do_break(): if all_lineterminators(line, i + 1, line_len): i = line_len else: - return sem_raise_with_message(ctx, class_csv_Error, unquoted_newline_msg) + return sem_raise_with_tformat(ctx, class_csv_Error, unquoted_newline_msg) elif c == delimiter and not current_quote_unclosed: # Delimiter i = i + 1 @@ -3537,9 +3608,9 @@ def do_break(): i = next_i return do_continue() else: - return sem_raise_with_message(ctx, - class_csv_Error, - "'" + delimiter + "' expected after '" + quotechar + "'") + return sem_raise_with_tformat(ctx, + class_csv_Error, + tformat("'{0}' expected after '{1}'", [delimiter, quotechar])) else: return do_break() else: @@ -3576,7 +3647,7 @@ def success(rte, new_line): def fail(rte): if strict: - return sem_raise_with_message(with_rte(ctx, rte), class_csv_Error, unexpected_end_of_data_msg) + return sem_raise_with_tformat(with_rte(ctx, rte), class_csv_Error, unexpected_end_of_data_msg) else: return join_element() @@ -3587,7 +3658,7 @@ def success(rte, new_line): def fail(rte): if strict: - return sem_raise_with_message(with_rte(ctx, rte), class_csv_Error, unexpected_end_of_data_msg) + return sem_raise_with_tformat(with_rte(ctx, rte), class_csv_Error, unexpected_end_of_data_msg) else: chars.append("\n") # as per cPython, in non-strict mode trailing escapes are replaced by \n return join_element() @@ -3614,14 +3685,14 @@ def get_next(rte, nxt_line): return success(rte, OM_get_boxed_value(nxt_line)) else: - return sem_raise_with_message(with_rte(ctx, rte), class_csv_Error, "iterator should return strings") + return sem_raise_with_tformat(with_rte(ctx, rte), class_csv_Error, tformat('iterator should return strings')) return sem_next(with_cont(ctx, get_next), line_iterator, None) return fetch_line(ctx, lambda rte, fst_line: om_csv_parse_line(with_rte(ctx, rte), self, fst_line, fetch_line), lambda rte: sem_raise(ctx, class_StopIteration)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) # class _csv.writer def csv_element_quoted(text, delimiter, lineterminator, quotechar, doublequote): @@ -3642,7 +3713,7 @@ def csv_element_quoted(text, delimiter, lineterminator, quotechar, doublequote): def om_csv_format_element(ctx, text, delimiter, doublequote, escapechar, lineterminator, quotechar, must_quote, must_not_quote): - need_to_escape_msg = "need to escape, but no escapechar set" + need_to_escape_msg = tformat("need to escape, but no escapechar set") text_len = len(text) line_terminator_len = len(lineterminator) @@ -3678,15 +3749,15 @@ def append_escaped(c): if quoted: chars.append(c) elif not append_escaped(c): - return sem_raise_with_message(ctx, class_csv_Error, need_to_escape_msg) + return sem_raise_with_tformat(ctx, class_csv_Error, need_to_escape_msg) elif c == quotechar: if quoted: if doublequote: chars.append(quotechar + quotechar) elif not append_escaped(quotechar): - return sem_raise_with_message(ctx, class_csv_Error, need_to_escape_msg) + return sem_raise_with_tformat(ctx, class_csv_Error, need_to_escape_msg) elif not append_escaped(quotechar): - return sem_raise_with_message(ctx, class_csv_Error, need_to_escape_msg) + return sem_raise_with_tformat(ctx, class_csv_Error, need_to_escape_msg) elif c == escapechar: chars.append(escapechar + escapechar) else: @@ -3718,7 +3789,7 @@ def parse_string(ctx, data): lineterminator, quotechar, must_quote, quote_none) if len(strings_data) == 1 and len(strings_data[0][0]) == 0: if quote_none or quotechar is None: - return sem_raise_with_message(ctx, class_csv_Error, "single empty field record must be quoted") + return sem_raise_with_tformat(ctx, class_csv_Error, tformat("single empty field record must be quoted")) else: return write_result(ctx.rte, [quotechar + quotechar]) else: @@ -3736,7 +3807,7 @@ def cont(rte, val_as_str): def catch_TypeError(exc): if om_isinstance(exc, class_TypeError): - return sem_raise_with_message(ctx, class_csv_Error, "iterable expected") + return sem_raise_with_tformat(ctx, class_csv_Error, tformat("iterable expected")) else: return sem_raise_unsafe(ctx.rte, exc) @@ -3770,7 +3841,7 @@ def om_csv_writer_writerow(ctx, args): quotechar, quote_all, quote_nonumeric, quote_none) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) def om_csv_writer_writerows(ctx, args): if len(args) == 2: @@ -3800,7 +3871,7 @@ def write_one_row(ctx, row): return om_foreach_iterable(with_cont(ctx, lambda rte: cont_obj(ctx, om_None)), write_one_row, rows) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) # class_NotImplementedType def om_format_NotImplementedType(self, rte): @@ -3825,7 +3896,7 @@ def om_bool_new_code(ctx, args): elif len(args) == 2: return sem_bool(ctx, args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected at most 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected at most 1 argument, got {1}', ["bool", str(len(args) - 1)])) om_bool_new = do_static_magic_method(class_bool, "__new__", om_bool_new_code) @@ -3842,7 +3913,7 @@ def om_bool_repr_code(ctx, args): self = args[0] return cont_str(ctx, om_format_bool_repr(self, ctx.rte)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_bool_repr = do_magic_method(class_bool, "__repr__", om_bool_repr_code) @@ -3853,7 +3924,7 @@ def om_bool_bool_code(ctx, args): self = args[0] return cont_obj(ctx, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_bool_bool = do_magic_method(class_bool, "__bool__", om_bool_bool_code) @@ -3864,7 +3935,7 @@ def om_int_neg_code(ctx, args): result = int_neg(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_boxval(class_int, result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_int_neg = do_magic_method(class_int, "__neg__", om_int_neg_code) @@ -3874,7 +3945,7 @@ def om_int_invert_code(ctx, args): result = int_not(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_boxval(class_int, result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_int_invert = do_magic_method(class_int, "__invert__", om_int_invert_code) @@ -3882,14 +3953,14 @@ def om_int_pos_code(ctx, args): if len(args) == 1: return ctx.cont(ctx.rte, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_int_pos = do_magic_method(class_int, "__pos__", om_int_pos_code) # compute pow_mod with unboxed value. def compute_pow_mod(ctx, num, power, mod): if int_is_zero(mod): - return sem_raise_with_message(ctx, class_ValueError, "pow() 3rd argument cannot be 0") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("pow() 3rd argument cannot be 0")) elif int_is_nonneg(power): result = int_pow_mod(num, power, mod) return cont_int(ctx, result) @@ -3901,10 +3972,10 @@ def compute_pow_mod(ctx, num, power, mod): # NOTE: NaN should not happen # raise an Overflow error when it cannot be exactly represent as a floating point if float_is_infinite(fl_num_mod) or float_is_nan(fl_num_mod) or float_is_nan(fl_power): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) elif float_is_neg(fl_power): # modular inverse computation - return sem_raise_with_message(ctx, class_NotImplementedError, "modular inverse unimplemented") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("modular inverse unimplemented")) elif float_is_infinite(fl_power): # the result tends to 0 when power tends to -Infinity return cont_float(ctx, float_from_num(0.0)) @@ -3925,7 +3996,7 @@ def compute_pow(ctx, num, power): # NOTE: NaN should not happen # raise an Overflow error when it cannot be exactly represent as a floating point if float_is_infinite(fl_num) or float_is_nan(fl_num) or float_is_nan(fl_power): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) elif not float_is_finite(fl_power): # the result tends to 0 when power tends to -Infinity return cont_float(ctx, float_from_num(0.0)) @@ -3936,9 +4007,9 @@ def compute_pow(ctx, num, power): def om_int_pow_code(ctx, args): args_len = len(args) if args_len < 2: - return sem_raise_with_message(ctx, class_TypeError, "expected at least 1 argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at least 1 argument, got {0}', [str(args_len - 1)])) elif args_len > 3: - return sem_raise_with_message(ctx, class_TypeError, "expected at most 3 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at most 3 arguments, got {0}', [str(args_len - 1)])) else: self = args[0] power = args[1] @@ -3955,7 +4026,7 @@ def om_int_pow_code(ctx, args): mod_value = OM_get_boxed_value(mod) return compute_pow_mod(ctx, self_value, power_value, mod_value) elif om_isinstance(mod, class_float): - return sem_raise_with_message(ctx, class_TypeError, "3rd argument not allowed unless all arguments are integers") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("3rd argument not allowed unless all arguments are integers")) return cont_obj(ctx, om_NotImplemented) om_int_pow = do_magic_method(class_int, "__pow__", om_int_pow_code) @@ -3964,9 +4035,9 @@ def om_int_pow_code(ctx, args): def om_int_rpow_code(ctx, args): args_len = len(args) if args_len < 2: - return sem_raise_with_message(ctx, class_TypeError, "expected at least 1 argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at least 1 argument, got {0}', [str(args_len - 1)])) elif args_len > 3: - return sem_raise_with_message(ctx, class_TypeError, "expected at most 3 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at most 3 arguments, got {0}', [str(args_len - 1)])) else: self = args[0] num = args[1] @@ -3983,7 +4054,7 @@ def om_int_rpow_code(ctx, args): mod_value = OM_get_boxed_value(mod) return compute_pow_mod(ctx, num_value, self_value, mod_value) elif om_isinstance(mod, class_float): - return sem_raise_with_message(ctx, class_TypeError, "3rd argument not allowed unless all arguments are integers") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("3rd argument not allowed unless all arguments are integers")) return cont_obj(ctx, om_NotImplemented) om_int_rpow = do_magic_method(class_int, "__rpow__", om_int_rpow_code) @@ -4050,7 +4121,7 @@ def apply_round(rte, n): return sem_index(with_cont(ctx, apply_round), ndigits) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_int_round = do_magic_method(class_int, "__round__", om_int_round_code) @@ -4091,7 +4162,7 @@ def om_tuple_repr_code(ctx, args): elements = OM_get_tuple_seq(self) return om_tuple_elements_repr(ctx, elements, [], 0) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_tuple_repr = do_magic_method(class_tuple, "__repr__", om_tuple_repr_code) @@ -4117,8 +4188,7 @@ def om_tuple_eq_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, - "__eq__() takes 1 argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes {1} argument ({2} given)', ["__eq__()", "1", str(args_len - 1)])) om_tuple_eq = do_magic_method(class_tuple, "__eq__", om_tuple_eq_code) @@ -4136,7 +4206,7 @@ def alloc(rte, seq): return ctx.cont(rte, om_tuple_subtype(cls, seq)) return om_unpack_iterable(with_cont(ctx, alloc), args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, "tuple expected at most 1 argument, got " + str(args_len)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected at most 1 argument, got {1}', ["tuple", str(args_len)])) om_tuple_new = do_static_magic_method(class_tuple, "__new__", om_tuple_new_code) @@ -4154,7 +4224,7 @@ def om_tuple_len_code(ctx, args): return cont_int(ctx, int_from_num(elements_len)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_tuple_len = do_magic_method(class_tuple, "__len__", om_tuple_len_code) @@ -4192,7 +4262,7 @@ def cont(rte, val): elements = OM_get_tuple_seq(self) elements_len = int_from_num(len(elements)) if int_ge(item_box_index, elements_len): - return sem_raise_with_message(ctx, class_IndexError, "tuple index out of range") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("{0} index out of range", ["tuple"])) elif int_is_nonneg(item_box_index): return cont_obj(ctx, elements[int_to_num(item_box_index)]) else: @@ -4200,12 +4270,12 @@ def cont(rte, val): if int_is_nonneg(reversed_index): return cont_obj(ctx, elements[int_to_num(reversed_index)]) else: - return sem_raise_with_message(ctx, class_IndexError, "tuple index out of range") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("{0} index out of range", ["tuple"])) return sem_index(with_cont(ctx, cont), item) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_tuple_getitem = do_magic_method(class_tuple, "__getitem__", om_tuple_getitem_code) @@ -4228,7 +4298,7 @@ def om_tuple_add_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_tuple_add = do_magic_method(class_tuple, "__add__", om_tuple_add_code) @@ -4257,7 +4327,7 @@ def cont(rte, n): return cont_tuple(with_rte(ctx, rte), []) return sem_maybe_index(with_cont(ctx, cont), other) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_tuple_mul = do_magic_method(class_tuple, "__mul__", om_tuple_mul_code) @@ -4291,8 +4361,7 @@ def om_tuple_count_code(ctx, args): return count_in_sequence(ctx, self_seq, self_len, val) else: - return sem_raise_with_message(ctx, class_TypeError, - "count() takes exactly one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes exactly one argument ({1} given)', ["count()", str(args_len - 1)])) om_tuple_count = do_magic_method(class_tuple, "count", om_tuple_count_code) @@ -4331,18 +4400,15 @@ def clamp_index(index, len_): return 0 -def gen_om_sequence_index(om_class, seq_getter, len_getter): - cls_name = OM_get_boxed_value(OM_get(om_class, "__name__")) - not_in_msg = " is not in " + cls_name - +def gen_om_sequence_index(om_class, seq_getter, len_getter, container_type_name): def code(ctx, args): args_len = len(args) def check_result(rte, res): if res is absent: def do_error(err_rte, repr_): - return sem_raise_with_message(with_rte(ctx, err_rte), class_ValueError, - OM_get_boxed_value(repr_) + not_in_msg) + return sem_raise_with_tformat(with_rte(ctx, err_rte), class_ValueError, + tformat("{0} is not in {1}", [OM_get_boxed_value(repr_), container_type_name])) return sem_repr(Context(rte, do_error, ctx.ast), value) else: return cont_int(with_rte(ctx, rte), int_from_num(res)) @@ -4378,13 +4444,12 @@ def get_stop(stop_rte, om_stop): return sem_index(Context(rte, get_stop, ctx.ast), stop) return sem_index(with_cont(ctx, get_start), start) else: - return sem_raise_with_message(ctx, class_TypeError, - "index() expected between 1 and 3 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('index() expected between 1 and 3 arguments, got {0}', [str(args_len - 1)])) return do_magic_method(om_class, 'index', code) -om_tuple_index = gen_om_sequence_index(class_tuple, OM_get_tuple_seq, lambda t, s: len(s)) +om_tuple_index = gen_om_sequence_index(class_tuple, OM_get_tuple_seq, lambda t, s: len(s), "tuple") # class_list methods @@ -4499,7 +4564,7 @@ def alloc(rte, seq): return make_list(ctx, seq) return om_unpack_iterable(with_cont(ctx, alloc), args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, "list expected at most 1 argument, got " + str(args_len)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected at most 1 argument, got {1}', ["list", str(args_len)])) om_list_new = do_static_magic_method(class_list, "__new__", om_list_new_code) @@ -4524,8 +4589,7 @@ def om_list_eq_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, - "__eq__() takes 1 argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes {1} argument ({2} given)', ["__eq__()", "1", str(args_len - 1)])) om_list_eq = do_magic_method(class_list, "__eq__", om_list_eq_code) @@ -4560,7 +4624,7 @@ def om_list_repr_code(ctx, args): elements = OM_get_list_seq(self) return om_list_elements_repr(ctx, elements, [], 0) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_list_repr = do_magic_method(class_list, "__repr__", om_list_repr_code) @@ -4597,7 +4661,7 @@ def cont(rte, item_index): next_ctx = with_rte(ctx, rte) if int_ge(index, self_len): - return sem_raise_with_message(next_ctx, class_IndexError, "list index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["list"])) elif int_is_nonneg(index): return cont_obj(next_ctx, elements[int_to_num(index)]) else: @@ -4605,11 +4669,13 @@ def cont(rte, item_index): if int_is_nonneg(reversed_index): return cont_obj(next_ctx, elements[int_to_num(reversed_index)]) else: - return sem_raise_with_message(next_ctx, class_IndexError, "list index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["list"])) return sem_index(with_cont(ctx, cont), item) else: - return sem_raise_with_message(ctx, class_TypeError, "__getitem__() takes exactly one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, + tformat('{0}() takes exactly {1} argument ({2} given)', + ["__getitem__", "1", str(args_len - 1)])) om_list_getitem = do_magic_method(class_list, "__getitem__", om_list_getitem_code) @@ -4677,12 +4743,7 @@ def get_assignment_values(elements_rte, elements): elements) return cont_obj(with_rte(ctx, elements_rte), om_None) else: - return sem_raise_with_message(with_rte(ctx, elements_rte), - class_ValueError, - "attempt to assign sequence of size " - + int_to_string(elements_len, 10) - + " to extended slice of size " - + int_to_string(slice_len, 10)) + return sem_raise_with_tformat(with_rte(ctx, elements_rte), class_ValueError, tformat('attempt to assign sequence of size {0} to extended slice of size {1}', [int_to_string(elements_len, 10), int_to_string(slice_len, 10)])) return om_unpack_iterable(Context(slice_rte, get_assignment_values, ctx.ast), value) return compute_slice_indices(with_cont(ctx, get_slice_indices), @@ -4699,7 +4760,7 @@ def cont(rte, item_index): next_ctx = with_rte(ctx, rte) if int_ge(index, self_len): - return sem_raise_with_message(next_ctx, class_IndexError, "list index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["list"])) elif int_is_nonneg(index): elements[int_to_num(index)] = value return cont_obj(next_ctx, om_None) @@ -4709,10 +4770,12 @@ def cont(rte, item_index): elements[int_to_num(reversed_index)] = value return cont_obj(next_ctx, om_None) else: - return sem_raise_with_message(next_ctx, class_IndexError, "list index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["list"])) return sem_index(with_cont(ctx, cont), item) else: - return sem_raise_with_message(ctx, class_TypeError, "__setitem__() takes exactly two argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, + tformat('{0}() takes exactly {1} arguments ({2} given)', + ["__setitem__", "2", str(args_len - 1)])) om_list_setitem = do_magic_method(class_list, "__setitem__", om_list_setitem_code) @@ -4723,8 +4786,7 @@ def om_list_len_code(ctx, args): elements_len = OM_get_list_len(self) return cont_int(ctx, int_from_num(elements_len)) else: - return sem_raise_with_message(ctx, class_TypeError, - "__len__() takes no argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes no argument ({1} given)', ["__len__", str(args_len - 1)])) om_list_len = do_magic_method(class_list, "__len__", om_list_len_code) @@ -4755,8 +4817,8 @@ def om_list_add_code(ctx, args): else: - return sem_raise_with_message(ctx, class_TypeError, - "__add__() takes one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}() takes {1} positional arguments but {2} was given", ["__add__()", "1", str(args_len - 1)])) om_list_add = do_magic_method(class_list, "__add__", om_list_add_code) @@ -4792,8 +4854,7 @@ def cont(rte, other_seq): return om_unpack_iterable(with_cont(ctx, cont), other) else: - return sem_raise_with_message(ctx, class_TypeError, - "extend() takes one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('extend() takes one argument ({0} given)', [str(args_len - 1)])) om_list_extend = do_magic_method(class_list, "extend", om_list_extend_code) @@ -4808,8 +4869,8 @@ def cont(rte, _): return om_list_extend_code(with_cont(ctx, cont), args) else: - return sem_raise_with_message(ctx, class_TypeError, - "__iadd__() takes one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, + tformat("{0}() takes {1} positional arguments but {2} was given", ["__iadd__()", "1", str(args_len - 1)])) om_list_iadd = do_magic_method(class_list, "__iadd__", om_list_iadd_code) @@ -4840,7 +4901,7 @@ def cont(rte, n_int): return cont_list(with_rte(ctx, rte), [], 0) return sem_maybe_index(with_cont(ctx, cont), n) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_list_mul = do_magic_method(class_list, "__mul__", om_list_mul_code) @@ -4864,8 +4925,7 @@ def om_list_append_code(ctx, args): return ctx.cont(ctx.rte, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, - "append() takes exactly one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('append() takes exactly one argument ({0} given)', [str(args_len - 1)])) om_list_append = do_magic_method(class_list, "append", om_list_append_code) @@ -4887,7 +4947,7 @@ def om_list_pop_code(ctx, args): list_seq_maybe_shrink(self, elements, last_index, inner_len) return cont_obj(ctx, last) else: - return sem_raise_with_message(ctx, class_IndexError, "pop item from empty list") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("pop item from empty list")) elif args_len == 2: def do_pop(rte, om_index): self = args[0] @@ -4899,7 +4959,7 @@ def do_pop(rte, om_index): next_ctx = with_rte(ctx, rte) if index >= len_: - return sem_raise_with_message(next_ctx, class_IndexError, "pop index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["pop"])) elif index >= 0: poped_item = elements[index] list_shift_left(self, elements, len_, inner_len, index, 1) @@ -4911,13 +4971,12 @@ def do_pop(rte, om_index): list_shift_left(self, elements, len_, inner_len, reversed_index, 1) return cont_obj(next_ctx, poped_item) else: - return sem_raise_with_message(next_ctx, class_IndexError, "pop index out of range") + return sem_raise_with_tformat(next_ctx, class_IndexError, tformat("{0} index out of range", ["pop"])) return sem_index(with_cont(ctx, do_pop), args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, - "pop() expected at most 1 argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected at most 1 argument, got {1}', ["pop()", str(args_len - 1)])) om_list_pop = do_magic_method(class_list, "pop", om_list_pop_code) @@ -4956,14 +5015,13 @@ def do_insert(rte, om_index): return sem_index(with_cont(ctx, do_insert), args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, - "insert() expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() expected {1} arguments, got {2}', ["insert", "2", str(args_len - 1)])) om_list_insert = do_magic_method(class_list, "insert", om_list_insert_code) -om_list_index = gen_om_sequence_index(class_list, OM_get_list_seq, lambda l, s: OM_get_list_len(l)) +om_list_index = gen_om_sequence_index(class_list, OM_get_list_seq, lambda l, s: OM_get_list_len(l), "list") def om_list_contains_code(ctx, args): @@ -4980,8 +5038,7 @@ def get_result(rte, res): return sequence_search(with_cont(ctx, get_result), seq, target, 0, len_) else: - return sem_raise_with_message(ctx, class_TypeError, - "__contains__() takes 1 argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes {1} argument ({2} given)', ["__contains__()", "1", str(args_len - 1)])) om_list_contains = do_magic_method(class_list, '__contains__', om_list_contains_code) @@ -4992,7 +5049,7 @@ def om_list_remove_code(ctx, args): if args_len == 2: def get_result(rte, res): if res is absent: - return sem_raise_with_message(with_rte(ctx, rte), class_ValueError, "list.remove(x): x not in list") + return sem_raise_with_tformat(with_rte(ctx, rte), class_ValueError, tformat('list.remove(x): x not in list')) else: list_shift_left(self, seq, len_, len(seq), res, 1) return cont_obj(with_rte(ctx, rte), om_None) @@ -5005,8 +5062,7 @@ def get_result(rte, res): return sequence_search(with_cont(ctx, get_result), seq, target, 0, len_) else: - return sem_raise_with_message(ctx, class_TypeError, - "remove() takes 1 argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes {1} argument ({2} given)', ["remove()", "1", str(args_len - 1)])) om_list_remove = do_magic_method(class_list, 'remove', om_list_remove_code) @@ -5023,8 +5079,7 @@ def om_list_copy_code(ctx, args): return cont_list(ctx, seq_copy, len_) else: - return sem_raise_with_message(ctx, class_TypeError, - "copy() takes no argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes no argument ({1} given)', ["copy", str(args_len - 1)])) om_list_copy = do_magic_method(class_list, "copy", om_list_copy_code) @@ -5040,8 +5095,7 @@ def om_list_clear_code(ctx, args): return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, - "clear() takes no argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes no argument ({1} given)', ["clear", str(args_len - 1)])) om_list_clear = do_magic_method(class_list, "clear", om_list_clear_code) @@ -5066,8 +5120,7 @@ def om_list_reverse_code(ctx, args): return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, - "reverse() takes no argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes no argument ({1} given)', ["reverse", str(args_len - 1)])) om_list_reverse = do_magic_method(class_list, "reverse", om_list_reverse_code) @@ -5083,8 +5136,7 @@ def om_list_count_code(ctx, args): return count_in_sequence(ctx, self_seq, self_len, val) else: - return sem_raise_with_message(ctx, class_TypeError, - "count() takes exactly one argument (" + str(args_len - 1) + " given)") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} takes exactly one argument ({1} given)', ["count()", str(args_len - 1)])) om_list_count = do_magic_method(class_list, "count", om_list_count_code) @@ -5139,7 +5191,7 @@ def check_step(alloc_rte, step_int): step_value = OM_get_boxed_value(step_int) if int_is_zero(step_value): - return sem_raise_with_message(ctx, class_ValueError, "range() arg 3 must not be zero") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("range() arg 3 must not be zero")) else: return cont_obj(with_rte(ctx, alloc_rte), om_range(start_value, stop_value, step_value)) @@ -5158,7 +5210,7 @@ def check_step(alloc_rte, step_int): else: return sem_index(with_cont(ctx, get_start), start) else: - return sem_raise_with_message(ctx, class_TypeError, "range expected 1 to 3 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected 1 to 3 arguments, got {1}', ["range", str(len(args) - 1)])) om_range_new = do_static_magic_method(class_range, "__new__", om_range_new_code) @@ -5186,7 +5238,7 @@ def om_range_repr_code(ctx, args): self = args[0] return cont_str(ctx, om_format_range_repr(self, ctx.rte)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_range_repr = do_magic_method(class_range, "__repr__", om_range_repr_code) @@ -5226,7 +5278,7 @@ def om_range_eq_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_range_eq = do_magic_method(class_range, "__eq__", om_range_eq_code) @@ -5255,7 +5307,7 @@ def om_range_len_code(ctx, args): return cont_int(ctx, compute_range_len(start, stop, step)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_range_len = do_magic_method(class_range, "__len__", om_range_len_code) @@ -5336,13 +5388,13 @@ def get_item(rte, index): res = compute_range_item(start, stop, step, index_value) if res is None: - return sem_raise_with_message(ctx, class_IndexError, "range object index out of range") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("range object index out of range")) else: return cont_int(ctx, res) return sem_index(with_cont(ctx, get_item), item) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_range_getitem = do_magic_method(class_range, "__getitem__", om_range_getitem_code) @@ -5371,7 +5423,7 @@ def om_slice_new_code(ctx, args): return cont_obj(ctx, om_slice(start, stop, step)) else: - return sem_raise_with_message(ctx, class_TypeError, "slice takes from 1 to 3 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('slice takes from 1 to 3 arguments, got {0}', [str(args_len - 1)])) om_slice_new = do_static_magic_method(class_slice, '__new__', om_slice_new_code) @@ -5399,7 +5451,7 @@ def get_step_repr(step_rte, step_repr): return sem_repr(make_out_of_ast_context(start_rte, get_stop_repr), stop) return sem_repr(with_cont(ctx, get_start_repr), start) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_slice_repr = do_magic_method(class_slice, '__repr__', om_slice_repr_code) @@ -5421,7 +5473,7 @@ def compute_slice_indices_aux(ctx, start, stop, step, len_): if step is None: real_step = int_from_num(1) elif int_is_zero(step): - return sem_raise_with_message(ctx, class_ValueError, "slice step cannot be 0") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("slice step cannot be 0")) else: real_step = step @@ -5480,8 +5532,7 @@ def get_int_or_none(rte): else: def get_index(rte, index): if om_is(index, absent): - return sem_raise_with_message(ctx, class_TypeError, - "slice indices must be integers or None or have an __index__ method") + return sem_raise_with_tformat(ctx, class_TypeError, tformat('slice indices must be integers or None or have an __index__ method')) else: args[i] = OM_get_boxed_value(index) return cont(rte) @@ -5505,7 +5556,7 @@ def om_slice_indices_code(ctx, args): def check_len(rte, len_): len_val = OM_get_boxed_value(len_) if int_is_neg(len_val): - return sem_raise_with_message(with_rte(ctx, rte), class_ValueError, "length should not be negative") + return sem_raise_with_tformat(with_rte(ctx, rte), class_ValueError, tformat('length should not be negative')) else: def cast_to_tuple(rte, res): return cont_tuple(with_rte(ctx, rte), [om_int(res[0]), om_int(res[1]), om_int(res[2])]) @@ -5517,7 +5568,7 @@ def cast_to_tuple(rte, res): return compute_slice_indices(Context(rte, cast_to_tuple, ctx.ast), start, stop, step, len_val) return sem_index(with_cont(ctx, check_len), args[1]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_slice_indices = do_magic_method(class_slice, "indices", om_slice_indices_code) @@ -5543,7 +5594,7 @@ def om_map_new_code(ctx, args): args_len = len(args) if args_len < 3: - return sem_raise_with_message(ctx, class_TypeError, "map() must have at least two arguments.") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} must have at least two arguments", ["map()"])) else: cls = args[0] fn = args[1] @@ -5563,7 +5614,7 @@ def om_map_iter_code(ctx, args): if len(args) == 1: return cont_obj(ctx, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_map_iter = do_magic_method(class_map, "__iter__", om_map_iter_code) @@ -5580,7 +5631,7 @@ def do_call(rte, fn_args): return cps_map(with_cont(ctx, do_call), sem_next_no_default, iterators) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_map_next = do_magic_method(class_map, "__next__", om_map_next_code) @@ -5593,7 +5644,7 @@ def om_filter_new_code(ctx, args): args_len = len(args) if args_len != 3: - return sem_raise_with_message(ctx, class_TypeError, "filter() expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() expected {1} arguments, got {2}', ["filter", "2", str(args_len - 1)])) else: cls = args[0] fn = args[1] @@ -5613,7 +5664,7 @@ def om_filter_iter_code(ctx, args): if len(args) == 1: return cont_obj(ctx, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_filter_iter = do_magic_method(class_filter, "__iter__", om_filter_iter_code) @@ -5651,7 +5702,7 @@ def check_truthiness(rte, bool_val): return sem_next_no_default(with_cont(ctx, get_next), iterator) return do_filter_call() else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_filter_next = do_magic_method(class_filter, "__next__", om_filter_next_code) @@ -5665,7 +5716,7 @@ def om_iterator_iter_code(ctx, args): if len(args) == 1: return cont_obj(ctx, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_iterator_iter = do_magic_method(class_iterator, "__iter__", om_iterator_iter_code) @@ -5694,7 +5745,7 @@ def catch_IndexError(exn): return sem_getitem(next_ctx, obj, index) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_iterator_next = do_magic_method(class_iterator, "__next__", om_iterator_next_code) @@ -5708,7 +5759,7 @@ def om_str_new_code(ctx, args): value = args[1] return sem_str(ctx, value) else: - return sem_raise_with_message(ctx, class_TypeError, "str() takes 0 or 1 argument") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0}() takes 0 or 1 argument", ["str"])) om_str_new = do_static_magic_method(class_str, "__new__", om_str_new_code) @@ -5779,7 +5830,7 @@ def om_str_repr_code(ctx, args): return ctx.cont(ctx.rte, om_str(formatted_str)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_str_repr = do_magic_method(class_str, "__repr__", om_str_repr_code) @@ -5798,7 +5849,7 @@ def om_str_add_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_str_add = do_magic_method(class_str, "__add__", om_str_add_code) @@ -5811,19 +5862,19 @@ def om_str_mul_code(ctx, args): def do_mul(rte, res): if res is absent: - return sem_raise_with_message(ctx, class_TypeError, "can't multiply sequence by non-int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("can't multiply sequence by non-int")) else: times = OM_get_boxed_value(res) num_times = int_to_num(times, True) if num_times is False: # NOTE: This is not strictly Python, but we cannot handle too big multpilciations for now - return sem_raise_with_message(ctx, class_OverflowError, "int too large to multiply sequence") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to multiply sequence")) else: return cont_str(ctx, string_mul(OM_get_boxed_value(self), num_times)) return sem_maybe_index(with_cont(ctx, do_mul), other) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_str_mul = do_magic_method(class_str, "__mul__", om_str_mul_code) om_str_rmul = do_magic_method(class_str, "__rmul__", om_str_mul_code) @@ -5866,7 +5917,7 @@ def get_char(rte, index): self_len = int_from_num(len(self_val)) if int_ge(index_val, self_len): - return sem_raise_with_message(ctx, class_IndexError, "string index out of range") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("string index out of range")) elif int_is_nonneg(index_val): return cont_str(ctx, self_val[int_to_num(index_val)]) else: @@ -5874,10 +5925,10 @@ def get_char(rte, index): if int_is_nonneg(reversed_index): return cont_str(ctx, self_val[int_to_num(reversed_index)]) else: - return sem_raise_with_message(ctx, class_IndexError, "string index out of range") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("string index out of range")) return sem_index(with_cont(ctx, get_char), item) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_str_getitem = do_magic_method(class_str, "__getitem__", om_str_getitem_code) @@ -5891,7 +5942,7 @@ def om_str_len_code(ctx, args): return cont_int(ctx, int_from_num(self_len)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_str_len = do_magic_method(class_str, "__len__", om_str_len_code) @@ -5907,7 +5958,7 @@ def om_str_str_code(ctx, args): new_str = om_str(OM_get_boxed_value(self)) ctx.cont(ctx.rte, new_str) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_str_str = do_magic_method(class_str, "__str__", om_str_str_code) @@ -5923,7 +5974,7 @@ def get_words(rte, words): for word in words: if not om_isinstance(word, class_str): - return sem_raise_with_message(with_rte(ctx, rte), class_TypeError, "sequence item " + str(i) + ": expected str instance") + return sem_raise_with_tformat(with_rte(ctx, rte), class_TypeError, tformat('sequence item {0}: expected str instance', [str(i)])) else: raw_strings[i] = OM_get_boxed_value(word) i += 1 @@ -5932,7 +5983,7 @@ def get_words(rte, words): return cont_str(with_rte(ctx, rte), res) return om_unpack_iterable(with_cont(ctx, get_words), it) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_str_join = do_magic_method(class_str, "join", om_str_join_code) @@ -5945,15 +5996,15 @@ def om_str_replace_code(ctx, args): replacement = args[2] if not om_isinstance(pattern, class_str): - return sem_raise_with_message(ctx, class_TypeError, "replace() argument 1 must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0}() argument {1} must be {2}", ["replace", "1", "str"])) elif not om_isinstance(replacement, class_str): - return sem_raise_with_message(ctx, class_TypeError, "replace() argument 2 must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0}() argument {1} must be {2}", ["replace", "2", "str"])) else: return cont_str(ctx, string_replace(OM_get_boxed_value(self), OM_get_boxed_value(pattern), OM_get_boxed_value(replacement))) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(len(args) - 1)])) om_str_replace = do_magic_method(class_str, "replace", om_str_replace_code) @@ -5966,7 +6017,7 @@ def op_code(ctx, args): if args_len == 1: return cont_kind(ctx, primitive(OM_get_boxed_value(args[0]))) else: - return sem_raise_with_message(ctx, class_TypeError, "expected no argument, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected no argument, got {0}', [str(len(args) - 1)])) return do_magic_method(class_str, method_name, op_code) @@ -6051,7 +6102,7 @@ def unicode_is_(string): def str_method_cont_maybe_bool(ctx, val): if val is None: - return sem_raise_with_message(ctx, class_NotImplementedError, "only extended ascii characters are supported for now") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("only extended ascii characters are supported for now")) else: return cont_bool(ctx, val) @@ -6085,7 +6136,7 @@ def do_split(rte, splits): sep_val = OM_get_boxed_value(sep) if len(sep_val) == 0: - return sem_raise_with_message(ctx, class_ValueError, "empty separator") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("empty separator")) else: res = primitive(OM_get_boxed_value(self), sep_val, max_split_num) return cont_list_of_str(ctx, res, len(res)) @@ -6093,11 +6144,11 @@ def do_split(rte, splits): res = whitespace_primitive(OM_get_boxed_value(self), max_split_num) return cont_list_of_str(ctx, res, len(res)) else: - return sem_raise_with_message(ctx, class_TypeError, "separator must be str or None") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("separator must be str or None")) return sem_index(with_cont(ctx, do_split), args[2]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected at most 3 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected at most 3 arguments, got {0}', [str(len(args) - 1)])) return do_magic_method_with_aligned_kwargs(class_str, method_name, code, 0, ["sep", "maxsplit"], [om_None, om_int_from_num(-1)]) @@ -6131,7 +6182,7 @@ def cont(rte, res): # cPython does not do that conversion and enforces a, int, but we might as well implement it return sem_bool(with_cont(ctx, cont), keepends) else: - return sem_raise_with_message(ctx, class_TypeError, "expected at most 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0} expected at most 1 argument, got {1}', ["splitlines", str(len(args) - 1)])) om_str_splitlines = do_magic_method_with_aligned_kwargs(class_str, "splitlines", om_splitlines_code, 0, @@ -6150,9 +6201,9 @@ def om_str_contains_code(ctx, args): self_len = len(self_val) return cont_bool(ctx, string_index_of(self_val, other_val, 0, self_len) != -1) else: - return sem_raise_with_message(ctx, class_TypeError, "'in ' requires string as left operand") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'in ' requires string as left operand")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_str_contains = do_magic_method(class_str, "__contains__", om_str_contains_code) @@ -6197,7 +6248,7 @@ def get_stop(rte, stop_index): else: return sem_index(with_cont(ctx, get_start), start) else: - return sem_raise_with_message(ctx, class_TypeError, "expected between 1 and 3 arguments arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected between 1 and 3 arguments arguments, got {0}', [str(len(args) - 1)])) return do_magic_method_with_defaults(class_str, method_name, code, 1, [om_None, om_None]) @@ -6211,7 +6262,7 @@ def om_str_do_find(ctx, indices, string, om_substring): int_to_num(indices[1])) return cont_int_from_num(ctx, index) else: - return sem_raise_with_message(ctx, class_TypeError, "must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("must be str")) def om_str_do_rfind(ctx, indices, string, om_substring): @@ -6222,7 +6273,7 @@ def om_str_do_rfind(ctx, indices, string, om_substring): int_to_num(indices[1])) return cont_int_from_num(ctx, index) else: - return sem_raise_with_message(ctx, class_TypeError, "must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("must be str")) def om_str_find_do_on_fail(ctx): @@ -6250,7 +6301,7 @@ def om_str_do_startswith(ctx, indices, string, om_substring): return cont_obj(ctx, om_False) else: - return sem_raise_with_message(ctx, class_TypeError, "startswith first arg must be str or a tuple of str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} first arg must be str or a tuple of str", ["startswith"])) def om_str_do_endswith(ctx, indices, string, om_substring): @@ -6270,7 +6321,7 @@ def om_str_do_endswith(ctx, indices, string, om_substring): return cont_obj(ctx, om_False) else: - return sem_raise_with_message(ctx, class_TypeError, "endswith first arg must be str or a tuple of str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} first arg must be str or a tuple of str", ["endswith"])) def om_str_startswith_do_on_fail(ctx): @@ -6290,13 +6341,13 @@ def om_str_do_index(ctx, indices, string, om_substring): if index >= 0: return cont_int_from_num(ctx, index) else: - return sem_raise_with_message(ctx, class_ValueError, "substring not found") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("substring not found")) else: - return sem_raise_with_message(ctx, class_TypeError, "must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("must be str")) def om_str_index_do_on_fail(ctx): - return sem_raise_with_message(ctx, class_ValueError, "substring not found") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("substring not found")) def om_str_do_rindex(ctx, indices, string, om_substring): @@ -6310,7 +6361,7 @@ def om_str_do_rindex(ctx, indices, string, om_substring): else: return om_str_index_do_on_fail(ctx) else: - return sem_raise_with_message(ctx, class_TypeError, "must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("must be str")) om_str_index = gen_str_find("index", om_str_do_index, om_str_index_do_on_fail) @@ -6325,7 +6376,7 @@ def om_str_do_count(ctx, indices, string, om_substring): int_to_num(indices[1])) return cont_int_from_num(ctx, count) else: - return sem_raise_with_message(ctx, class_TypeError, "must be str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("must be str")) def om_str_count_do_on_fail(ctx): @@ -6345,7 +6396,7 @@ def code(ctx, args): elif om_isinstance(chars, class_str): return cont_str(ctx, chars_primitive(OM_get_boxed_value(self), OM_get_boxed_value(chars))) else: - return sem_raise_with_message(ctx, class_TypeError, "strip arg must be None or str") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("strip arg must be None or str")) return do_magic_method_with_defaults(class_str, "method_name", code, 0, [om_None]) @@ -6358,7 +6409,7 @@ def code(ctx, args): # class_dict methods def om_dict_new(ctx, args): - return sem_raise_with_message(ctx, class_NotImplementedError, "dict type not implemented") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("dict type not implemented")) def om_dict_getitem_code(ctx, args): @@ -6373,14 +6424,14 @@ def om_dict_getitem_code(ctx, args): key_val = OM_get_boxed_value(key) val = dict_get(OM_get_boxed_value(self), key_val, None) if val is None: - return sem_raise_with_message(ctx, class_KeyError, "'" + key_val + "'") + return sem_raise_with_tformat(ctx, class_KeyError, tformat('{0}', [key_val])) else: return cont_obj(ctx, val) else: - return sem_raise_with_message(ctx, class_NotImplementedError, "dict type not implemented") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("dict type not implemented")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_dict_getitem = do_magic_method(class_dict, "__getitem__", om_dict_getitem_code) @@ -6399,10 +6450,10 @@ def om_dict_get_code(ctx, args): val = dict_get(OM_get_boxed_value(self), key_val, default_) return cont_obj(ctx, val) else: - return sem_raise_with_message(ctx, class_NotImplementedError, "dict type not implemented") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("dict type not implemented")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 or 3 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected 2 or 3 arguments, got {0}', [str(args_len - 1)])) om_dict_get = do_magic_method(class_dict, "__getitem__", om_dict_get_code) @@ -6428,9 +6479,9 @@ def om_module_getattribute_code(ctx, args): else: return ctx.cont(ctx.rte, result) else: - return sem_raise_with_message(ctx, class_TypeError, "attribute name must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_module_getattribute = do_magic_method(class_module, "__getattribute__", om_module_getattribute_code) @@ -6451,9 +6502,9 @@ def om_module_setattr_code(ctx, args): dict_set(module_env, attr, value) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "attribute name must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(len(args) - 1)])) om_module_setattr = do_magic_method(class_module, "__setattr__", om_module_setattr_code) @@ -6597,11 +6648,11 @@ def om_method_new_code(ctx, args): fn_call = getattribute_from_obj_mro(fn, "__call__") if fn_call is absent: - return sem_raise_with_message(ctx, class_TypeError, "first argument must be callable") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("first argument must be callable")) else: return cont_method(ctx, fn, instance) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(args_len - 1)])) om_method_new = do_static_magic_method(class_method, "__new__", om_method_new_code) @@ -6642,7 +6693,7 @@ def get_self_repr(_, self_repr): return sem_repr(with_cont(ctx, get_self_repr), self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected one argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected one argument, got {0}', [str(args_len - 1)])) om_method_repr = do_magic_method(class_method, "__repr__", om_method_repr_code) @@ -6812,7 +6863,7 @@ def int_from_str(s, base): def om_int_str_conversion(ctx, obj, radix): if not om_isinstance(obj, class_str): - return sem_raise_with_message(ctx, class_TypeError, "int() can't convert non-string with explicit base") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("int() can't convert non-string with explicit base")) def check_range(rte, index): str_value = OM_get_boxed_value(obj) @@ -6821,8 +6872,9 @@ def check_range(rte, index): res = int_from_str(str_value, base) if res is False: - return sem_raise_with_message(ctx, class_ValueError, "invalid literal for int() with base " + str( - base) + ": '" + str_value + "'") + str_repr = om_format_str_repr(obj) + return sem_raise_with_tformat(ctx, class_ValueError, + tformat("invalid literal for int() with base {0}: {1}", [str(base), str_repr])) else: return ctx.cont(rte, om_int(res)) return sem_index(with_cont(ctx, check_range), radix) @@ -6842,10 +6894,7 @@ def check_result(rte, res): if om_isinstance(obj, class_str): return om_int_str_conversion(ctx, obj, om_int(int_from_num(10))) else: - return sem_raise_with_message( - Context(rte, ctx.cont, ctx.ast), - class_TypeError, - "int() argument must be a string, a bytes-like object or a number") + return sem_raise_with_tformat(Context(rte, ctx.cont, ctx.ast), class_TypeError, tformat('int() argument must be a string, a bytes-like object or a number')) else: return ctx.cont(ctx.rte, om_int_subtype(cls, OM_get_boxed_value(res))) return sem_maybe_int(with_cont(ctx, check_result), obj) @@ -6859,13 +6908,13 @@ def check_radix_range(rte, res): if int_is_zero(res_value) or int_ge(res_value, int_from_num(2)) and int_le(res_value, int_from_num(36)): return om_int_str_conversion(ctx, obj, res) else: - return sem_raise_with_message(ctx, class_ValueError, "int() base must be >= 2 and <= 36, or 0") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("int() base must be >= 2 and <= 36, or 0")) return sem_index(with_cont(ctx, check_radix_range), radix) else: - return sem_raise_with_message(ctx, class_TypeError, "int() can't convert non-string with explicit base") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("int() can't convert non-string with explicit base")) else: - return sem_raise_with_message(ctx, class_TypeError, "int() takes at most 2 argument, got " + str(args_len)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes at most {1} arguments, got {2}', ["int", "2", str(args_len - 1)])) om_int_new = do_static_magic_method(class_int, "__new__", om_int_new_code) @@ -6876,7 +6925,7 @@ def om_int_int_code(ctx, args): self = args[0] return ctx.cont(ctx.rte, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_int_int = do_magic_method(class_int, "__int__", om_int_int_code) @@ -6887,7 +6936,7 @@ def om_int_index_code(ctx, args): self = args[0] return ctx.cont(ctx.rte, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_int_index = do_magic_method(class_int, "__index__", om_int_index_code) @@ -6899,7 +6948,7 @@ def om_int_float_code(ctx, args): float_val = int_to_num(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_float(float_val)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_int_float = do_magic_method(class_int, "__float__", om_int_float_code) @@ -6907,7 +6956,7 @@ def om_int_bool_code(ctx, args): if debug: print('int.__bool__') args_len = len(args) if args_len != 1: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) self = args[0] val_value = OM_get_boxed_value(self) @@ -6919,7 +6968,7 @@ def om_int_abs_code(ctx, args): result = int_abs(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_int(result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_int_abs = do_magic_method(class_int, "__abs__", om_int_abs_code) om_int_bool = do_magic_method(class_int, "__bool__", om_int_bool_code) @@ -6955,7 +7004,7 @@ def om_int_mod_code(ctx, args): # Early break for ZeroDivisionError val2_value = OM_get_boxed_value(val2) if int_is_zero(val2_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("modulo by zero")) else: val1_value = OM_get_boxed_value(val1) result = int_mod_floor(val1_value, val2_value) @@ -6976,7 +7025,7 @@ def om_int_rmod_code(ctx, args): # Early break for ZeroDivisionError val1_value = OM_get_boxed_value(val1) if int_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("modulo by zero")) else: val2_value = OM_get_boxed_value(val2) result = int_mod_floor(val2_value, val1_value) @@ -7000,7 +7049,7 @@ def om_int_floordiv_code(ctx, args): # Early break for ZeroDivisionError val2_value = OM_get_boxed_value(val2) if int_is_zero(val2_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "division by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("division by zero")) else: val1_value = OM_get_boxed_value(val1) result = int_div_floor(val1_value, val2_value) @@ -7022,7 +7071,7 @@ def om_int_rfloordiv_code(ctx, args): # Early break for ZeroDivisionError val1_value = OM_get_boxed_value(val1) if int_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "division by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("division by zero")) else: val2_value = OM_get_boxed_value(val2) result = int_div_floor(val2_value, val1_value) @@ -7043,7 +7092,7 @@ def om_int_truediv_code(ctx, args): # Early break for ZeroDivisionError val2_value = OM_get_boxed_value(val2) if int_is_zero(val2_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "division by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("division by zero")) else: val1_value = OM_get_boxed_value(val1) result = float_div(int_to_num(val1_value), int_to_num(val2_value)) @@ -7065,7 +7114,7 @@ def om_int_rtruediv_code(ctx, args): # Early break for ZeroDivisionError val1_value = OM_get_boxed_value(val1) if int_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "division by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("division by zero")) else: val2_value = OM_get_boxed_value(val2) result = float_div(int_to_num(val2_value), int_to_num(val1_value)) @@ -7181,8 +7230,7 @@ def float_str_conversion(s): return float_from_string(s) def raise_could_not_convert_str_to_float(ctx, s): - return sem_raise_with_message(ctx, class_ValueError, - "could not convert string to float: " + om_format_str_repr(s, ctx.rte)) + return sem_raise_with_tformat(ctx, class_ValueError, tformat('could not convert string to float: {0}', [om_format_str_repr(s, ctx.rte)])) def om_float_str_conversion(ctx, obj): @@ -7194,7 +7242,7 @@ def om_float_str_conversion(ctx, obj): else: return cont_float(ctx, res) else: - return sem_raise_with_message(ctx, class_TypeError, "float() argument must be a string or a number") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("float() argument must be a string or a number")) def om_float_new_code(ctx, args): args_len = len(args) @@ -7213,7 +7261,7 @@ def check_result(rte, res): return ctx.cont(ctx.rte, om_float_subtype(cls, OM_get_boxed_value(res))) return sem_maybe_float(with_cont(ctx, check_result), obj) else: - return sem_raise_with_message(ctx, class_TypeError, "int() takes at most 1 argument, got " + str(args_len)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes at most {1} argument, got {2}', ["float", "1", str(args_len - 1)])) om_float_new = do_static_magic_method(class_float, "__new__", om_float_new_code) @@ -7221,7 +7269,7 @@ def om_float_bool_code(ctx, args): if debug: print('int.__bool__') args_len = len(args) if args_len != 1: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) self = args[0] val_value = OM_get_boxed_value(self) return cont_bool(ctx, not float_is_zero(val_value)) @@ -7249,7 +7297,7 @@ def om_float_float_code(ctx, args): self = args[0] return ctx.cont(ctx.rte, self) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_float_float = do_magic_method(class_float, "__float__", om_float_float_code) @@ -7275,7 +7323,7 @@ def dunder_Float_BinOp(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value) or float_is_nan(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) else: res = prim(val1_value, val2_float_value) return cont_box(ctx, res) @@ -7308,7 +7356,7 @@ def dunder_Float_rBinOp(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value) or float_is_nan(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) res = prim(val2_float_value, val1_value) return cont_box(ctx, res) @@ -7334,7 +7382,7 @@ def dunder_Float_DivideOp(ctx, args): val2_value = OM_get_boxed_value(val2) if float_is_zero(val2_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float division or modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float division or modulo by zero")) result = prim(val1_value, val2_value) return ctx.cont(ctx.rte, om_float(result)) @@ -7343,10 +7391,10 @@ def dunder_Float_DivideOp(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value, True) if val2_float_value is False: - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) if float_is_zero(val2_float_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float division or modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float division or modulo by zero")) res = prim(val1_value, val2_float_value) return cont_box(ctx, res) @@ -7371,7 +7419,7 @@ def dunder_Float_rDivideOp(ctx, args): val2_value = OM_get_boxed_value(val2) if float_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float division or modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float division or modulo by zero")) result = prim(val1_value, val2_value) return ctx.cont(ctx.rte, om_float(result)) @@ -7380,10 +7428,10 @@ def dunder_Float_rDivideOp(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value, True) if val2_float_value is False: - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) if float_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float division or modulo by zero") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float division or modulo by zero")) res = prim(val2_float_value, val1_value) return cont_box(ctx, res) @@ -7497,7 +7545,7 @@ def om_float_mod_code(ctx, args): val2_value = OM_get_boxed_value(val2) if float_is_zero(val2_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float modulo") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float modulo")) elif float_is_infinite(val2_value) and float_is_finite(val1_value): if float_is_neg(val1_value): # Return inf @@ -7512,9 +7560,9 @@ def om_float_mod_code(ctx, args): val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) elif float_is_zero(val2_float_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float modulo") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float modulo")) elif float_is_infinite(val2_float_value) and float_is_finite(val1_value): if float_is_neg(val1_value): # Return inf @@ -7526,7 +7574,7 @@ def om_float_mod_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_float_mod = do_magic_method(class_float, '__mod__', om_float_mod_code) @@ -7543,7 +7591,7 @@ def om_float_rmod_code(ctx, args): val2_value = OM_get_boxed_value(val2) if float_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float modulo") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float modulo")) elif float_is_infinite(val1_value) and float_is_finite(val2_value): if float_is_neg(val2_value): # Return inf @@ -7558,9 +7606,9 @@ def om_float_rmod_code(ctx, args): val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) elif float_is_zero(val1_value): - return sem_raise_with_message(ctx, class_ZeroDivisionError, "float modulo") + return sem_raise_with_tformat(ctx, class_ZeroDivisionError, tformat("float modulo")) elif float_is_infinite(val1_value) and float_is_finite(val2_float_value): if float_is_neg(val2_float_value): # Return inf @@ -7572,7 +7620,7 @@ def om_float_rmod_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_float_rmod = do_magic_method(class_float, '__rmod__', om_float_rmod_code) @@ -7600,15 +7648,15 @@ def om_float_pow_code(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) else: return cont_float(ctx, float_pow(val1_value, val2_float_value)) else: return cont_obj(ctx, om_NotImplemented) elif args_len == 3: - return sem_raise_with_message(ctx, class_TypeError, "pow() 3rd argument not allowed unless all arguments are integers") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("pow() 3rd argument not allowed unless all arguments are integers")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_float_pow = do_magic_method(class_float, "__pow__", om_float_pow_code) @@ -7637,7 +7685,7 @@ def om_float_rpow_code(ctx, args): val2_value = OM_get_boxed_value(val2) val2_float_value = int_to_num(val2_value) if float_is_infinite(val2_float_value): - return sem_raise_with_message(ctx, class_OverflowError, "int too large to convert to float") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("int too large to convert to float")) elif float_is_infinite(val1_value) and float_eq(val2_float_value, float_from_num(1.0)): # Special case in Python where 1.0 ** inf returns 1.0 return cont_float(ctx, val2_float_value) @@ -7646,9 +7694,9 @@ def om_float_rpow_code(ctx, args): else: return cont_obj(ctx, om_NotImplemented) elif args_len == 3: - return sem_raise_with_message(ctx, class_TypeError, "pow() 3rd argument not allowed unless all arguments are integers") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("pow() 3rd argument not allowed unless all arguments are integers")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(args_len - 1)])) om_float_rpow = do_magic_method(class_float, "__rpow__", om_float_rpow_code) @@ -7724,7 +7772,7 @@ def apply_round(rte, n): res = int_to_num(int_round(int_norm_integral_part, n_value, False)) if float_is_infinite(res): - return sem_raise_with_message(ctx, class_OverflowError, "rounded value too large to represent") + return sem_raise_with_tformat(ctx, class_OverflowError, tformat("rounded value too large to represent")) else: return cont_float(ctx, float_mul(sign, res)) else: @@ -7746,7 +7794,7 @@ def apply_round(rte, n): return sem_index(with_cont(ctx, apply_round), ndigits) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 1 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["1", str(len(args) - 1)])) om_float_round = do_magic_method(class_float, "__round__", om_float_round_code) @@ -7756,7 +7804,7 @@ def om_float_abs_code(ctx, args): result = float_abs(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_float(result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_float_abs = do_magic_method(class_float, "__abs__", om_float_abs_code) @@ -8007,7 +8055,7 @@ def om_float_repr_code(ctx, args): result = om_format_float_repr(self, ctx.rte) return ctx.cont(ctx.rte, om_str(result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_float_repr = do_magic_method(class_float, "__repr__", om_float_repr_code) @@ -8017,7 +8065,7 @@ def om_float_neg_code(ctx, args): result = float_neg(OM_get_boxed_value(self)) return ctx.cont(ctx.rte, om_boxval(class_float, result)) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_float_neg = do_magic_method(class_float, "__neg__", om_float_neg_code) @@ -8025,7 +8073,7 @@ def om_float_pos_code(ctx, args): if len(args) == 1: return ctx.cont(ctx.rte, args[0]) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got "+ str(len(args) - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(len(args) - 1)])) om_float_pos = do_magic_method(class_float, "__pos__", om_float_pos_code) @@ -8104,11 +8152,10 @@ def conv_code(rte, cont): result = "-" + prefix + int_to_string(int_neg(obj_value), radix) return unwind_return(rte, om_str(result)) else: - obj_cls_name = OM_get(obj_cls, '__name__') - obj_cls_name_value = OM_get_boxed_value(obj_cls_name) - msg = "'"+obj_cls_name_value+"' object cannot be interpreted as an integer" - ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_TypeError, msg) + cls_name = OM_get_class_name(obj_cls) + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), + class_TypeError, + tformat("'{0}' object cannot be interpreted as an integer", [cls_name])) return conv_code @@ -8125,10 +8172,10 @@ def om_chr_code(rte, cont): return unwind_return(rte, om_str(chr(obj_int_val))) else: ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_ValueError, "chr() arg not in range(0x110000)") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("chr() arg not in range(0x110000)")) else: ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_TypeError, "an integer is required") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("an integer is required")) def om_ord_code(rte, cont): obj = rte_lookup_locals(rte, "obj") @@ -8140,10 +8187,10 @@ def om_ord_code(rte, cont): return unwind_return(rte, om_int(obj_value_int)) else: ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_ValueError, "ord() expected a character, but string of length " + str(obj_value_len) + " found") + return sem_raise_with_tformat(ctx, class_ValueError, tformat('ord() expected a character, but string of length {0} found', [str(obj_value_len)])) else: ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_TypeError, "ord() expected string of length 1") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("ord() expected string of length 1")) def om_print_code(rte, _): args = rte_lookup_locals(rte, 'args') @@ -8248,14 +8295,16 @@ def om_open_code(rte, _): mode_value = OM_get_boxed_value(mode) if mode_value != 'r' and mode_value != 'w': - return sem_raise_with_message(next_ctx, class_ValueError, "invalid mode: '" + mode_value + "'") + return sem_raise_with_tformat(next_ctx, + class_ValueError, + tformat("invalid mode: '{0}'", [mode_value])) else: - return sem_raise_with_message(next_ctx, class_TypeError, "open() argument 'mode' must be str") + return sem_raise_with_tformat(next_ctx, class_TypeError, tformat("{0} argument '{1}' must be {2}", ["open()", "mode", "str"])) if om_isinstance(file, class_str): file_value = OM_get_boxed_value(file) else: - return sem_raise_with_message(next_ctx, class_TypeError, "open() argument 'file' must be str") + return sem_raise_with_tformat(next_ctx, class_TypeError, tformat("{0} argument '{1}' must be {2}", ["open()", "file", "str"])) if mode_value == "r" and runtime_file_exists(rte, file_value): return unwind_return(rte, om_TextIOWrapper(class_TextIOWrapper, file_value, mode_value, 0, True)) @@ -8263,8 +8312,8 @@ def om_open_code(rte, _): runtime_write_file(rte, file_value, "") return unwind_return(rte, om_TextIOWrapper(class_TextIOWrapper, file_value, mode_value, 0, True)) else: - return sem_raise_with_message(next_ctx, class_FileNotFoundError, - "No such file: '" + file_value + "'") + return sem_raise_with_tformat(next_ctx, class_FileNotFoundError, + tformat("No such file: {0}", [om_format_str_repr(file)])) def om_abs_code(rte, _): next_ctx = make_out_of_ast_context(rte, unwind_return) @@ -8273,15 +8322,14 @@ def om_abs_code(rte, _): return sem_abs(next_ctx, obj) def do_min_max(name, sem_Comp): - expected_argument_error_msg = name + " expected 1 argument, got 0" - empty_sequence_error_msg = name + "() arg is an empty sequence" - def code(rte, cont): args = rte_lookup_locals(rte, 'args') args_elements = OM_get_tuple_seq(args) args_len = len(args_elements) if args_len == 0: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, expected_argument_error_msg) + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), + class_TypeError, + tformat("{0} expected 1 argument, got 0", [name])) elif args_len == 1: iterable = args_elements[0] else: @@ -8290,7 +8338,9 @@ def code(rte, cont): def loop_iterator(loop_iterator_rte, iterator): def get_first(get_first_rte, first_element): if first_element is for_loop_end_marker: - return sem_raise_with_message(make_out_of_ast_context(get_first_rte, cont), class_ValueError, empty_sequence_error_msg) + return sem_raise_with_tformat(make_out_of_ast_context(get_first_rte, cont), + class_ValueError, + tformat("{0}() arg is an empty sequence", [name])) candidate_ref = [first_element] def get_next(get_next_rte, next_element): if next_element is for_loop_end_marker: @@ -8340,11 +8390,9 @@ def om_isinstance_code(rte, cont): if om_isinstance(classinfo, class_type): return cont_bool(next_ctx, om_isinstance(obj, classinfo)) elif om_isinstance(classinfo, class_tuple): - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_NotImplementedError, - "isinstance() tuple classinfo is not supported yet") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_NotImplementedError, tformat('isinstance() tuple classinfo is not supported yet')) else: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, - "isinstance() arg 2 must be a type or tuple of types") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('isinstance() arg 2 must be a type or tuple of types')) # Built-in Modules @@ -8354,7 +8402,7 @@ def float_code(rte, cont): def apply_float_fn(float_rte, float_val): if float_val is absent: - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_TypeError, "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_TypeError, tformat('must be real number')) else: res = float_fn(OM_get_boxed_value(float_val)) return unwind_return(float_rte, om_float(res)) @@ -8369,16 +8417,14 @@ def float_code(rte, cont): def apply_float_fn(float_rte, float_val): if float_val is absent: - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_TypeError, "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_TypeError, tformat('must be real number')) else: res = float_fn(OM_get_boxed_value(float_val)) if float_is_infinite(res): - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_ValueError, - "cannot convert float infinity to integer") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_ValueError, tformat('cannot convert float infinity to integer')) elif float_is_nan(res): - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_ValueError, - "cannot convert float NaN to integer") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_ValueError, tformat('cannot convert float NaN to integer')) else: int_res = int_from_num(float_to_num(res)) return unwind_return(float_rte, om_int(int_res)) @@ -8393,7 +8439,7 @@ def float_code(rte, cont): def apply_float_fn(float_rte, float_val): if float_val is absent: - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_TypeError, "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_TypeError, tformat('must be real number')) else: float_unboxed_val = OM_get_boxed_value(float_val) @@ -8403,7 +8449,7 @@ def apply_float_fn(float_rte, float_val): res = float_fn(OM_get_boxed_value(float_val)) return unwind_return(float_rte, om_float(res)) else: - return sem_raise_with_message(make_out_of_ast_context(float_rte, cont), class_ValueError, "math domain error") + return sem_raise_with_tformat(make_out_of_ast_context(float_rte, cont), class_ValueError, tformat('math domain error')) return sem_maybe_float(make_out_of_ast_context(rte, apply_float_fn), val) @@ -8436,13 +8482,11 @@ def math_pow_code(rte, cont): def check_obj1(obj1_rte, obj1_res): if obj1_res is absent: - return sem_raise_with_message(make_out_of_ast_context(obj1_rte, cont), class_TypeError, - "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(obj1_rte, cont), class_TypeError, tformat('must be real number')) else: def check_obj2(obj2_rte, obj2_res): if obj2_res is absent: - return sem_raise_with_message(make_out_of_ast_context(obj2_rte, cont), class_ValueError, - "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(obj2_rte, cont), class_ValueError, tformat('must be real number')) else: float_res1 = OM_get_boxed_value(obj1_res) float_res2 = OM_get_boxed_value(obj2_res) @@ -8450,11 +8494,9 @@ def check_obj2(obj2_rte, obj2_res): res = float_pow(float_res1, float_res2) if float_is_infinite(res): - return sem_raise_with_message(make_out_of_ast_context(obj2_rte, cont), class_OverflowError, - "math range error") + return sem_raise_with_tformat(make_out_of_ast_context(obj2_rte, cont), class_OverflowError, tformat('math range error')) elif float_is_nan(res): - return sem_raise_with_message(make_out_of_ast_context(obj2_rte, cont), class_ValueError, - "math domain error") + return sem_raise_with_tformat(make_out_of_ast_context(obj2_rte, cont), class_ValueError, tformat('math domain error')) else: return unwind_return(obj2_rte, om_float(res)) @@ -8490,13 +8532,11 @@ def math_atan2_code(rte, cont): def check_obj1(obj1_rte, obj1_res): if obj1_res is absent: - return sem_raise_with_message(make_out_of_ast_context(obj1_rte, cont), class_TypeError, - "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(obj1_rte, cont), class_TypeError, tformat('must be real number')) else: def check_obj2(obj2_rte, obj2_res): if obj2_res is absent: - return sem_raise_with_message(make_out_of_ast_context(obj2_rte, cont), class_ValueError, - "must be real number") + return sem_raise_with_tformat(make_out_of_ast_context(obj2_rte, cont), class_ValueError, tformat('must be real number')) else: float_res1 = OM_get_boxed_value(obj1_res) float_res2 = OM_get_boxed_value(obj2_res) @@ -8573,7 +8613,9 @@ def get_arg2_float(arg2_rte, arg2_float): val2 = float_to_num(OM_get_boxed_value(arg2_float)) if not float_is_finite(val1) or not float_is_finite(val2): - return sem_raise_with_message(make_out_of_ast_context(arg2_rte, cont), class_ValueError, name + "() arguments must be finite numbers") + return sem_raise_with_tformat(make_out_of_ast_context(arg2_rte, cont), + class_ValueError, + tformat("{0}() arguments must be finite numbers", [name])) else: fn(rte, val1, val2) return unwind_return(rte, om_None) @@ -8601,9 +8643,7 @@ def get_width_float(width_rte, width_float): width_val = float_to_num(OM_get_boxed_value(width_float)) if not float_is_finite(width_val): - return sem_raise_with_message(make_out_of_ast_context(width_rte, cont), - class_ValueError, - "clear() width argument must be a finite number") + return sem_raise_with_tformat(make_out_of_ast_context(width_rte, cont), class_ValueError, tformat('{0}() width argument must be a finite number', ["clear"])) elif height is absent: drawing_cs(width_rte, width_val) return unwind_return(width_rte, om_None) @@ -8613,9 +8653,7 @@ def get_height_float(height_rte, height_float): height_val = float_to_num(OM_get_boxed_value(height_float)) if not float_is_finite(height_val): - return sem_raise_with_message(make_out_of_ast_context(height_rte, cont), - class_ValueError, - "clear() height argument must be a finite number") + return sem_raise_with_tformat(make_out_of_ast_context(height_rte, cont), class_ValueError, tformat('{0}() height argument must be a finite number', ["clear"])) elif scale is absent: drawing_cs(height_rte, width_val, height_val) @@ -8626,9 +8664,7 @@ def get_scale_float(scale_rte, scale_float): scale_val = float_to_num(OM_get_boxed_value(scale_float)) if not float_is_finite(scale_val): - return sem_raise_with_message(make_out_of_ast_context(scale_rte, cont), - class_ValueError, - "clear() scale argument must be a finite number") + return sem_raise_with_tformat(make_out_of_ast_context(scale_rte, cont), class_ValueError, tformat('{0}() scale argument must be a finite number', ["clear"])) else: drawing_cs(scale_rte, width_val, height_val, scale_val) return unwind_return(scale_rte, om_None) @@ -8653,9 +8689,7 @@ def get_y_float(y_rte, y_float): y_val = float_to_num(OM_get_boxed_value(y_float)) if not float_is_finite(x_val) or not float_is_finite(y_val): - return sem_raise_with_message(make_out_of_ast_context(y_rte, cont), - class_ValueError, - "goto() arguments must be finite numbers") + return sem_raise_with_tformat(make_out_of_ast_context(y_rte, cont), class_ValueError, tformat('{0}() arguments must be finite numbers', ["goto"])) else: drawing_mv(y_rte, x_val, y_val) return unwind_return(rte, om_None) @@ -8675,9 +8709,9 @@ def get_angle_float(angle_rte, angle_float): fn(angle_rte, angle_val) return unwind_return(angle_rte, om_None) else: - return sem_raise_with_message(make_out_of_ast_context(angle_rte, cont), + return sem_raise_with_tformat(make_out_of_ast_context(angle_rte, cont), class_ValueError, - name + "() argument must be a finite number") + tformat("{0}() argument must be a finite number", [name])) return sem_float(make_out_of_ast_context(rte, get_angle_float), angle) return om_make_builtin_function_with_signature(name, code, make_posonly_only_signature((arg_name,))) @@ -8704,9 +8738,7 @@ def get_b_float(b_rte, b_float): drawing_setpc(rte, r_val, g_val, b_val) return unwind_return(rte, om_None) else: - return sem_raise_with_message(make_out_of_ast_context(b_rte, cont), - class_ValueError, - "pencolor() arguments must be between 0 and 1") + return sem_raise_with_tformat(make_out_of_ast_context(b_rte, cont), class_ValueError, tformat('{0}() arguments must be between 0 and 1', ["pencolor"])) return sem_float(make_out_of_ast_context(g_rte, get_b_float), b) return sem_float(make_out_of_ast_context(r_rte, get_g_float), g) @@ -8725,8 +8757,7 @@ def get_width_float(width_rte, width_float): drawing_setpw(width_rte, float_to_num(width_value)) return unwind_return(width_rte, om_None) else: - return sem_raise_with_message(make_out_of_ast_context(width_rte, cont), class_ValueError, - "pensize() argument must be a non-negative number") + return sem_raise_with_tformat(make_out_of_ast_context(width_rte, cont), class_ValueError, tformat('pensize() argument must be a non-negative number')) return sem_float(make_out_of_ast_context(rte, get_width_float), width) @@ -8743,8 +8774,7 @@ def get_scale_float(scale_rte, scale_float): drawing_setscale(scale_rte, float_to_num(scale_value)) return unwind_return(scale_rte, om_None) else: - return sem_raise_with_message(make_out_of_ast_context(scale_rte, cont), class_ValueError, - "scale() argument must be a finite number") + return sem_raise_with_tformat(make_out_of_ast_context(scale_rte, cont), class_ValueError, tformat('{0}() argument must be a finite number', ["scale"])) return sem_float(make_out_of_ast_context(rte, get_scale_float), scale) @@ -8822,20 +8852,17 @@ def return_none(_): if om_isinstance(secs, class_float): sleep_time = float_to_num(OM_get_boxed_value(secs)) if sleep_time < 0: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_ValueError, - "sleep length must be non-negative") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_ValueError, tformat('sleep length must be non-negative')) else: return stmt_end_with_sleep(sleep_ctx, sleep_time * 1000) else: def sleep_int_amount(int_rte, int_res): if int_res is absent: - return sem_raise_with_message(make_out_of_ast_context(int_rte, cont), class_TypeError, - "a number is required") + return sem_raise_with_tformat(make_out_of_ast_context(int_rte, cont), class_TypeError, tformat('a number is required')) else: sleep_time = int_to_num(OM_get_boxed_value(int_res)) if sleep_time < 0: - return sem_raise_with_message(make_out_of_ast_context(int_rte, cont), class_ValueError, - "sleep length must be non-negative") + return sem_raise_with_tformat(make_out_of_ast_context(int_rte, cont), class_ValueError, tformat('sleep length must be non-negative')) else: return stmt_end_with_sleep(sleep_ctx, sleep_time * 1000) return sem_maybe_index(make_out_of_ast_context(rte, sleep_int_amount), secs) @@ -8880,7 +8907,7 @@ def do_call(rte, nxt): def catch_StopIteration(exn): ctx = make_out_of_ast_context(rte, cont) if om_isinstance(exn, class_StopIteration): - return sem_raise_with_message(ctx, class_TypeError, "reduce() of empty sequence with no initial value") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("reduce() of empty sequence with no initial value")) else: return sem_raise_unsafe(ctx.rte, exn) @@ -8936,13 +8963,13 @@ def create_object(reader_rte, csvfile_transformation): # Check for dialect # TODO: we ignore dialect if not om_isinstance(dialect, class_str): - return sem_raise_with_message(make_out_of_ast_context(reader_rte, None), class_TypeError, "dialect must be a string") + return sem_raise_with_tformat(make_out_of_ast_context(reader_rte, None), class_TypeError, tformat('dialect must be a string')) else: dialect_value = OM_get_boxed_value(dialect) # check for delimiter if not om_isinstance(delimiter, class_str) or len(OM_get_boxed_value(delimiter)) != 1: - return sem_raise_with_message(make_out_of_ast_context(reader_rte, None), class_TypeError, "delimiter must be a 1-character string") + return sem_raise_with_tformat(make_out_of_ast_context(reader_rte, None), class_TypeError, tformat('delimiter must be a 1-character string')) else: delimiter_value = OM_get_boxed_value(delimiter) @@ -8956,11 +8983,11 @@ def after_doublequote(dq_rte, doublequote_as_bool): elif om_isinstance(escapechar, class_str) and len(OM_get_boxed_value(delimiter)) == 1: escapechar_value = OM_get_boxed_value(escapechar) else: - return sem_raise_with_message(make_out_of_ast_context(dq_rte, None), class_TypeError, "escapechar must be a string or None") + return sem_raise_with_tformat(make_out_of_ast_context(dq_rte, None), class_TypeError, tformat('escapechar must be a string or None')) # check for lineterminator if not om_isinstance(lineterminator, class_str): - return sem_raise_with_message(make_out_of_ast_context(dq_rte, None), class_TypeError, "lineterminator must be a string") + return sem_raise_with_tformat(make_out_of_ast_context(dq_rte, None), class_TypeError, tformat('lineterminator must be a string')) else: lineterminator_value = OM_get_boxed_value(lineterminator) @@ -8969,17 +8996,17 @@ def after_doublequote(dq_rte, doublequote_as_bool): if om_is(quotechar, om_None): quotechar_value = None elif not om_isinstance(quotechar, class_str) or len(OM_get_boxed_value(quotechar)) != 1: - return sem_raise_with_message(make_out_of_ast_context(dq_rte, None), class_TypeError, "quotechar must be a 1-character string") + return sem_raise_with_tformat(make_out_of_ast_context(dq_rte, None), class_TypeError, tformat('quotechar must be a 1-character string')) else: quotechar_value = OM_get_boxed_value(quotechar) # check for quoting if not om_has_type(quoting, class_int): - return sem_raise_with_message(make_out_of_ast_context(dq_rte, None), class_TypeError, "quoting must be an interger") + return sem_raise_with_tformat(make_out_of_ast_context(dq_rte, None), class_TypeError, tformat('quoting must be an interger')) else: quoting_value = OM_get_boxed_value(quoting) if quoting_value < csv_param_quote_minimal or quoting_value > csv_param_quote_none: - return sem_raise_with_message(make_out_of_ast_context(dq_rte, None), class_TypeError, "bad quoting value") + return sem_raise_with_tformat(make_out_of_ast_context(dq_rte, None), class_TypeError, tformat('bad quoting value')) def after_skipinitialspace(initialspace_rte, skipinitialspace_as_bool): # skipinitialspace truthiness is tested @@ -9007,17 +9034,17 @@ def after_strict(initialspace_rte, strict_as_bool): def check_csvfile_writable(ctx, csvfile): # NOTE: We do not check that the object is a writable file, we check that the object is writable (has callable write attribute) - no_write_method_msg = 'first argument must have a "write" method' + no_write_method_msg = tformat('first argument must have a "{0}" method', ["write"]) def return_write_method(rte, write_method): if om_iscallable(write_method): return cont_obj(ctx, write_method) else: - return sem_raise_with_message(ctx, class_TypeError, no_write_method_msg) + return sem_raise_with_tformat(ctx, class_TypeError, no_write_method_msg) def catch_AttributeError(exn): if om_isinstance(exn, class_AttributeError): - return sem_raise_with_message(ctx, class_TypeError, no_write_method_msg) + return sem_raise_with_tformat(ctx, class_TypeError, no_write_method_msg) else: return sem_raise_unsafe(ctx.rte, exn) @@ -9194,7 +9221,7 @@ def setScreenMode_code(rte, cont): return unwind_return(rte, om_None) else: ctx = make_out_of_ast_context(rte, cont) - return sem_raise_with_message(ctx, class_TypeError, "arguments width and height must be of type int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("arguments {0} and {1} must be of type int", ["width", "height"])) def getScreenWidth_code(rte, cont): result = drawing_getScreenWidth(rte) @@ -9217,29 +9244,29 @@ def setPixel_code(rte, cont): screen_height = drawing_getScreenHeight(rte) if xval < 0 or xval >= screen_width: - return sem_raise_with_message(ctx, class_IndexError, "x parameter of setPixel must be a non-negative integer less than " + str(screen_width)) + return sem_raise_with_tformat(ctx, class_IndexError, tformat('{0} parameter of setPixel must be a non-negative integer less than {1}', ["x", str(screen_width)])) if yval < 0 or yval >= screen_height: - return sem_raise_with_message(ctx, class_IndexError, "y parameter of setPixel must be a non-negative integer less than " + str(screen_height)) + return sem_raise_with_tformat(ctx, class_IndexError, tformat('{0} parameter of setPixel must be a non-negative integer less than {1}', ["y", str(screen_height)])) if om_isinstance(color, class_str): color_val = color_str_to_dict(OM_get_boxed_value(color)) if color_val is None: - return sem_raise_with_message(ctx, class_ValueError, "invalid HTML color str format") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("invalid HTML color {0} format", ["str"])) else: drawing_setPixel(rte, xval, yval, color_val) return unwind_return(rte, om_None) if om_isinstance(color, class_struct): color_val = color_struct_to_dict(color) if color_val is None: - return sem_raise_with_message(ctx, class_ValueError, "invalid HTML color struct format") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("invalid HTML color {0} format", ["struct"])) else: drawing_setPixel(rte, xval, yval, color_val) return unwind_return(rte, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "color must be of type str or struct") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("color must be of type str or struct")) else: - return sem_raise_with_message(ctx, class_TypeError, "arguments x and y must be of type int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("arguments {0} and {1} must be of type int", ["x", "y"])) def fillRectangle_code(rte, cont): @@ -9260,37 +9287,39 @@ def fillRectangle_code(rte, cont): screen_height = drawing_getScreenHeight(rte) if xval < 0: - return sem_raise_with_message(ctx, class_IndexError, "x parameter of fillRectangle must be a non-negative integer") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("{0} parameter of fillRectangle must be a non-negative integer", ["x"])) if yval < 0: - return sem_raise_with_message(ctx, class_IndexError, "y parameter of fillRectangle must be a non-negative integer") + return sem_raise_with_tformat(ctx, class_IndexError, tformat("{0} parameter of fillRectangle must be a non-negative integer", ["y"])) if width_val < 0 or xval + width_val > screen_width: - error_msg = "width parameter of fillRectangle must be a non-negative integer such that x + width <= " + str(screen_width) - return sem_raise_with_message(ctx, class_IndexError, error_msg) + error_msg = tformat("{0} parameter of {1} must be a non-negative integer such that {2} + {0} <= {3}", + [tformat("width"), "fillRectangle", "x", str(screen_width)]) + return sem_raise_with_tformat(ctx, class_IndexError, error_msg) if height_val < 0 or yval + height_val > screen_height: - error_msg = "height parameter of fillRectangle must be a non-negative integer such that y + height <= " + str(screen_height) - return sem_raise_with_message(ctx, class_IndexError, error_msg) + error_msg = tformat("{0} parameter of {1} must be a non-negative integer such that {2} + {0} <= {3}", + [tformat("height"), "fillRectangle", "y", str(screen_height)]) + return sem_raise_with_tformat(ctx, class_IndexError, error_msg) if om_isinstance(color, class_str): color_val = color_str_to_dict(OM_get_boxed_value(color)) if color_val is None: - return sem_raise_with_message(ctx, class_ValueError, "invalid HTML color str format") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("invalid HTML color {0} format", ["str"])) else: drawing_fillRectangle(rte, xval, yval, width_val, height_val, color_val) return unwind_return(rte, om_None) elif om_isinstance(color, class_struct): color_val = color_struct_to_dict(color) if color_val is None: - return sem_raise_with_message(ctx, class_ValueError, "invalid HTML color struct format") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("invalid HTML color {0} format", ["struct"])) else: drawing_fillRectangle(rte, xval, yval, width_val, height_val, color_val) return unwind_return(rte, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "color must be of type str or struct") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("color must be of type {0} or {1}", ["str", "struct"])) else: - return sem_raise_with_message(ctx, class_TypeError, "x, y, width and height must be of type int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("x, y, width and height must be of type int")) def exportScreen_code(rte, cont): @@ -9337,11 +9366,9 @@ def om_struct_new_code(ctx, args, kwargs): value = pair[1] if key == '_fields': - return sem_raise_with_message(ctx, class_ValueError, - "cannot set reserved attribute '_fields' of struct()") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("cannot set reserved attribute '{0}}' of {1}", ["_fields", "struct()"])) elif key == '__class__': - return sem_raise_with_message(ctx, class_ValueError, - "cannot set reserved attribute '__class__' of struct()") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("cannot set reserved attribute '{0}}' of {1}", ["__class__", "struct()"])) else: fields.append(om_str(key)) OM_set(struct_obj, key, value) @@ -9351,8 +9378,7 @@ def om_struct_new_code(ctx, args, kwargs): return cont_obj(ctx, struct_obj) else: - return sem_raise_with_message(ctx, class_TypeError, - "struct takes no positional argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('struct takes no positional argument, got {0}', [str(args_len - 1)])) om_struct_new = do_static_magic_method_with_kwargs(class_struct, "__new__", om_struct_new_code) @@ -9397,7 +9423,7 @@ def do_attr_repr(attr_rte, repr_): return cont(ctx.rte, []) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 0 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} argument, got {1}', ["0", str(args_len - 1)])) om_struct_repr = do_magic_method(class_struct, "__repr__", om_struct_repr_code) @@ -9423,13 +9449,13 @@ def om_struct_setattr_code(ctx, args): return cont_obj(ctx, om_None) - return sem_raise_with_message(ctx, class_AttributeError, - "struct() object has no attribute '" + name_value + "'") + return sem_raise_with_tformat(ctx, class_AttributeError, + tformat("'{0}' object has no attribute '{1}'", ["struct", name_value])) else: - return sem_raise_with_message(ctx, class_TypeError, "attribute must be string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("attribute name must be string")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(args_len - 1)])) om_struct_setattr = do_magic_method(class_struct, "__setattr__", om_struct_setattr_code) @@ -9446,19 +9472,18 @@ def readFile_code(rte, cont): filename = rte_lookup_locals(rte, 'filename') if not om_isinstance(filename, class_str): - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, "filename must be a str") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('filename must be a str')) else: filename_value = OM_get_boxed_value(filename) if len(filename_value) == 0: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, - "filename must be a non-empty str") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('filename must be a non-empty str')) elif runtime_file_exists(rte, filename_value): content = runtime_read_file(rte, filename_value) return unwind_return(rte, om_str(content)) else: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_FileNotFoundError, - "No such file: '" + filename_value + "'") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_FileNotFoundError, + tformat("No such file: {0}", [om_format_str_repr(filename)])) om_readFile = om_make_builtin_function_with_signature('readFile', readFile_code, @@ -9469,16 +9494,15 @@ def writeFile_code(rte, cont): content = rte_lookup_locals(rte, 'content') if not om_isinstance(filename, class_str): - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, "filename must be a str") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('filename must be a str')) elif not om_isinstance(content, class_str): - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, "content must be a str") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('content must be a str')) else: filename_value = OM_get_boxed_value(filename) content_value = OM_get_boxed_value(content) if len(filename_value) == 0: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_TypeError, - "filename must be a non-empty str") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_TypeError, tformat('filename must be a non-empty str')) else: runtime_write_file(rte, filename_value, content_value) return unwind_return(rte, om_None) @@ -9493,10 +9517,12 @@ def writeFile_code(rte, cont): om_document = om(class_DOMDocument) def om_DOMDocument_new_code(ctx, args): - if len(args) == 1: + args_len = len(args) + + if args_len == 1: return cont_obj(ctx, om_document) else: - return sem_raise_with_message(ctx, class_TypeError, 'DOMDocument takes no argument') + return sem_raise_with_tformat(ctx, class_TypeError, tformat('{0}() takes no argument ({1} given)', ["DOMDocument", str(args_len - 1)])) om_DOMDocument_new = do_static_magic_method(class_DOMDocument, '__new__', om_DOMDocument_new_code) @@ -9518,9 +9544,9 @@ def om_DOMDocument_querySelector_code(ctx, args): else: return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "HTML element selector must be a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("HTML element selector must be a string")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected one argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected one argument, got {0}', [str(args_len - 1)])) om_DOMDocument_querySelector = do_magic_method(class_DOMDocument, "querySelector", om_DOMDocument_querySelector_code) @@ -9539,7 +9565,7 @@ def om_DOMElement_innerHTML_getter(ctx, instance): content = runtime_getInnerHTML(ctx.rte, OM_get_DOMElement_elem(instance)) return cont_str(ctx, content) else: - return sem_raise_with_message(ctx, class_TypeError, "innerHTML descriptor expected a 'DOMElement'") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("innerHTML descriptor expected a 'DOMElement'")) def om_DOMElement_innerHTML_setter(ctx, instance, content): @@ -9549,9 +9575,9 @@ def om_DOMElement_innerHTML_setter(ctx, instance, content): runtime_setInnerHTML(ctx.rte, OM_get_DOMElement_elem(instance), content_value) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "innerHTML attribute must be set to a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} attribute must be set to a string" , ["innerHTML"])) else: - return sem_raise_with_message(ctx, class_TypeError, "innerHTML descriptor expected a 'DOMElement'") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("innerHTML descriptor expected a 'DOMElement'")) def om_DOMElement_value_getter(ctx, instance): @@ -9561,7 +9587,7 @@ def om_DOMElement_value_getter(ctx, instance): content = runtime_getValue(ctx.rte, OM_get_DOMElement_elem(instance)) return cont_str(ctx, content) else: - return sem_raise_with_message(ctx, class_TypeError, "value descriptor expected a 'DOMElement'") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("value descriptor expected a '{0}'", ["DOMElement"])) def om_DOMElement_value_setter(ctx, instance, content): @@ -9571,9 +9597,9 @@ def om_DOMElement_value_setter(ctx, instance, content): runtime_setValue(ctx.rte, OM_get_DOMElement_elem(instance), content_value) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "value attribute must be set to a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'{0}' attribute must be set to a string" , ["value"])) else: - return sem_raise_with_message(ctx, class_TypeError, "value descriptor expected a 'DOMElement'") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("value descriptor expected a '{0}'", ["DOMElement"])) def gen_DOMElement_handleAttribute(name, runtime_fn, do_cont): @@ -9588,9 +9614,9 @@ def om_DOMElement_handleAttribute_code(ctx, args): if om_isinstance(attr, class_str): return do_cont(ctx, runtime_fn(ctx.rte, elem, OM_get_boxed_value(attr))) else: - return sem_raise_with_message(ctx, class_TypeError, "'DOMElement' attribute must be a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'DOMElement' attribute must be a string")) else: - return sem_raise_with_message(ctx, class_TypeError, "expected one argument, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected one argument, got {0}', [str(args_len - 1)])) return do_magic_method(class_DOMElement, name, om_DOMElement_handleAttribute_code) @@ -9608,11 +9634,11 @@ def om_DOMElement_setAttribute_code(ctx, args): runtime_setAttribute(ctx.rte, elem, OM_get_boxed_value(attr), OM_get_boxed_value(value)) return cont_obj(ctx, om_None) else: - return sem_raise_with_message(ctx, class_TypeError, "'DOMElement' attribute value must be a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} attribute value must be a string", ['DOMElement'])) else: - return sem_raise_with_message(ctx, class_TypeError, "'DOMElement' attribute must be a string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} attribute must be a string", ['DOMElement'])) else: - return sem_raise_with_message(ctx, class_TypeError, "expected 2 arguments, got " + str(args_len - 1)) + return sem_raise_with_tformat(ctx, class_TypeError, tformat('expected {0} arguments, got {1}', ["2", str(args_len - 1)])) om_DOMElement_setAttribute = do_magic_method(class_DOMElement, "setAttribute", om_DOMElement_setAttribute_code) @@ -9727,7 +9753,7 @@ def om_host_eval_code(rte, cont): expr = rte_lookup_locals(rte, 'expr') result = host2py(host_eval(py2host(expr))) if result == absent: - return sem_raise_with_message(make_out_of_ast_context(rte, cont), class_ValueError, "Could not convert JavaScript type to Python") + return sem_raise_with_tformat(make_out_of_ast_context(rte, cont), class_ValueError, tformat('Could not convert JavaScript type to Python')) return unwind_return(rte, result) def om_runtime_chart_code(rte, cont): @@ -11401,7 +11427,7 @@ def get_bases(bases_rte, bases_list): def exec_body(kwargs_rte, kwargs_dict): if dict_len(kwargs_dict) > 0: ctx = Context(kwargs_rte, cont, keywords[0]) - return sem_raise_with_message(ctx, class_NotImplementedError, "class keyword arguments not yet supported") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("class keyword arguments not yet supported")) else: class_locals_env = make_dict() body_rte = make_class_rte(rte, class_locals_env) @@ -11414,7 +11440,7 @@ def create_class(_): b_type = OM_get_object_class(b) if om_is_not(b_type, class_type): ctx = Context(kwargs_rte, cont, bases[i]) - return sem_raise_with_message(ctx, class_NotImplementedError, "derived metaclass must be 'type'") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("derived metaclass must be 'type'")) else: i += 1 @@ -11424,7 +11450,7 @@ def create_class(_): # mro could not if om_class is None: ctx = Context(kwargs_rte, cont, bases[0]) - return sem_raise_with_message(ctx, class_TypeError, "Cannot create a consistent method resolution order (MRO) for bases") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("Cannot create a consistent method resolution order (MRO) for bases")) for pair in dict_items(class_locals_env): key = pair[0] @@ -11472,9 +11498,9 @@ def do_assign(assign_rte): i -= 1 return next_cont(start_assign_rte) elif targets_len < seq_len: - return sem_raise_with_message(Context(start_assign_rte, cont, ast), class_ValueError, "too many values to unpack") + return sem_raise_with_tformat(Context(start_assign_rte, cont, ast), class_ValueError, tformat('too many values to unpack')) else: - return sem_raise_with_message(Context(start_assign_rte, cont, ast), class_ValueError, "not enough values to unpack") + return sem_raise_with_tformat(Context(start_assign_rte, cont, ast), class_ValueError, tformat('not enough values to unpack')) return om_unpack_iterable(Context(unpack_rte, start_assignments, ast), iterable) return value_code(rte, unpack) return cte, code @@ -11623,8 +11649,7 @@ def get_exc_type(type_rte, exc_type): else: return skip_cont(type_rte) else: - return sem_raise_with_message(Context(type_rte, skip_cont, exc_type), - class_TypeError, "catching classes that do not inherit from BaseException is not allowed") + return sem_raise_with_tformat(Context(type_rte, skip_cont, exc_type), class_TypeError, tformat('catching classes that do not inherit from BaseException is not allowed')) return exc_type_code(rte, get_exc_type) return body_cte, code @@ -11645,8 +11670,7 @@ def exec_body(rte): else: return skip_cont(type_rte) else: - return sem_raise_with_message(Context(type_rte, skip_cont, exc_type), - class_TypeError, "catching classes that do not inherit from BaseException is not allowed") + return sem_raise_with_tformat(Context(type_rte, skip_cont, exc_type), class_TypeError, tformat('catching classes that do not inherit from BaseException is not allowed')) return exc_type_code(rte, get_exc_type) return body_cte, code @@ -11715,7 +11739,7 @@ def raise_current(rte, cont): ctx = Context(rte, cont, ast) current_exc = rte_get_current_exc(rte) if current_exc is absent: - return sem_raise_with_message(ctx, class_RuntimeError, "No active exception to reraise") + return sem_raise_with_tformat(ctx, class_RuntimeError, tformat("No active exception to reraise")) else: return sem_raise_unsafe(rte, current_exc) return cte, raise_current @@ -11767,11 +11791,11 @@ def exec_context_obj(rte, unopened_context): # https://docs.python.org/3.8/reference/compound_stmts.html#with item_enter = getattribute_from_obj_mro(unopened_context, '__enter__') if item_enter is absent: - return sem_raise_with_message(Context(rte, cont, optional_vars), class_AttributeError, "__enter__") + return sem_raise_with_tformat(Context(rte, cont, optional_vars), class_AttributeError, tformat('__enter__')) item_exit = getattribute_from_obj_mro(unopened_context, '__exit__') if item_exit is absent: - return sem_raise_with_message(Context(rte, cont, optional_vars), class_AttributeError, "__exit__") + return sem_raise_with_tformat(Context(rte, cont, optional_vars), class_AttributeError, tformat('__exit__')) def enter_context(enter_rte, context_val): # Put a try-except-finally around the execution of the body @@ -11853,7 +11877,7 @@ def code(rte, cont): # When repl fails to re-import a module (deleted of not a file), take existing one from sys.modules return set_code(rte, cont, existing_module) else: - return sem_raise_with_message(Context(rte, cont, ast), class_ModuleNotFoundError, "No module named '" + name + "'") + return sem_raise_with_tformat(Context(rte, cont, ast), class_ModuleNotFoundError, tformat("No module named '{0}'", [name])) else: module_src = runtime_read_file(rte, filename) container = runtime_get_file_container(rte, filename) @@ -12338,8 +12362,8 @@ def sem_Neg(ctx, val1): val1_neg = getattribute_from_obj_mro(val1, '__neg__') if val1_neg is absent: cls = OM_get_object_class(val1) - cls_name = OM_get_boxed_value(OM_get(cls, "__name__")) - return sem_raise_with_message(ctx, class_TypeError, "bad operand type for unary -: '"+cls_name+"'") + cls_name = OM_get_class_name(cls) + return sem_raise_with_tformat(ctx, class_TypeError, tformat("bad operand type for unary {0}: '{1}'", ["-", cls_name])) else: return sem_simple_call(ctx, val1_neg, [val1]) @@ -12347,8 +12371,8 @@ def sem_Pos(ctx, val1): val1_pos = getattribute_from_obj_mro(val1, '__pos__') if val1_pos is absent: cls = OM_get_object_class(val1) - cls_name = OM_get_boxed_value(OM_get(cls, "__name__")) - return sem_raise_with_message(ctx, class_TypeError, "bad operand type for unary +: '"+cls_name+"'") + cls_name = OM_get_class_name(cls) + return sem_raise_with_tformat(ctx, class_TypeError, tformat("bad operand type for unary {0}: '{1}'", ["+", cls_name])) else: return sem_simple_call(ctx, val1_pos, [val1]) @@ -12356,8 +12380,8 @@ def sem_Invert(ctx, val1): val1_pos = getattribute_from_obj_mro(val1, '__invert__') if val1_pos is absent: cls = OM_get_object_class(val1) - cls_name = OM_get_boxed_value(OM_get(cls, "__name__")) - return sem_raise_with_message(ctx, class_TypeError, "bad operand type for unary ~: '"+cls_name+"'") + cls_name = OM_get_class_name(cls) + return sem_raise_with_tformat(ctx, class_TypeError, tformat("bad operand type for unary {0}: '{1}'", ["~", cls_name])) else: return sem_simple_call(ctx, val1_pos, [val1]) @@ -12365,7 +12389,16 @@ def gen_sem_IOperator(method_name, sem_fall_back, op_name): def sem_IOp(ctx, self, other): def cont_raise_error(rte, result): if om_is(result, om_NotImplemented): - return sem_raise_with_message(ctx, class_TypeError, "unsupported operand type(s) for " + op_name) + self_type = OM_get_object_class(self) + other_type = OM_get_object_class(other) + + self_type_name = OM_get_class_name(self_type) + other_type_name = OM_get_class_name(other_type) + + msg = tformat("unsupported operand type(s) for {0}: {1}", + (op_symbol, tenum([self_type_name, other_type_name]))) + + return sem_raise_with_tformat(ctx, class_TypeError, msg) else: return cont_obj(ctx, result) @@ -12417,7 +12450,7 @@ def check_string(rte, res): rte_repr_exit(rte) return ctx.cont(rte, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__repr__ returned non-string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} returned non-string", ["__repr__"])) ctx1 = with_cont(ctx, check_string) return sem_simple_call(ctx1, val1_repr, [val1]) @@ -12429,7 +12462,7 @@ def check_string(rte, res): if om_isinstance(res, class_str): return ctx.cont(rte, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__str__ returned non-string") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} returned non-string", ["__str__"])) next_ctx = with_cont(ctx, check_string) return sem_simple_call(next_ctx, value_str, [value]) @@ -12484,7 +12517,7 @@ def sem_simple_call(ctx, obj, args): obj_call = getattribute_from_obj_mro(obj, '__call__') if obj_call is absent: class_name = OM_get_object_class_name(obj) - return sem_raise_with_message(ctx, class_TypeError, "'" + class_name + "' object is not callable") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'{0}' object is not callable", [class_name])) else: return sem_simple_call(ctx, obj_call, [obj] + args) @@ -12503,7 +12536,7 @@ def sem_generic_call(ctx, obj, args, kwargs): instance = OM_get_MethodWrapper_instance(obj) return code(ctx, [instance] + args, kwargs) else: - return sem_raise_with_message(ctx, class_TypeError, "method takes no keyword arguments") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("method takes no keyword arguments")) elif om_is(obj_type, class_WrapperDescriptor): requires_kwargs = OM_get_requires_kwargs(obj) @@ -12511,35 +12544,35 @@ def sem_generic_call(ctx, obj, args, kwargs): code = OM_get_code(obj) return code(ctx, args, kwargs) else: - return sem_raise_with_message(ctx, class_TypeError, "function takes no keyword arguments") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("function takes no keyword arguments")) elif om_is(obj_type, class_function): return om_function_call_code(ctx, [obj] + args, kwargs) else: obj_call = getattribute_from_obj_mro(obj, '__call__') if obj_call is absent: class_name = OM_get_object_class_name(obj) - return sem_raise_with_message(ctx, class_TypeError, "'" + class_name + "' object is not callable") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'{0}' object is not callable", [class_name])) else: return sem_generic_call(ctx, obj_call, [obj] + args, kwargs) def sem_getitem(ctx, obj, item): obj_getitem = getattribute_from_obj_mro(obj, "__getitem__") if obj_getitem is absent: - return sem_raise_with_message(ctx, class_TypeError, 'object is not subscriptable') + return sem_raise_with_tformat(ctx, class_TypeError, tformat('object is not subscriptable')) else: return sem_simple_call(ctx, obj_getitem, [obj, item]) def sem_setitem(ctx, obj, item, val): obj_setitem = getattribute_from_obj_mro(obj, "__setitem__") if obj_setitem is absent: - return sem_raise_with_message(ctx, class_TypeError, 'object does not support item assignment') + return sem_raise_with_tformat(ctx, class_TypeError, tformat('object does not support item assignment')) else: return sem_simple_call(with_cont(ctx, lambda rte, _: ctx.cont(rte)), obj_setitem, [obj, item, val]) def sem_next(ctx, obj, default_): obj_next = getattribute_from_obj_mro(obj, "__next__") if obj_next is absent: - return sem_raise_with_message(ctx, class_TypeError, "object is not an iterator") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("object is not an iterator")) elif default_ is absent: return sem_simple_call(ctx, obj_next, [obj]) else: @@ -12569,7 +12602,7 @@ def sem_iter(ctx, obj): if obj_iter is absent: obj_getitem = getattribute_from_obj_mro(obj, "__getitem__") if obj_getitem is absent: - return sem_raise_with_message(ctx, class_TypeError, "object is not iterable") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("object is not iterable")) else: return ctx.cont(ctx.rte, om_iterator(obj, om_int(int_from_num(0)))) else: @@ -12671,7 +12704,7 @@ def om_unpack_mapping(ctx, mapping): if om_isinstance(mapping, class_dict): return cont_obj(ctx, OM_get_boxed_value(mapping)) else: - return sem_raise_with_message(ctx, class_NotImplementedError, "mapping unpacking is not yet supported for non-dict objects") + return sem_raise_with_tformat(ctx, class_NotImplementedError, tformat("mapping unpacking is not yet supported for non-dict objects")) def sem_maybe_len(ctx, obj): obj_len = getattribute_from_obj_mro(obj, "__len__") @@ -12684,7 +12717,7 @@ def check_range(range_rte, len_res): if int_is_nonneg(res_value): return cont_obj(ctx, res) else: - return sem_raise_with_message(ctx, class_ValueError, "__len__() should return >= 0") + return sem_raise_with_tformat(ctx, class_ValueError, tformat("__len__() should return >= 0")) return sem_index(with_cont(ctx, check_range), res) return sem_simple_call(with_cont(ctx, check_result), obj_len, [obj]) @@ -12692,8 +12725,8 @@ def sem_len(ctx, obj): def cont(rte, val): if val is absent: obj_cls_name = OM_get_object_class_name(obj) - error_msg = "object of type '" + obj_cls_name + "' has no len()" - return sem_raise_with_message(ctx, class_TypeError, error_msg) + error_msg = tformat("object of type '{0}' has no len()", [obj_cls_name]) + return sem_raise_with_tformat(ctx, class_TypeError, error_msg) else: return ctx.cont(rte, val) @@ -12703,7 +12736,7 @@ def sem_abs(ctx, obj): obj_abs = getattribute_from_obj_mro(obj, '__abs__') if obj_abs is absent: - return sem_raise_with_message(ctx, class_TypeError, "bad operand type for abs()") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("bad operand type for abs()")) else: return sem_simple_call(ctx, obj_abs, [obj]) @@ -12717,13 +12750,15 @@ def check_int(rte, res): if om_isinstance(res, class_int): return ctx.cont(rte, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__int__ returned non-int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} returned non-int", ["__int__"])) return sem_simple_call(with_cont(ctx, check_int), obj_int, [obj]) def sem_int(ctx, obj): def check_result(rte, res): if res is absent: - return sem_raise_with_message(ctx, class_TypeError, "object cannot be interpreted as an integer") + obj_cls = OM_get_object_class(obj) + cls_name = OM_get_class_name(obj_cls) + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'{0}' object cannot be interpreted as an integer", [cls_name])) else: return cont_obj(ctx, res) return sem_maybe_int(with_cont(ctx, check_result), obj) @@ -12739,13 +12774,15 @@ def check_int(rte, res): if om_isinstance(res, class_int): return ctx.cont(rte, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__index__ returned non-int") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("{0} returned non-int", ["__index__"])) return sem_simple_call(with_cont(ctx, check_int), obj_int, [obj]) def sem_index(ctx, obj): def check_result(rte, res): if res is absent: - return sem_raise_with_message(ctx, class_TypeError, "object cannot be interpreted as an integer") + obj_cls = OM_get_object_class(obj) + cls_name = OM_get_class_name(obj_cls) + return sem_raise_with_tformat(ctx, class_TypeError, tformat("'{0}' object cannot be interpreted as an integer", [cls_name])) else: return cont_obj(ctx, res) return sem_maybe_index(with_cont(ctx, check_result), obj) @@ -12760,13 +12797,13 @@ def check_float(rte, res): if om_isinstance(res, class_float): return ctx.cont(rte, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__float__ returned non-float") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("__float__ returned non-float")) return sem_simple_call(with_cont(ctx, check_float), obj_float, [obj]) def sem_float(ctx, obj): def check_result(rte, res): if res is absent: - return sem_raise_with_message(ctx, class_TypeError, "object cannot be interpreted as a float") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("object cannot be interpreted as a float")) else: return cont_obj(ctx, res) return sem_maybe_float(with_cont(ctx, check_result), obj) @@ -12925,15 +12962,16 @@ def sem_var_get_local(ctx, id): value = rte_lookup_locals(ctx.rte, id) if value is absent: - return sem_raise_with_message(ctx, class_UnboundLocalError, - "local variable '" + id + "' referenced before assignment") + return sem_raise_with_tformat(ctx, class_UnboundLocalError, + tformat("local variable '{0}' referenced before assignment", [id])) return cont_obj(ctx, value) def sem_var_get_local_boxed(ctx, id): value = rte_lookup_locals_boxed(ctx.rte, id) if value is absent: - return sem_raise_with_message(ctx, class_UnboundLocalError, "local variable '" + id + "' referenced before assignment") + return sem_raise_with_tformat(ctx, class_UnboundLocalError, + tformat("local variable '{0}' referenced before assignment", [id])) return cont_obj(ctx, value) @@ -12942,8 +12980,8 @@ def sem_var_get_class_closure_boxed(ctx, id): value = dict_get(parent_locals_env, id, absent)[0] if value is absent: - return sem_raise_with_message(ctx, class_NameError, - "free variable '" + id + "' referenced before assignment in enclosing scope") + return sem_raise_with_tformat(ctx, class_NameError, + tformat("free variable '{0}' referenced before assignment in enclosing scope", [id])) else: return cont_obj(ctx, value) @@ -12953,8 +12991,8 @@ def sem_var_get_class_closure(ctx, id): value = dict_get(parent_locals_env, id, absent) if value is absent: - return sem_raise_with_message(ctx, class_NameError, - "free variable '" + id + "' referenced before assignment in enclosing scope") + return sem_raise_with_tformat(ctx, class_NameError, + tformat("free variable '{0}' referenced before assignment in enclosing scope", [id])) else: return cont_obj(ctx, value) @@ -12963,15 +13001,16 @@ def sem_var_get_closure(ctx, pos, id): value = rte_lookup_closure(ctx.rte, pos) if value is absent: - return sem_raise_with_message(ctx, class_NameError, "free variable '" + id + "' referenced before assignment in enclosing scope") + return sem_raise_with_tformat(ctx, class_NameError, + tformat("free variable '{0}' referenced before assignment in enclosing scope", [id])) else: return cont_obj(ctx, value) def sem_var_get_global(ctx, id): def catch_AttributeError(exn): if om_isinstance(exn, class_AttributeError): - error_msg = "name '" + id + "' is not defined" - return sem_raise_with_message(ctx, class_NameError, error_msg) + error_msg = tformat("name '{0}' is not defined", [id]) + return sem_raise_with_tformat(ctx, class_NameError, error_msg) else: return sem_raise_unsafe(ctx.rte, exn) @@ -13001,7 +13040,7 @@ def check_bool(rte, res): if om_is(res, om_True) or om_is(res, om_False): return cont_obj(ctx, res) else: - return sem_raise_with_message(ctx, class_TypeError, "__bool__ should return bool") + return sem_raise_with_tformat(ctx, class_TypeError, tformat("__bool__ should return bool")) return sem_simple_call(with_cont(ctx, check_bool), val_bool, [val]) @@ -13041,9 +13080,13 @@ def sem_raise(ctx, exn): return sem_raise_unsafe(rte, exn_obj) +# Obsolete: use sem_raise_with_tformat to allow translation of error messages +#def sem_raise_with_message(ctx, exn_type, msg): +# args = om_tuple((om_str(msg),)) +# return sem_raise(ctx, om_exception(exn_type, args)) -def sem_raise_with_message(ctx, exn_type, msg): - args = om_tuple((om_str(msg),)) +def sem_raise_with_tformat(ctx, exn_type, tformat_obj): + args = om_tuple((om_str_from_tformat(tformat_obj),)) return sem_raise(ctx, om_exception(exn_type, args)) @@ -13422,28 +13465,8 @@ def om_simple_repr_with_max_length(ctx, value, max_length): return repr_res -def om_simple_exception_format(ctx, exn): - exn_name = OM_get_object_class_qualname(exn) - exn_args = OM_get(exn, 'args') - - if exn_args is absent or not om_isinstance(exn_args, class_tuple): - return exn_name + ': ' - else: - seq = OM_get_tuple_seq(exn_args) - if len(seq) == 0: - return exn_name - elif len(seq) == 1: - el = seq[0] - if om_isinstance(el, class_str): - return exn_name + ": " + OM_get_boxed_value(el) - else: - return exn_name + ": " + om_simple_repr(ctx, seq[0]) - else: - return exn_name + ": " + om_simple_repr(ctx, exn_args) - - -def expr_end_with_error(ctx, error): - return return_to_trampoline(ctx.ast, '', 0, False, False, None, error, lambda: None, ctx) +def expr_end_with_error(ctx, error_msg): + return return_to_trampoline(ctx.ast, '', 0, False, False, None, error_msg, lambda: None, ctx) def expr_end(ctx, val): return expr_end_with_step(ctx, val, 1)