diff --git a/aheui/aheui.py b/aheui/aheui.py index b72ccf3..f04962c 100644 --- a/aheui/aheui.py +++ b/aheui/aheui.py @@ -10,7 +10,7 @@ from aheui._compat import jit, unichr, ord, _unicode, bigint, PYR from aheui import compile from aheui.option import process_options, OptionError -from aheui.warning import WarningPool +from aheui.warning import NoRpythonWarning, WriteUtf8RangeWarning, warnings def get_location(pc, stackok, is_queue, program): @@ -283,7 +283,7 @@ def write_number(value_str): os.write(outfp, value_str) -def write_utf8(warnings, value): +def write_utf8(value): REPLACE_CHAR = unichr(0xfffd).encode('utf-8') if bigint.is_unicodepoint(value): @@ -296,8 +296,8 @@ def write_utf8(warnings, value): os.write(outfp, bytes) -def warn_utf8_range(warnings, value): - warnings.warn(b'write-utf8-range', value) +def warn_utf8_range(value): + warnings.warn(WriteUtf8RangeWarning, value) os.write(outfp, unichr(0xfffd).encode('utf-8')) class Program(object): @@ -328,7 +328,6 @@ def get_label(self, pc): outfp = 1 errfp = 2 -warnings = WarningPool() def mainloop(program, debug): @@ -422,7 +421,7 @@ def mainloop(program, debug): write_number(bigint.str(r)) elif op == c.OP_POPCHAR: r = selected.pop() - write_utf8(warnings, r) + write_utf8(r) elif op == c.OP_PUSHNUM: num = read_number() selected.push(num) @@ -499,7 +498,7 @@ def entry_point(argv): outfp = 1 if output == '-' else open_w(output) if target == 'run': if not PYR: - warnings.warn(b'no-rpython') + warnings.warn(NoRpythonWarning) program = Program(compiler.lines, compiler.label_map) exitcode = mainloop(program, compiler.debug) elif target in ['asm', 'asm+comment']: diff --git a/aheui/option.py b/aheui/option.py index d22f160..23ef81e 100644 --- a/aheui/option.py +++ b/aheui/option.py @@ -6,6 +6,7 @@ from aheui._argparse import ArgumentParser, ParserError from aheui._compat import bigint, PY3 from aheui.version import VERSION +from aheui.warning import CommandLineArgumentWarning, warnings from aheui import compile @@ -56,16 +57,16 @@ def message(self): return 'The value of %s="%s" is not a valid integer' % self.args -class SourceError(Exception): +class SourceError(OptionError): pass -class NoInputError(Exception): +class NoInputError(SourceError): def message(self): return "no input files" -class CommandConflictInputFileError(Exception): +class CommandConflictInputFileError(SourceError): def message(self): return "--cmd,-c and input file cannot be used together" @@ -177,6 +178,9 @@ def process_options(argv, environ): else: assert False # must be handled by argparse raise SystemExit() + else: + if target == 'run': + warnings.warn(CommandLineArgumentWarning, '--target=run always ignores --output') warning_limit = kwarg_or_environ_int(kwargs, environ, 'warning-limit', 'RPAHEUI_WARNING_LIMIT', 3) trace_limit = kwarg_or_environ_int(kwargs, environ, 'trace-limit', 'RPAHEUI_TRACE_LIMIT', -1) diff --git a/aheui/warning.py b/aheui/warning.py index e8f7265..0060f63 100644 --- a/aheui/warning.py +++ b/aheui/warning.py @@ -5,36 +5,46 @@ class Warning(object): - def __init__(self, name, message): - self.name = name - self.message = message - def format(self, *args): - return self.message % args + return self.MESSAGE % args + + +class NoRpythonWarning(Warning): + MESSAGE = b"[Warning:VirtualMachine] Running without rlib/jit." + + +class CommandLineArgumentWarning(Warning): + MESSAGE = b"[Warning:CommandLine] Invalid command line argument is ignored: %s." + + +class WriteUtf8RangeWarning(Warning): + MESSAGE = b'[Warning:UndefinedBehavior:write-utf8-range] value %x is out of unicode codepoint range.' WARNING_LIST = [ - Warning(b'no-rpython', b"[Warning:VirtualMachine] Running without rlib/jit.\n"), - Warning(b'write-utf8-range', b'[Warning:UndefinedBehavior:write-utf8-range] value %x is out of unicode codepoint range.'), + NoRpythonWarning(), + CommandLineArgumentWarning(), + WriteUtf8RangeWarning(), ] class WarningPool(object): def __init__(self): self.limit = -1 - self.warnings = {} self.counters = {} for w in WARNING_LIST: - self.warnings[w.name] = w - self.counters[w.name] = 0 + self.counters[type(w).__name__] = 0 @jit.dont_look_inside - def warn(self, name, *args): - warning = self.warnings[name] + def warn(self, warning, *args): + name = warning.__name__ if self.limit != -1 and self.limit <= self.counters[name]: return self.counters[name] = self.counters[name] + 1 - os.write(2, warning.format(*args)) + os.write(2, warning().format(*args)) os.write(2, b'\n') if self.limit != -1 and self.limit <= self.counters[name]: - os.write(2, b"[Warning:Meta] The warning '%s' has reached the limit %d and will be suppressed\n" % (warning.name, self.limit)) + os.write(2, b"[Warning:Meta] The warning '%s' has reached the limit %d and will be suppressed\n" % (name, self.limit)) + + +warnings = WarningPool()