# HG changeset patch # User Paul Boddie # Date 1478819134 -3600 # Node ID 78e02906e7f28ea1ec8b27e351d8412626524773 # Parent 459b1a69fdbbe6836da27d63fdae95e77141572f Added initial support for the print statement and stream output. Added error reporting where invocation arguments are missing. diff -r 459b1a69fdbb -r 78e02906e7f2 common.py --- a/common.py Fri Nov 11 00:03:05 2016 +0100 +++ b/common.py Fri Nov 11 00:05:34 2016 +0100 @@ -510,6 +510,26 @@ ) return self.process_structure_node(invocation) + def process_print_node(self, n): + + """ + Process the given print node 'n' as an invocation on a stream of the + form... + + $print(dest, args, nl) + + The special function name will be translated elsewhere. + """ + + nl = isinstance(n, compiler.ast.Printnl) + invocation = compiler.ast.CallFunc( + compiler.ast.Name("$print"), + [n.dest or compiler.ast.Name("None"), + compiler.ast.List(list(n.nodes)), + nl and compiler.ast.Name("True") or compiler.ast.Name("false")] + ) + return self.process_structure_node(invocation) + def process_slice_node(self, n, expr=None): """ diff -r 459b1a69fdbb -r 78e02906e7f2 inspector.py --- a/inspector.py Fri Nov 11 00:03:05 2016 +0100 +++ b/inspector.py Fri Nov 11 00:05:34 2016 +0100 @@ -278,6 +278,11 @@ self.process_structure(n) self.trackers[-1].abandon_returning_branch() + # Print statements. + + elif isinstance(n, (compiler.ast.Print, compiler.ast.Printnl)): + self.process_print_node(n) + # Invocations. elif isinstance(n, compiler.ast.CallFunc): @@ -774,7 +779,7 @@ path = self.get_namespace_path() - # Special names. + # Special names that have already been identified. if n.name.startswith("$"): value = self.get_special(n.name) @@ -801,6 +806,20 @@ self.set_special(n.name, value) return value + # Special case for print operations. + + elif n.name.startswith("$print"): + + # Attempt to get a reference. + + ref = self.get_builtin("print_") + + # Record the imported name and provide the resolved name reference. + + value = ResolvedNameRef(n.name, ref) + self.set_special(n.name, value) + return value + # Test for self usage, which is only allowed in methods. if n.name == "self" and not (self.in_function and self.in_class): diff -r 459b1a69fdbb -r 78e02906e7f2 lib/__builtins__/__init__.py --- a/lib/__builtins__/__init__.py Fri Nov 11 00:03:05 2016 +0100 +++ b/lib/__builtins__/__init__.py Fri Nov 11 00:05:34 2016 +0100 @@ -96,7 +96,7 @@ from __builtins__.character import chr, hex, oct, ord, unichr from __builtins__.comparable import cmp, hash from __builtins__.identity import callable, help, id, isinstance, issubclass, repr -from __builtins__.io import eval, open, raw_input +from __builtins__.io import open, raw_input, print_, sysfile from __builtins__.iterable import all, any, enumerate, filter, iter, len, map, max, min, range, reduce, reversed, sorted, sum, zip from __builtins__.namespace import dir, globals, locals, vars from __builtins__.numeric import abs, divmod, pow, round diff -r 459b1a69fdbb -r 78e02906e7f2 lib/__builtins__/file.py --- a/lib/__builtins__/file.py Fri Nov 11 00:03:05 2016 +0100 +++ b/lib/__builtins__/file.py Fri Nov 11 00:05:34 2016 +0100 @@ -3,7 +3,7 @@ """ File objects. -Copyright (C) 2015 Paul Boddie +Copyright (C) 2015, 2016 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -20,6 +20,10 @@ """ class file(object): + + "A file abstraction." + + def __init__(self, name, mode=None, buffering=None): pass def read(self, n=None): pass def write(self, s): pass def close(self): pass diff -r 459b1a69fdbb -r 78e02906e7f2 lib/__builtins__/io.py --- a/lib/__builtins__/io.py Fri Nov 11 00:03:05 2016 +0100 +++ b/lib/__builtins__/io.py Fri Nov 11 00:05:34 2016 +0100 @@ -3,7 +3,7 @@ """ Input/output-related functions. -Copyright (C) 2015 Paul Boddie +Copyright (C) 2015, 2016 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,8 +19,69 @@ this program. If not, see . """ -def eval(source, globals=None, locals=None): pass -def open(name, mode=None, buffering=None): pass +from native import _read, _write +from sys import stdout + +class sysfile: + + "A system-level file object." + + def __init__(self, fd): + + "Initialise the file with the given 'fd'." + + self.fd = fd + + def read(self, n): + + "Read 'n' bytes from the file." + + return _read(self.fd, n) + + def write(self, s): + + "Write 's' to the file." + + _write(self.fd, str(s)) + +def open(name, mode=None, buffering=None): + + """ + Open the file with the given 'name', using the given 'mode' and applying the + indicated 'buffering'. + """ + + return file(name, mode, buffering) + def raw_input(prompt=None): pass +def print_(dest, args, nl): + + """ + Write to 'dest' the string representation of 'args', adding a newline if + 'nl' is given as a true value. + """ + + # Write to standard output if dest is not specified. + + dest = dest or stdout + + first = True + + for arg in args: + + # Insert spaces between arguments. + + if first: + first = False + else: + dest.write(" ") + + dest.write(str(arg)) + + # Add a newline if specified. + + if nl: + dest.write("\n") + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 459b1a69fdbb -r 78e02906e7f2 lib/native.py --- a/lib/native.py Fri Nov 11 00:03:05 2016 +0100 +++ b/lib/native.py Fri Nov 11 00:05:34 2016 +0100 @@ -63,4 +63,7 @@ def _isinstance(obj, cls): pass +def _read(fd, n): pass +def _write(fd, str): pass + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 459b1a69fdbb -r 78e02906e7f2 lib/sys.py --- a/lib/sys.py Fri Nov 11 00:03:05 2016 +0100 +++ b/lib/sys.py Fri Nov 11 00:05:34 2016 +0100 @@ -21,20 +21,17 @@ from native import _exit -# Placeholders for run-time data. +# Standard streams. -stdin = file() -stdout = file() -stderr = file() +stdin = sysfile(0) +stdout = sysfile(1) +stderr = sysfile(2) + +# NOTE: Environment details to be implemented. argv = [] path = [] -hexversion = 0x20703f0 # 2.7.3 final 0 -maxint = 2147483647 # 2**31 - 1 -maxunicode = 1114111 -platform = 'posix' - # Functions to be implemented natively. def exit(status=0): diff -r 459b1a69fdbb -r 78e02906e7f2 templates/native.c --- a/templates/native.c Fri Nov 11 00:03:05 2016 +0100 +++ b/templates/native.c Fri Nov 11 00:05:34 2016 +0100 @@ -1,4 +1,5 @@ #include /* calloc, exit */ +#include /* read, write */ #include "types.h" #include "exceptions.h" #include "ops.h" @@ -368,6 +369,30 @@ #undef cls } +__attr __fn_native__read(__attr __args[]) +{ + #define fd (__args[1]) + #define n (__args[2]) + + /* NOTE: To be written. */ + return __builtins___none_None; + #undef fd + #undef n +} + +__attr __fn_native__write(__attr __args[]) +{ + #define fd (__args[1]) + #define str (__args[2]) + + /* NOTE: To be written. */ + return __builtins___none_None; + #undef fd + #undef str +} + +/* Module initialisation. */ + void __main_native() { } diff -r 459b1a69fdbb -r 78e02906e7f2 templates/native.h --- a/templates/native.h Fri Nov 11 00:03:05 2016 +0100 +++ b/templates/native.h Fri Nov 11 00:05:34 2016 +0100 @@ -37,6 +37,11 @@ __attr __fn_native__tuple_len(__attr __args[]); __attr __fn_native__tuple_element(__attr __args[]); __attr __fn_native__isinstance(__attr __args[]); +__attr __fn_native__read(__attr __args[]); +__attr __fn_native__write(__attr __args[]); + +/* Module initialisation. */ + void __main_native(); #endif /* __NATIVE_H__ */ diff -r 459b1a69fdbb -r 78e02906e7f2 tests/assign_sequence.py --- a/tests/assign_sequence.py Fri Nov 11 00:03:05 2016 +0100 +++ b/tests/assign_sequence.py Fri Nov 11 00:05:34 2016 +0100 @@ -3,6 +3,9 @@ x = l a, b, c = l d, e, f = [1, 2, 3] + print a, b, c + print d, e, f + print x def g(x): l = [1, 2, 3] @@ -11,13 +14,18 @@ n = l else: n = m + print n l = [1, 2, 3] x = l a, b, c = l d, e, f = [1, 2, 3] +print a, b, c +print d, e, f +print x m = [4, l, 6] if x: n = l else: n = m +print n diff -r 459b1a69fdbb -r 78e02906e7f2 translator.py --- a/translator.py Fri Nov 11 00:03:05 2016 +0100 +++ b/translator.py Fri Nov 11 00:05:34 2016 +0100 @@ -536,6 +536,11 @@ elif isinstance(n, compiler.ast.Return): return self.process_return_node(n) + # Print statements. + + elif isinstance(n, (compiler.ast.Print, compiler.ast.Printnl)): + self.statement(self.process_print_node(n)) + # Invocations. elif isinstance(n, compiler.ast.CallFunc): @@ -914,6 +919,12 @@ if not args[argnum+1]: args[argnum+1] = "__GETDEFAULT(&%s, %d)" % (target_structure, i) + # Test for missing arguments. + + if None in args: + raise TranslateError("Not all arguments supplied.", + self.get_namespace_path(), n) + # Encode the arguments. argstr = "__ARGS(%s)" % ", ".join(args) @@ -1041,15 +1052,11 @@ if n.name in predefined_constants: return PredefinedConstantRef(n.name) - # Convert literal references. + # Convert literal references, operator function names, and print + # function names to references. - elif n.name.startswith("$L"): - ref = self.importer.get_module(self.name).special.get(n.name) - return TrResolvedNameRef(n.name, ref) - - # Convert operator function names to references. - - elif n.name.startswith("$op"): + elif n.name.startswith("$L") or n.name.startswith("$op") or \ + n.name.startswith("$print"): ref = self.importer.get_module(self.name).special.get(n.name) return TrResolvedNameRef(n.name, ref)