mirror of
https://github.com/pocketpy/pocketpy
synced 2026-08-05 05:37:10 +08:00
Compare commits
12 Commits
e144785436
...
b25cc37123
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b25cc37123 | ||
|
|
2161532677 | ||
|
|
048df25e6f | ||
|
|
beb1557d00 | ||
|
|
4e2b40db2d | ||
|
|
7fd7e2db15 | ||
|
|
005550e92a | ||
|
|
f2b6d90a72 | ||
|
|
2ed21e8814 | ||
|
|
08fce73bbb | ||
|
|
4fc4d665ec | ||
|
|
4816c4471b |
@ -251,7 +251,7 @@
|
||||
* types in @ref docs/protocol.md for more information.
|
||||
*/
|
||||
#ifndef MPACK_EXTENSIONS
|
||||
#define MPACK_EXTENSIONS 0
|
||||
#define MPACK_EXTENSIONS 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
20
3rd/msgpack/include/mpack1.h
Normal file
20
3rd/msgpack/include/mpack1.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "mpack.h"
|
||||
#include "pocketpy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef bool (*is_mpack_ext_t)(py_Type type);
|
||||
typedef bool (*py_to_mpack_ext_t)(py_Ref object, mpack_writer_t* writer);
|
||||
typedef bool (*mpack_to_py_ext_t)(py_StackRef tmp, mpack_node_t node);
|
||||
|
||||
void mpack_config_exttype_callbacks(is_mpack_ext_t is_ext,
|
||||
py_to_mpack_ext_t to_mpack,
|
||||
mpack_to_py_ext_t to_py);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1,8 +1,22 @@
|
||||
#include "pocketpy.h"
|
||||
|
||||
#include "mpack.h"
|
||||
#include "mpack1.h"
|
||||
#include <assert.h>
|
||||
|
||||
_Static_assert(MPACK_EXTENSIONS == 1, "You should change MPACK_EXTENSIONS in mpack.h to 1");
|
||||
|
||||
static is_mpack_ext_t is_mpack_ext;
|
||||
static py_to_mpack_ext_t py_to_mpack_ext;
|
||||
static mpack_to_py_ext_t mpack_to_py_ext;
|
||||
|
||||
void mpack_config_exttype_callbacks(is_mpack_ext_t is_ext,
|
||||
py_to_mpack_ext_t to_mpack,
|
||||
mpack_to_py_ext_t to_py) {
|
||||
is_mpack_ext = is_ext;
|
||||
py_to_mpack_ext = to_mpack;
|
||||
mpack_to_py_ext = to_py;
|
||||
}
|
||||
|
||||
static bool mpack_to_py(mpack_node_t node) {
|
||||
py_StackRef tmp = py_pushtmp();
|
||||
|
||||
@ -69,6 +83,14 @@ static bool mpack_to_py(mpack_node_t node) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case mpack_type_ext: {
|
||||
if(!mpack_to_py_ext) {
|
||||
return RuntimeError("msgpack: mpack_to_py_ext is not set, cannot handle ext type");
|
||||
}
|
||||
if(!mpack_to_py_ext(tmp, node)) return false;
|
||||
break;
|
||||
}
|
||||
default: return ValueError("msgpack: invalid node type");
|
||||
}
|
||||
return true;
|
||||
@ -111,9 +133,7 @@ static bool mpack_write_dict_kv(py_Ref k, py_Ref v, void* ctx) {
|
||||
} else {
|
||||
return TypeError("msgpack: key must be string or integer");
|
||||
}
|
||||
bool ok = py_to_mpack(v, writer);
|
||||
if(!ok) mpack_write_nil(writer);
|
||||
return ok;
|
||||
return py_to_mpack(v, writer);
|
||||
}
|
||||
|
||||
static bool py_to_mpack(py_Ref object, mpack_writer_t* writer) {
|
||||
@ -154,7 +174,15 @@ static bool py_to_mpack(py_Ref object, mpack_writer_t* writer) {
|
||||
if(!ok) return false;
|
||||
break;
|
||||
}
|
||||
default: return TypeError("msgpack: unsupported type '%t'", object->type);
|
||||
default: {
|
||||
if(is_mpack_ext && is_mpack_ext(object->type)) {
|
||||
assert(py_to_mpack_ext != NULL);
|
||||
return py_to_mpack_ext(object, writer);
|
||||
break;
|
||||
}
|
||||
mpack_write_nil(writer);
|
||||
return TypeError("msgpack: unsupported type '%t'", object->type);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
14
README.md
14
README.md
@ -195,6 +195,7 @@ And these are the results of the primes benchmark on Intel i5-12400F, WSL (Ubunt
|
||||
|
||||
| | Description |
|
||||
|-----------------------------------------------------------------|--------------------------------------------------------------------------|
|
||||
| [Tesselmax.EM](https://fdtd.io) | Distributed electromagnetic field simulator for silicon photonics and RF/interconnect design. |
|
||||
| [godot-pocketpy](https://github.com/pocketpy/godot-pocketpy) | Godot extension for using pocketpy in Godot Engine. |
|
||||
| [TIC-80](https://github.com/nesbox/TIC-80) | TIC-80 is a fantasy computer for making, playing and sharing tiny games. |
|
||||
| [py-js](https://github.com/shakfu/py-js) | Python3 externals for Max / MSP. |
|
||||
@ -215,7 +216,7 @@ All kinds of contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTI
|
||||
- any suggestions
|
||||
- any questions
|
||||
|
||||
If you find pkpy useful, consider star this repository (●'◡'●)
|
||||
If you find pkpy useful, consider star this repository.
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
@ -226,6 +227,17 @@ You can sponsor this project via these ways.
|
||||
|
||||
Your sponsorship will help us develop pkpy continuously.
|
||||
|
||||
## Premium supporter
|
||||
|
||||
Special thanks to our premium supporter, Tesselmax, for sponsoring the development of pocketpy.
|
||||
|
||||
Tesselmax builds Tesselmax.EM, a distributed electromagnetic field simulator for silicon
|
||||
photonics and RF/interconnect design (FDTD, FDFD, and mode solving across GPU clusters).
|
||||
Tesselmax embeds pocketpy as the scripting engine in our simulation console, so user scripts drive
|
||||
geometry, materials, sources, and post-processing.
|
||||
|
||||
Website: [https://fdtd.io](https://fdtd.io)
|
||||
|
||||
## Reference
|
||||
|
||||
+ [cpython](https://github.com/python/cpython)
|
||||
|
||||
@ -51,7 +51,7 @@ On Windows platform, only MSVC compiler is officially supported.
|
||||
|
||||
## Star the repo
|
||||
|
||||
If you find pkpy useful, consider [star this repository](https://github.com/blueloveth/pocketpy) (●'◡'●)
|
||||
If you find pkpy useful, consider [star this repository](https://github.com/blueloveth/pocketpy).
|
||||
|
||||
## Sponsor this project
|
||||
|
||||
@ -62,6 +62,17 @@ You can sponsor this project via these ways.
|
||||
|
||||
Your sponsorship will help us develop pkpy continuously.
|
||||
|
||||
## Premium supporter
|
||||
|
||||
Special thanks to our premium supporter, Tesselmax, for sponsoring the development of pocketpy.
|
||||
|
||||
Tesselmax builds Tesselmax.EM, a distributed electromagnetic field simulator for silicon
|
||||
photonics and RF/interconnect design (FDTD, FDFD, and mode solving across GPU clusters).
|
||||
Tesselmax embeds pocketpy as the scripting engine in our simulation console, so user scripts drive
|
||||
geometry, materials, sources, and post-processing.
|
||||
|
||||
Website: [https://fdtd.io](https://fdtd.io)
|
||||
|
||||
## Upgrade to v2.0
|
||||
|
||||
pkpy v2.0 is a C11 project instead of C++17. All your existing code for v1.x won't work anymore.
|
||||
|
||||
@ -3,7 +3,7 @@ output: .retype
|
||||
url: https://pocketpy.dev
|
||||
branding:
|
||||
title: pocketpy
|
||||
label: v2.1.9
|
||||
label: v2.2.0
|
||||
logo: "./static/logo.png"
|
||||
favicon: "./static/logo.png"
|
||||
meta:
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
// clang-format off
|
||||
|
||||
#define PK_VERSION "2.1.9"
|
||||
#define PK_VERSION "2.2.0"
|
||||
#define PK_VERSION_MAJOR 2
|
||||
#define PK_VERSION_MINOR 1
|
||||
#define PK_VERSION_PATCH 9
|
||||
#define PK_VERSION_MINOR 2
|
||||
#define PK_VERSION_PATCH 0
|
||||
|
||||
/*************** feature settings ***************/
|
||||
#ifndef PK_ENABLE_OS // can be overridden by cmake
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
#include "pocketpy/export.h"
|
||||
#include "pocketpy/vmath.h"
|
||||
|
||||
// for sandbox branch
|
||||
#include "pocketpy/sandbox.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
25
include/pocketpy/sandbox.h
Normal file
25
include/pocketpy/sandbox.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/export.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
// Fine-grained capabilities of the VM for sandboxing.
|
||||
typedef struct py_Capabilities {
|
||||
// FileIO
|
||||
bool (*file_open)(const char* path, const char* mode);
|
||||
// os
|
||||
bool (*os_chdir)(const char* path);
|
||||
bool (*os_getcwd)();
|
||||
bool (*os_system)(const char* command);
|
||||
bool (*os_remove)(const char* path);
|
||||
// stdc
|
||||
bool stdc_write; // memset, write_bytes, ...
|
||||
bool stdc_read; // memcmp, read_bytes, ...
|
||||
bool stdc_malloc; // malloc
|
||||
bool stdc_free; // free
|
||||
} py_Capabilities;
|
||||
|
||||
/// Setup the capabilities for the current VM.
|
||||
PK_API py_Capabilities* py_capabilities();
|
||||
/// Raise a `KeyboardInterrupt` to interrupt the current execution.
|
||||
PK_API void py_interrupt();
|
||||
@ -27,6 +27,7 @@ OPCODE(LOAD_NAME)
|
||||
OPCODE(LOAD_NONLOCAL)
|
||||
OPCODE(LOAD_GLOBAL)
|
||||
OPCODE(LOAD_ATTR)
|
||||
OPCODE(LOAD_SELF_ATTR)
|
||||
OPCODE(LOAD_CLASS_GLOBAL)
|
||||
OPCODE(LOAD_METHOD)
|
||||
OPCODE(LOAD_SUBSCR)
|
||||
@ -35,6 +36,7 @@ OPCODE(STORE_FAST)
|
||||
OPCODE(STORE_NAME)
|
||||
OPCODE(STORE_GLOBAL)
|
||||
OPCODE(STORE_ATTR)
|
||||
OPCODE(STORE_SELF_ATTR)
|
||||
OPCODE(STORE_SUBSCR)
|
||||
|
||||
OPCODE(DELETE_FAST)
|
||||
|
||||
@ -35,7 +35,7 @@ A new Flutter FFI plugin project.
|
||||
|
||||
s.prepare_command = <<-CMD
|
||||
rm -rf pocketpy
|
||||
git clone --branch v2.1.9 --depth 1 https://github.com/pocketpy/pocketpy.git
|
||||
git clone --branch v2.2.0 --depth 1 https://github.com/pocketpy/pocketpy.git
|
||||
cd pocketpy
|
||||
git submodule update --init --recursive --depth 1
|
||||
bash build_ios_libs.sh
|
||||
|
||||
@ -32,7 +32,7 @@ A new Flutter FFI plugin project.
|
||||
|
||||
s.prepare_command = <<-CMD
|
||||
rm -rf pocketpy
|
||||
git clone --branch v2.1.9 --depth 1 https://github.com/pocketpy/pocketpy.git
|
||||
git clone --branch v2.2.0 --depth 1 https://github.com/pocketpy/pocketpy.git
|
||||
cd pocketpy
|
||||
git submodule update --init --recursive --depth 1
|
||||
bash build_darwin_libs.sh
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
name: pocketpy
|
||||
description: A lightweight Python interpreter for game engines. It supports Android/iOS/Windows/Linux/MacOS.
|
||||
version: 2.1.9
|
||||
version: 2.2.0
|
||||
homepage: https://pocketpy.dev
|
||||
repository: https://github.com/pocketpy/pocketpy
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ set(PK_BUILD_SHARED_LIB ON CACHE BOOL "" FORCE)
|
||||
FetchContent_Declare(
|
||||
pocketpy
|
||||
GIT_REPOSITORY https://github.com/pocketpy/pocketpy.git
|
||||
GIT_TAG v2.1.9
|
||||
GIT_TAG v2.2.0
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(pocketpy)
|
||||
|
||||
@ -384,7 +384,7 @@ static bool int__abs__(int argc, py_Ref argv) {
|
||||
static bool float__abs__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_f64 val = py_tofloat(&argv[0]);
|
||||
py_newfloat(py_retval(), val < 0 ? -val : val);
|
||||
py_newfloat(py_retval(), dmath_fabs(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -447,6 +447,12 @@ static bool str_zfill(int argc, py_Ref argv) {
|
||||
}
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
// a leading sign is kept in front; the padding goes after it
|
||||
if(self.size > 0 && (self.data[0] == '+' || self.data[0] == '-')) {
|
||||
c11_sbuf__write_char(&buf, self.data[0]);
|
||||
self.data++;
|
||||
self.size--;
|
||||
}
|
||||
for(int i = 0; i < delta; i++) {
|
||||
c11_sbuf__write_char(&buf, '0');
|
||||
}
|
||||
|
||||
@ -701,8 +701,11 @@ double dmath_copysign(double x, double y) {
|
||||
return ux.f;
|
||||
}
|
||||
|
||||
// https://github.com/kraj/musl/blob/kraj/master/src/math/fabs.c
|
||||
double dmath_fabs(double x) {
|
||||
return (x < 0) ? -x : x;
|
||||
union Float64Bits u = { .f = x };
|
||||
u.i &= -1ULL/2;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
double dmath_ceil(double x) {
|
||||
|
||||
@ -60,6 +60,7 @@ typedef struct Expr {
|
||||
typedef struct Ctx {
|
||||
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
|
||||
FuncDecl* func; // optional, weakref
|
||||
py_Name n_self;
|
||||
int level;
|
||||
int curr_iblock;
|
||||
bool is_compiling_class;
|
||||
@ -70,7 +71,7 @@ typedef struct Ctx {
|
||||
|
||||
typedef struct Expr Expr;
|
||||
|
||||
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level);
|
||||
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level, py_Name n_self);
|
||||
static void Ctx__dtor(Ctx* self);
|
||||
static int Ctx__prepare_loop_divert(Ctx* self, int line, bool is_break);
|
||||
static int Ctx__enter_block(Ctx* self, CodeBlockType type);
|
||||
@ -732,9 +733,9 @@ static void NamedExpr__dtor(Expr* self_) {
|
||||
|
||||
static void NamedExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
NamedExpr* self = (NamedExpr*)self_;
|
||||
vtemit_(self->rhs, ctx); // [value]
|
||||
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [value, value]
|
||||
vtemit_store((Expr*)self->name, ctx); // [value]
|
||||
vtemit_(self->rhs, ctx); // [value]
|
||||
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [value, value]
|
||||
vtemit_store((Expr*)self->name, ctx); // [value]
|
||||
}
|
||||
|
||||
static NamedExpr* NamedExpr__new(int line, NameExpr* name, Expr* rhs) {
|
||||
@ -997,8 +998,23 @@ void AttribExpr__dtor(Expr* self_) {
|
||||
vtdelete(self->child);
|
||||
}
|
||||
|
||||
static bool is_self_xxx(Expr* child, Ctx* ctx) {
|
||||
if(child->vt->is_name) {
|
||||
NameExpr* ne = (NameExpr*)child;
|
||||
if(ne->scope == NAME_LOCAL && ne->name == ctx->n_self) {
|
||||
int index = c11_smallmap_n2d__get(&ctx->co->varnames_inv, ne->name, -1);
|
||||
if(index == 0) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AttribExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||
AttribExpr* self = (AttribExpr*)self_;
|
||||
if(is_self_xxx(self->child, ctx)) {
|
||||
Ctx__emit_(ctx, OP_LOAD_SELF_ATTR, Ctx__add_name(ctx, self->name), self->line);
|
||||
return;
|
||||
}
|
||||
vtemit_(self->child, ctx);
|
||||
Ctx__emit_(ctx, OP_LOAD_ATTR, Ctx__add_name(ctx, self->name), self->line);
|
||||
}
|
||||
@ -1012,6 +1028,10 @@ bool AttribExpr__emit_del(Expr* self_, Ctx* ctx) {
|
||||
|
||||
bool AttribExpr__emit_store(Expr* self_, Ctx* ctx) {
|
||||
AttribExpr* self = (AttribExpr*)self_;
|
||||
if(is_self_xxx(self->child, ctx)) {
|
||||
Ctx__emit_(ctx, OP_STORE_SELF_ATTR, Ctx__add_name(ctx, self->name), self->line);
|
||||
return true;
|
||||
}
|
||||
vtemit_(self->child, ctx);
|
||||
Ctx__emit_(ctx, OP_STORE_ATTR, Ctx__add_name(ctx, self->name), self->line);
|
||||
return true;
|
||||
@ -1127,9 +1147,10 @@ CallExpr* CallExpr__new(int line, Expr* callable) {
|
||||
}
|
||||
|
||||
/* context.c */
|
||||
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) {
|
||||
static void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level, py_Name n_self) {
|
||||
self->co = co;
|
||||
self->func = func;
|
||||
self->n_self = n_self;
|
||||
self->level = level;
|
||||
self->curr_iblock = 0;
|
||||
self->is_compiling_class = false;
|
||||
@ -1361,6 +1382,7 @@ typedef struct Compiler {
|
||||
|
||||
Token* tokens;
|
||||
int tokens_length;
|
||||
py_Name n_self;
|
||||
|
||||
int i; // current token index
|
||||
c11_vector /*T=CodeEmitContext*/ contexts;
|
||||
@ -1370,6 +1392,7 @@ static void Compiler__ctor(Compiler* self, SourceData_ src, Token* tokens, int t
|
||||
self->src = src;
|
||||
self->tokens = tokens;
|
||||
self->tokens_length = tokens_length;
|
||||
self->n_self = py_name("self");
|
||||
self->i = 0;
|
||||
c11_vector__ctor(&self->contexts, sizeof(Ctx));
|
||||
}
|
||||
@ -1540,7 +1563,7 @@ static Error* EXPR_VARS(Compiler* self) {
|
||||
static void push_global_context(Compiler* self, CodeObject* co) {
|
||||
co->start_line = self->i == 0 ? 1 : prev()->line;
|
||||
Ctx* ctx = c11_vector__emplace(&self->contexts);
|
||||
Ctx__ctor(ctx, co, NULL, self->contexts.length);
|
||||
Ctx__ctor(ctx, co, NULL, self->contexts.length, self->n_self);
|
||||
}
|
||||
|
||||
static Error* pop_context(Compiler* self) {
|
||||
@ -1715,9 +1738,7 @@ static Error* exprWalrus(Compiler* self) {
|
||||
int line = prev()->line;
|
||||
// LHS is on the stack; verify it's a simple name
|
||||
Expr* lhs = Ctx__s_top(ctx());
|
||||
if(!lhs->vt->is_name) {
|
||||
return SyntaxError(self, "':=' target must be a simple name");
|
||||
}
|
||||
if(!lhs->vt->is_name) { return SyntaxError(self, "':=' target must be a simple name"); }
|
||||
check(parse_expression(self, PREC_NAMED_EXPR + 1, false));
|
||||
Expr* rhs = Ctx__s_popx(ctx());
|
||||
NameExpr* name = (NameExpr*)Ctx__s_popx(ctx());
|
||||
@ -1940,7 +1961,7 @@ static Error* exprCall(Compiler* self) {
|
||||
Error* err;
|
||||
Expr* callable = Ctx__s_popx(ctx());
|
||||
int line = prev()->line;
|
||||
|
||||
|
||||
CallExpr* e = CallExpr__new(line, callable);
|
||||
Ctx__s_push(ctx(), (Expr*)e); // push onto the stack in advance
|
||||
do {
|
||||
@ -2289,7 +2310,7 @@ static FuncDecl_ push_f_context(Compiler* self, c11_sv name, int* out_index) {
|
||||
*out_index = top_ctx->co->func_decls.length - 1;
|
||||
// push new context
|
||||
top_ctx = c11_vector__emplace(&self->contexts);
|
||||
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.length);
|
||||
Ctx__ctor(top_ctx, &decl->code, decl, self->contexts.length, self->n_self);
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
@ -325,6 +325,23 @@ __NEXT_STEP:
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_LOAD_SELF_ATTR: {
|
||||
assert(!frame->is_locals_special);
|
||||
py_Ref val = &frame->locals[0];
|
||||
if(!py_isnil(val)) {
|
||||
// LOAD_ATTR
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(py_getattr(val, name)) {
|
||||
PUSH(py_retval());
|
||||
} else {
|
||||
goto __ERROR;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
|
||||
UnboundLocalError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_LOAD_CLASS_GLOBAL: {
|
||||
assert(self->curr_class);
|
||||
py_Name name = co_names[byte.arg];
|
||||
@ -427,6 +444,20 @@ __NEXT_STEP:
|
||||
STACK_SHRINK(2);
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_SELF_ATTR: {
|
||||
assert(!frame->is_locals_special);
|
||||
py_Ref val = &frame->locals[0];
|
||||
if(!py_isnil(val)) {
|
||||
// [val, a] -> a.b = val
|
||||
py_Name name = co_names[byte.arg];
|
||||
if(!py_setattr(val, name, TOP())) goto __ERROR;
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
|
||||
UnboundLocalError(name);
|
||||
goto __ERROR;
|
||||
}
|
||||
case OP_STORE_SUBSCR: {
|
||||
// [val, a, b] -> a[b] = val
|
||||
py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
|
||||
|
||||
@ -77,8 +77,10 @@ static bool disassemble(CodeObject* co) {
|
||||
case OP_LOAD_NONLOCAL:
|
||||
case OP_STORE_GLOBAL:
|
||||
case OP_LOAD_ATTR:
|
||||
case OP_LOAD_SELF_ATTR:
|
||||
case OP_LOAD_METHOD:
|
||||
case OP_STORE_ATTR:
|
||||
case OP_STORE_SELF_ATTR:
|
||||
case OP_DELETE_ATTR:
|
||||
case OP_BEGIN_CLASS:
|
||||
case OP_DELETE_GLOBAL:
|
||||
|
||||
@ -5,8 +5,8 @@
|
||||
// Magic number for CodeObject serialization: "CO" = 0x434F
|
||||
#define CODEOBJECT_MAGIC 0x434F
|
||||
#define CODEOBJECT_VER_MAJOR 1
|
||||
#define CODEOBJECT_VER_MINOR 0
|
||||
#define CODEOBJECT_VER_MINOR_MIN 0
|
||||
#define CODEOBJECT_VER_MINOR 1
|
||||
#define CODEOBJECT_VER_MINOR_MIN 1
|
||||
|
||||
// Forward declarations
|
||||
static void FuncDecl__serialize(c11_serializer* s,
|
||||
|
||||
@ -97,6 +97,9 @@ assert 3.4e+3 == 3400.0
|
||||
assert abs(1.0) == 1.0
|
||||
assert abs(-1.0) == 1.0
|
||||
assert abs(0.0) == 0.0
|
||||
# abs(-0.0) is 0.0, not -0.0. `==` cannot tell them apart, so check the sign.
|
||||
assert str(abs(-0.0)) == '0.0'
|
||||
assert str(abs(0.0)) == '0.0'
|
||||
|
||||
# import math
|
||||
# assert math.isnan(0/0)
|
||||
|
||||
@ -112,6 +112,9 @@ assert s2.join( seq ) == "runoob"
|
||||
|
||||
assert 'x'.zfill(5) == '0000x'
|
||||
assert '568'.zfill(1) == '568'
|
||||
assert '-5'.zfill(4) == '-005'
|
||||
assert '+5'.zfill(4) == '+005'
|
||||
assert '-'.zfill(3) == '-00'
|
||||
|
||||
num = 6
|
||||
assert str(num) == '6'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user