cython-devel
changeset 3049:6c0c2ae56034
implemented 'print >> stream'
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Tue Mar 09 09:29:47 2010 +0100 (23 months ago) |
| parents | 058a70c40bf0 |
| children | a95dff390f68 |
| files | Cython/Compiler/Nodes.py Cython/Compiler/Parsing.py tests/run/print.pyx |
line diff
1.1 --- a/Cython/Compiler/Nodes.py Sat Mar 06 18:14:05 2010 +0100
1.2 +++ b/Cython/Compiler/Nodes.py Tue Mar 09 09:29:47 2010 +0100
1.3 @@ -3447,11 +3447,15 @@
1.4 # print statement
1.5 #
1.6 # arg_tuple TupleNode
1.7 + # stream ExprNode or None (stdout)
1.8 # append_newline boolean
1.9
1.10 - child_attrs = ["arg_tuple"]
1.11 -
1.12 - def analyse_expressions(self, env):
1.13 + child_attrs = ["arg_tuple", "stream"]
1.14 +
1.15 + def analyse_expressions(self, env):
1.16 + if self.stream:
1.17 + self.stream.analyse_expressions(env)
1.18 + self.stream = self.stream.coerce_to_pyobject(env)
1.19 self.arg_tuple.analyse_expressions(env)
1.20 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env)
1.21 env.use_utility_code(printing_utility_code)
1.22 @@ -3462,12 +3466,18 @@
1.23 gil_message = "Python print statement"
1.24
1.25 def generate_execution_code(self, code):
1.26 + if self.stream:
1.27 + self.stream.generate_evaluation_code(code)
1.28 + stream_result = self.stream.py_result()
1.29 + else:
1.30 + stream_result = '0'
1.31 if len(self.arg_tuple.args) == 1 and self.append_newline:
1.32 arg = self.arg_tuple.args[0]
1.33 arg.generate_evaluation_code(code)
1.34
1.35 code.putln(
1.36 - "if (__Pyx_PrintOne(%s) < 0) %s" % (
1.37 + "if (__Pyx_PrintOne(%s, %s) < 0) %s" % (
1.38 + stream_result,
1.39 arg.py_result(),
1.40 code.error_goto(self.pos)))
1.41 arg.generate_disposal_code(code)
1.42 @@ -3475,14 +3485,21 @@
1.43 else:
1.44 self.arg_tuple.generate_evaluation_code(code)
1.45 code.putln(
1.46 - "if (__Pyx_Print(%s, %d) < 0) %s" % (
1.47 + "if (__Pyx_Print(%s, %s, %d) < 0) %s" % (
1.48 + stream_result,
1.49 self.arg_tuple.py_result(),
1.50 self.append_newline,
1.51 code.error_goto(self.pos)))
1.52 self.arg_tuple.generate_disposal_code(code)
1.53 self.arg_tuple.free_temps(code)
1.54
1.55 - def annotate(self, code):
1.56 + if self.stream:
1.57 + self.stream.generate_disposal_code(code)
1.58 + self.stream.free_temps(code)
1.59 +
1.60 + def annotate(self, code):
1.61 + if self.stream:
1.62 + self.stream.annotate(code)
1.63 self.arg_tuple.annotate(code)
1.64
1.65
1.66 @@ -5028,7 +5045,7 @@
1.67
1.68 printing_utility_code = UtilityCode(
1.69 proto = """
1.70 -static int __Pyx_Print(PyObject *, int); /*proto*/
1.71 +static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/
1.72 #if PY_MAJOR_VERSION >= 3
1.73 static PyObject* %s = 0;
1.74 static PyObject* %s = 0;
1.75 @@ -5044,13 +5061,14 @@
1.76 return f;
1.77 }
1.78
1.79 -static int __Pyx_Print(PyObject *arg_tuple, int newline) {
1.80 - PyObject *f;
1.81 +static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) {
1.82 PyObject* v;
1.83 int i;
1.84
1.85 - if (!(f = __Pyx_GetStdout()))
1.86 - return -1;
1.87 + if (!f) {
1.88 + if (!(f = __Pyx_GetStdout()))
1.89 + return -1;
1.90 + }
1.91 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) {
1.92 if (PyFile_SoftSpace(f, 1)) {
1.93 if (PyFile_WriteString(" ", f) < 0)
1.94 @@ -5078,7 +5096,7 @@
1.95
1.96 #else /* Python 3 has a print function */
1.97
1.98 -static int __Pyx_Print(PyObject *arg_tuple, int newline) {
1.99 +static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) {
1.100 PyObject* kwargs = 0;
1.101 PyObject* result = 0;
1.102 PyObject* end_string;
1.103 @@ -5087,27 +5105,43 @@
1.104 if (!%(PRINT_FUNCTION)s)
1.105 return -1;
1.106 }
1.107 + if (stream) {
1.108 + kwargs = PyDict_New();
1.109 + if (unlikely(!kwargs))
1.110 + return -1;
1.111 + if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0))
1.112 + goto bad;
1.113 + }
1.114 + }
1.115 if (!newline) {
1.116 - if (!%(PRINT_KWARGS)s) {
1.117 + if (!kwargs)
1.118 + kwargs = %(PRINT_KWARGS)s;
1.119 + if (!kwargs) {
1.120 %(PRINT_KWARGS)s = PyDict_New();
1.121 - if (!%(PRINT_KWARGS)s)
1.122 + if unlikely((!%(PRINT_KWARGS)s))
1.123 return -1;
1.124 - end_string = PyUnicode_FromStringAndSize(" ", 1);
1.125 - if (!end_string)
1.126 - return -1;
1.127 - if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
1.128 - Py_DECREF(end_string);
1.129 - return -1;
1.130 - }
1.131 + kwargs = %(PRINT_KWARGS)s;
1.132 + }
1.133 + end_string = PyUnicode_FromStringAndSize(" ", 1);
1.134 + if (unlikely(!end_string))
1.135 + goto bad;
1.136 + if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) {
1.137 Py_DECREF(end_string);
1.138 - }
1.139 - kwargs = %(PRINT_KWARGS)s;
1.140 + goto bad;
1.141 + }
1.142 + Py_DECREF(end_string);
1.143 }
1.144 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs);
1.145 + if (unlikely(kwargs) && (kwargs != %(PRINT_FUNCTION)s))
1.146 + Py_DECREF(kwargs);
1.147 if (!result)
1.148 return -1;
1.149 Py_DECREF(result);
1.150 return 0;
1.151 +bad:
1.152 + if (kwargs != %(PRINT_FUNCTION)s)
1.153 + Py_XDECREF(kwargs);
1.154 + return -1;
1.155 }
1.156
1.157 #endif
1.158 @@ -5119,15 +5153,16 @@
1.159
1.160 printing_one_utility_code = UtilityCode(
1.161 proto = """
1.162 -static int __Pyx_PrintOne(PyObject *o); /*proto*/
1.163 +static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/
1.164 """,
1.165 impl = r"""
1.166 #if PY_MAJOR_VERSION < 3
1.167
1.168 -static int __Pyx_PrintOne(PyObject *o) {
1.169 - PyObject *f;
1.170 - if (!(f = __Pyx_GetStdout()))
1.171 - return -1;
1.172 +static int __Pyx_PrintOne(PyObject* f, PyObject *o) {
1.173 + if (!f) {
1.174 + if (!(f = __Pyx_GetStdout()))
1.175 + return -1;
1.176 + }
1.177 if (PyFile_SoftSpace(f, 0)) {
1.178 if (PyFile_WriteString(" ", f) < 0)
1.179 return -1;
1.180 @@ -5139,19 +5174,19 @@
1.181 return 0;
1.182 /* the line below is just to avoid compiler
1.183 * compiler warnings about unused functions */
1.184 - return __Pyx_Print(NULL, 0);
1.185 + return __Pyx_Print(f, NULL, 0);
1.186 }
1.187
1.188 #else /* Python 3 has a print function */
1.189
1.190 -static int __Pyx_PrintOne(PyObject *o) {
1.191 +static int __Pyx_PrintOne(PyObject* stream, PyObject *o) {
1.192 int res;
1.193 PyObject* arg_tuple = PyTuple_New(1);
1.194 if (unlikely(!arg_tuple))
1.195 return -1;
1.196 Py_INCREF(o);
1.197 PyTuple_SET_ITEM(arg_tuple, 0, o);
1.198 - res = __Pyx_Print(arg_tuple, 1);
1.199 + res = __Pyx_Print(stream, arg_tuple, 1);
1.200 Py_DECREF(arg_tuple);
1.201 return res;
1.202 }
2.1 --- a/Cython/Compiler/Parsing.py Sat Mar 06 18:14:05 2010 +0100
2.2 +++ b/Cython/Compiler/Parsing.py Tue Mar 09 09:29:47 2010 +0100
2.3 @@ -929,11 +929,17 @@
2.4 def p_print_statement(s):
2.5 # s.sy == 'print'
2.6 pos = s.position()
2.7 + ends_with_comma = 0
2.8 s.next()
2.9 if s.sy == '>>':
2.10 - s.error("'print >>' not yet implemented")
2.11 + s.next()
2.12 + stream = p_simple_expr(s)
2.13 + if s.sy == ',':
2.14 + s.next()
2.15 + ends_with_comma = s.sy in ('NEWLINE', 'EOF')
2.16 + else:
2.17 + stream = None
2.18 args = []
2.19 - ends_with_comma = 0
2.20 if s.sy not in ('NEWLINE', 'EOF'):
2.21 args.append(p_simple_expr(s))
2.22 while s.sy == ',':
2.23 @@ -944,7 +950,8 @@
2.24 args.append(p_simple_expr(s))
2.25 arg_tuple = ExprNodes.TupleNode(pos, args = args)
2.26 return Nodes.PrintStatNode(pos,
2.27 - arg_tuple = arg_tuple, append_newline = not ends_with_comma)
2.28 + arg_tuple = arg_tuple, stream = stream,
2.29 + append_newline = not ends_with_comma)
2.30
2.31 def p_exec_statement(s):
2.32 # s.sy == 'exec'
3.1 --- a/tests/run/print.pyx Sat Mar 06 18:14:05 2010 +0100
3.2 +++ b/tests/run/print.pyx Tue Mar 09 09:29:47 2010 +0100
3.3 @@ -14,3 +14,29 @@
3.4 print a, b
3.5 print a, b,
3.6 print 42, u"spam"
3.7 +
3.8 +
3.9 +try:
3.10 + from StringIO import StringIO
3.11 +except ImportError:
3.12 + from io import StringIO
3.13 +
3.14 +def s(stream, a, b):
3.15 + """
3.16 + >>> stream = StringIO()
3.17 + >>> s(stream, 1, 'test')
3.18 + >>> print(stream.getvalue())
3.19 + <BLANKLINE>
3.20 + 1
3.21 + 1 test
3.22 + 1 test
3.23 + 1 test 42 spam
3.24 + <BLANKLINE>
3.25 + """
3.26 + print >> stream
3.27 + print >> stream, a
3.28 + print >> stream, a,
3.29 + print >> stream, b
3.30 + print >> stream, a, b
3.31 + print >> stream, a, b,
3.32 + print >> stream, 42, u"spam"
