blueloveTH 4 месяцев назад
Родитель
Сommit
96505249d6
3 измененных файлов с 21 добавлено и 8 удалено
  1. 5 1
      docs/C-API/introduction.md
  2. 5 2
      include/pocketpy/pocketpy.h
  3. 11 5
      src/interpreter/ceval.c

+ 5 - 1
docs/C-API/introduction.md

@@ -55,4 +55,8 @@ Mark a function that can raise an exception on failure.
 
 ### `PY_RETURN` macro
 
-Mark a function that can store a value in `py_retval()` on success.
+Mark a function that can store a value in `py_retval()` on success.
+
+### `PY_MAYBENULL` macro
+
+Mark a variable or callback function that may be `NULL`.

+ 5 - 2
include/pocketpy/pocketpy.h

@@ -49,6 +49,7 @@ typedef struct c11_sv {
 
 #define PY_RAISE
 #define PY_RETURN
+#define PY_MAYBENULL
 
 /// A generic reference to a python object.
 typedef py_TValue* py_Ref;
@@ -79,7 +80,7 @@ typedef struct py_Callbacks {
     /// Used by `__import__` to load a source module.
     char* (*importfile)(const char*);
     /// Called before `importfile` to lazy-import a C module.
-    py_GlobalRef (*lazyimport)(const char*);
+    PY_MAYBENULL py_GlobalRef (*lazyimport)(const char*);
     /// Used by `print` to output a string.
     void (*print)(const char*);
     /// Flush the output buffer of `print`.
@@ -87,7 +88,9 @@ typedef struct py_Callbacks {
     /// Used by `input` to get a character.
     int (*getchr)();
     /// Used by `gc.collect()` to mark extra objects for garbage collection.
-    void (*gc_mark)(void (*f)(py_Ref val, void* ctx), void* ctx);
+    PY_MAYBENULL void (*gc_mark)(void (*f)(py_Ref val, void* ctx), void* ctx);
+    /// Used by `PRINT_EXPR` bytecode.
+    PY_MAYBENULL bool (*displayhook)(py_Ref val) PY_RAISE;
 } py_Callbacks;
 
 /// A struct contains the application-level callbacks.

+ 11 - 5
src/interpreter/ceval.c

@@ -152,15 +152,21 @@ __NEXT_STEP:
             *THIRD() = tmp;
             DISPATCH();
         }
-        case OP_PRINT_EXPR:
-            if(TOP()->type != tp_NoneType) {
-                bool ok = py_repr(TOP());
+        case OP_PRINT_EXPR: {
+            if(self->callbacks.displayhook) {
+                bool ok = self->callbacks.displayhook(TOP());
                 if(!ok) goto __ERROR;
-                self->callbacks.print(py_tostr(&self->last_retval));
-                self->callbacks.print("\n");
+            } else {
+                if(TOP()->type != tp_NoneType) {
+                    bool ok = py_repr(TOP());
+                    if(!ok) goto __ERROR;
+                    self->callbacks.print(py_tostr(&self->last_retval));
+                    self->callbacks.print("\n");
+                }
             }
             POP();
             DISPATCH();
+        }
         /*****************************************/
         case OP_LOAD_CONST: {
             PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg));