Author: Armin Rigo <[email protected]>
Branch: py3.5-fstring-pep498
Changeset: r89697:fa0095403f9d
Date: 2017-01-22 22:48 +0100
http://bitbucket.org/pypy/pypy/changeset/fa0095403f9d/

Log:    bytecode interpreter

diff --git a/lib-python/3/opcode.py b/lib-python/3/opcode.py
--- a/lib-python/3/opcode.py
+++ b/lib-python/3/opcode.py
@@ -214,8 +214,8 @@
 def_op('BUILD_TUPLE_UNPACK', 152)
 def_op('BUILD_SET_UNPACK', 153)
 
-def_op('FORMAT_VALUE', 155)
-def_op('BUILD_STRING', 157)
+def_op('FORMAT_VALUE', 155)   # in CPython 3.6, but available in PyPy from 3.5
+def_op('BUILD_STRING', 157)   # in CPython 3.6, but available in PyPy from 3.5
 
 # pypy modification, experimental bytecode
 def_op('LOOKUP_METHOD', 201)          # Index in name list
diff --git a/pypy/interpreter/astcompiler/assemble.py 
b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -758,6 +758,13 @@
 def _compute_CALL_METHOD(arg):
     return -_num_args(arg) - 1
 
+def _compute_FORMAT_VALUE(arg):
+    #if arg contains some flag: return -1
+    return 0
+
+def _compute_BUILD_STRING(arg):
+    return 1 - arg
+
 
 _stack_effect_computers = {}
 for name, func in globals().items():
diff --git a/pypy/interpreter/astcompiler/astbuilder.py 
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -1286,18 +1286,18 @@
                 else:
                     self.error("f-string: unexpected '}'", atom_node)
                 continue
+            self._f_constant_string(joined_pieces, u[start:p1], atom_node)
             if p1 == len(u):
-                self._f_constant_string(joined_pieces, u[start:], atom_node)
                 break     # no more '{' or '}' left
             pn = p1 + 1
             if pn < len(u) and u[pn] == u'{':    # '{{' => single '{'
-                self._f_constant_string(joined_pieces, u[start:pn], atom_node)
-                start = pn + 1
+                start = pn
+                p1 = u.find(u'{', start + 1)
             else:
                 assert u[p1] == u'{'
                 start = self._f_string_expr(joined_pieces, u, pn, atom_node)
                 assert u[start - 1] == u'}'
-            p1 = u.find(u'{', start)
+                p1 = u.find(u'{', start)
 
     def handle_atom(self, atom_node):
         first_child = atom_node.get_child(0)
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py 
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -12,7 +12,7 @@
     p = pyparse.PythonParser(space)
     info = pyparse.CompileInfo("<test>", mode)
     cst = p.parse_source(expr, info)
-    ast = astbuilder.ast_from_node(space, cst, info)
+    ast = astbuilder.ast_from_node(space, cst, info, recursive_parser=p)
     return codegen.compile_ast(space, ast, info)
 
 def generate_function_code(expr, space):
@@ -1162,6 +1162,9 @@
         """
         yield self.st, source, "f()", 43
 
+    def test_fstring(self):
+        yield self.st, """x = 42; z = f'ab{x}cd'""", 'z', 'ab42cd'
+
 
 class AppTestCompiler:
 
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -434,6 +434,10 @@
                 self.GET_AITER(oparg, next_instr)
             elif opcode == opcodedesc.GET_ANEXT.index:
                 self.GET_ANEXT(oparg, next_instr)
+            elif opcode == opcodedesc.FORMAT_VALUE.index:
+                self.FORMAT_VALUE(oparg, next_instr)
+            elif opcode == opcodedesc.BUILD_STRING.index:
+                self.BUILD_STRING(oparg, next_instr)
             else:
                 self.MISSING_OPCODE(oparg, next_instr)
 
@@ -1607,6 +1611,23 @@
                         "from __anext__: %T", w_next_iter)
         self.pushvalue(w_awaitable)
 
+    def FORMAT_VALUE(self, oparg, next_instr):
+        space = self.space
+        w_value = self.popvalue()
+        w_res = space.format(w_value, space.newunicode(u''))
+        self.pushvalue(w_res)
+
+    @jit.unroll_safe
+    def BUILD_STRING(self, itemcount, next_instr):
+        space = self.space
+        lst = []
+        for i in range(itemcount-1, -1, -1):
+            w_item = self.peekvalue(i)
+            lst.append(space.unicode_w(w_item))
+        self.dropvalues(itemcount)
+        w_res = space.newunicode(u''.join(lst))
+        self.pushvalue(w_res)
+
 ### ____________________________________________________________ ###
 
 class ExitFrame(Exception):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to