瀏覽代碼

fix https://github.com/blueloveTH/pocketpy/issues/130

blueloveTH 2 年之前
父節點
當前提交
85efbd0b1d
共有 5 個文件被更改,包括 44 次插入2 次删除
  1. 1 1
      include/pocketpy/common.h
  2. 1 0
      include/pocketpy/opcodes.h
  3. 3 0
      src/ceval.cpp
  4. 11 0
      src/expr.cpp
  5. 28 1
      tests/25_rawstring.py

+ 1 - 1
include/pocketpy/common.h

@@ -21,7 +21,7 @@
 #include <type_traits>
 #include <random>
 
-#define PK_VERSION				"1.1.8"
+#define PK_VERSION				"1.1.9"
 
 #include "config.h"
 #include "export.h"

+ 1 - 0
include/pocketpy/opcodes.h

@@ -89,6 +89,7 @@ OPCODE(LOOP_BREAK)
 OPCODE(GOTO)
 /**************************/
 OPCODE(EVAL)
+OPCODE(REPR)
 OPCODE(CALL)
 OPCODE(CALL_TP)
 OPCODE(RETURN_VALUE)

+ 3 - 0
src/ceval.cpp

@@ -498,6 +498,9 @@ __NEXT_STEP:;
         _0 = builtins->attr(pk_id_eval);
         TOP() = call(_0, TOP());
         DISPATCH();
+    TARGET(REPR)
+        TOP() = py_repr(TOP());
+        DISPATCH();
     TARGET(CALL)
         _0 = vectorcall(
             byte.arg & 0xFFFF,          // ARGC

+ 11 - 0
src/expr.cpp

@@ -351,6 +351,14 @@ namespace pkpy{
 
 
     void FStringExpr::_load_simple_expr(CodeEmitContext* ctx, Str expr){
+        bool repr = false;
+        if(expr.size>=2 && expr.end()[-2]=='!'){
+            switch(expr.end()[-1]){
+                case 'r': repr = true; expr = expr.substr(0, expr.size-2); break;
+                case 's': repr = false; expr = expr.substr(0, expr.size-2); break;
+                default: break;     // nothing happens
+            }
+        }
         // name or name.name
         std::regex pattern(R"(^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*){0,1}$)");
         if(std::regex_match(expr.str(), pattern)){
@@ -368,6 +376,9 @@ namespace pkpy{
             ctx->emit(OP_LOAD_CONST, index, line);
             ctx->emit(OP_EVAL, BC_NOARG, line);
         }
+        if(repr){
+            ctx->emit(OP_REPR, BC_NOARG, line);
+        }
     }
 
     void FStringExpr::emit(CodeEmitContext* ctx){

+ 28 - 1
tests/25_rawstring.py

@@ -71,4 +71,31 @@ assert f'{"test":*>10}' == '******test'
 assert f'{"test":*<10}' == 'test******'
 assert f'{"test":*^10}' == '***test***'
 assert f'{"test":*^11}' == '***test****'
-assert f'{12345:0>10}' == '0000012345'
+assert f'{12345:0>10}' == '0000012345'
+
+assert f'{obj.b!r:10}' == "'123'     "
+assert f'{obj.b!r:*>10}' == "*****'123'"
+assert f'{obj.b!r:1}' == "'123'"
+assert f'{obj.b!r:10s}' == "'123'     "
+
+assert f'{"text"!r:10}' == "'text'    "
+assert f'{"test"!r:*>10}' == "****'test'"
+assert f'{"test"!r:*<10}' == "'test'****"
+assert f'{"test"!r:*^10}' == "**'test'**"
+assert f'{"test"!r:*^11}' == "**'test'***"
+assert f'{12345!r:0>10}' == "0000012345"
+
+class A:
+    def __repr__(self):
+        return 'A()'
+    def __str__(self):
+        return 'A'
+
+a = A()
+assert f'{a!r:10}' == 'A()       '
+assert f'{a!s:10}' == 'A         '
+assert f'{a:10}' == 'A         '
+
+assert f'{A()!r:10}' == 'A()       '
+assert f'{A()!s:10}' == 'A         '
+assert f'{A():10}' == 'A         '