mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
add py_smartexec
This commit is contained in:
parent
cc94a382a9
commit
b99c3ed220
@ -111,6 +111,21 @@ PK_EXPORT bool py_exec(const char* source,
|
|||||||
/// Evaluate a source string. Equivalent to `py_exec(source, "<string>", EVAL_MODE, module)`.
|
/// Evaluate a source string. Equivalent to `py_exec(source, "<string>", EVAL_MODE, module)`.
|
||||||
PK_EXPORT bool py_eval(const char* source, py_Ref module) PY_RAISE PY_RETURN;
|
PK_EXPORT bool py_eval(const char* source, py_Ref module) PY_RAISE PY_RETURN;
|
||||||
|
|
||||||
|
/// Run a source string with smart interpretation.
|
||||||
|
/// Example:
|
||||||
|
/// `py_newstr(py_r0(), "abc");`
|
||||||
|
/// `py_newint(py_r1(), 123);`
|
||||||
|
/// `py_smartexec("print(_1, _2)", NULL, py_r0(), py_r1());`
|
||||||
|
/// `// "abc 123" will be printed`.
|
||||||
|
PK_EXPORT bool py_smartexec(const char* source, py_Ref module, ...) PY_RAISE PY_RETURN;
|
||||||
|
/// Evaluate a source string with smart interpretation.
|
||||||
|
/// Example:
|
||||||
|
/// `py_newstr(py_r0(), "abc");`
|
||||||
|
/// `py_smarteval("len(_1)", NULL, py_r0());`
|
||||||
|
/// `int res = py_toint(py_retval());`
|
||||||
|
/// `// res will be 3`.
|
||||||
|
PK_EXPORT bool py_smarteval(const char* source, py_Ref module, ...) PY_RAISE PY_RETURN;
|
||||||
|
|
||||||
/// Compile a source string into a code object.
|
/// Compile a source string into a code object.
|
||||||
/// Use python's `exec()` or `eval()` to execute it.
|
/// Use python's `exec()` or `eval()` to execute it.
|
||||||
PK_EXPORT bool py_compile(const char* source,
|
PK_EXPORT bool py_compile(const char* source,
|
||||||
@ -286,6 +301,15 @@ PK_EXPORT py_GlobalRef py_getreg(int i);
|
|||||||
/// Set the i-th register.
|
/// Set the i-th register.
|
||||||
PK_EXPORT void py_setreg(int i, py_Ref val);
|
PK_EXPORT void py_setreg(int i, py_Ref val);
|
||||||
|
|
||||||
|
#define py_r0() py_getreg(0)
|
||||||
|
#define py_r1() py_getreg(1)
|
||||||
|
#define py_r2() py_getreg(2)
|
||||||
|
#define py_r3() py_getreg(3)
|
||||||
|
#define py_r4() py_getreg(4)
|
||||||
|
#define py_r5() py_getreg(5)
|
||||||
|
#define py_r6() py_getreg(6)
|
||||||
|
#define py_r7() py_getreg(7)
|
||||||
|
|
||||||
/// Get variable in the `__main__` module.
|
/// Get variable in the `__main__` module.
|
||||||
PK_EXPORT py_ItemRef py_getglobal(py_Name name);
|
PK_EXPORT py_ItemRef py_getglobal(py_Name name);
|
||||||
/// Set variable in the `__main__` module.
|
/// Set variable in the `__main__` module.
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
#include "pocketpy/common/str.h"
|
||||||
#include "pocketpy/objects/codeobject.h"
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
#include "pocketpy/common/utils.h"
|
#include "pocketpy/common/utils.h"
|
||||||
#include "pocketpy/objects/object.h"
|
#include "pocketpy/objects/object.h"
|
||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
#include "pocketpy/common/_generated.h"
|
#include "pocketpy/common/_generated.h"
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
py_Ref py_getmodule(const char* path) {
|
py_Ref py_getmodule(const char* path) {
|
||||||
@ -523,6 +525,67 @@ static bool builtins_eval(int argc, py_Ref argv) {
|
|||||||
return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
|
return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
pk_smartexec(const char* source, py_Ref module, enum py_CompileMode mode, va_list args) {
|
||||||
|
if(module == NULL) module = &pk_current_vm->main;
|
||||||
|
pk_mappingproxy__namedict(py_pushtmp(), module); // globals
|
||||||
|
py_newdict(py_pushtmp()); // locals
|
||||||
|
bool ok = py_compile(source, "<string>", mode, true);
|
||||||
|
if(!ok) return false;
|
||||||
|
py_push(py_retval());
|
||||||
|
// [globals, locals, code]
|
||||||
|
CodeObject* co = py_touserdata(py_peek(-1));
|
||||||
|
py_StackRef locals = py_peek(-2);
|
||||||
|
int max_index = 0;
|
||||||
|
c11__foreach(Bytecode, &co->codes, bc) {
|
||||||
|
if(bc->op == OP_LOAD_NAME) {
|
||||||
|
c11_sv name = py_name2sv(bc->arg);
|
||||||
|
if(name.data[0] != '_') continue;
|
||||||
|
int index;
|
||||||
|
if(name.size == 1) {
|
||||||
|
index = 1;
|
||||||
|
} else if(name.size == 2 && isdigit(name.data[1])) {
|
||||||
|
index = name.data[1] - '0';
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
max_index = c11__max(max_index, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(max_index == 0) { return ValueError("no placeholder found in the source"); }
|
||||||
|
|
||||||
|
for(int i = 1; i <= max_index; i++) {
|
||||||
|
py_Ref val = va_arg(args, py_Ref);
|
||||||
|
char buf[3];
|
||||||
|
buf[0] = '_';
|
||||||
|
buf[1] = '0' + i;
|
||||||
|
buf[2] = '\0';
|
||||||
|
py_dict_setitem_by_str(locals, buf, val);
|
||||||
|
if(i == 1) {
|
||||||
|
// _ => _1
|
||||||
|
py_dict_setitem_by_str(locals, "_", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pk_exec(co, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool py_smartexec(const char* source, py_Ref module, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, module);
|
||||||
|
bool ok = pk_smartexec(source, module, EXEC_MODE, args);
|
||||||
|
va_end(args);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool py_smarteval(const char* source, py_Ref module, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, module);
|
||||||
|
bool ok = pk_smartexec(source, module, EVAL_MODE, args);
|
||||||
|
va_end(args);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static bool builtins_compile(int argc, py_Ref argv) {
|
static bool builtins_compile(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(3);
|
PY_CHECK_ARGC(3);
|
||||||
for(int i = 0; i < 3; i++) {
|
for(int i = 0; i < 3; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user