mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
Merge branch 'main' into updated-c-binding-test
This commit is contained in:
commit
4fce05b611
2
.gitignore
vendored
2
.gitignore
vendored
@ -21,9 +21,9 @@ plugins/macos/pocketpy/pocketpy.*
|
|||||||
src/_generated.h
|
src/_generated.h
|
||||||
profile.sh
|
profile.sh
|
||||||
test
|
test
|
||||||
tmp.rar
|
|
||||||
src/httplib.h
|
src/httplib.h
|
||||||
pocketpy.exe
|
pocketpy.exe
|
||||||
main.obj
|
main.obj
|
||||||
pocketpy.exp
|
pocketpy.exp
|
||||||
pocketpy.lib
|
pocketpy.lib
|
||||||
|
APPS
|
@ -42,4 +42,4 @@ The easiest way to test a feature is to [try it on your browser](https://pocketp
|
|||||||
6. `__ne__` is not required. Define `__eq__` is enough.
|
6. `__ne__` is not required. Define `__eq__` is enough.
|
||||||
7. Raw string cannot have boundary quotes in it, even escaped. See [#55](https://github.com/blueloveTH/pocketpy/issues/55).
|
7. Raw string cannot have boundary quotes in it, even escaped. See [#55](https://github.com/blueloveTH/pocketpy/issues/55).
|
||||||
8. In a starred unpacked assignment, e.g. `a, b, *c = x`, the starred variable can only be presented in the last position. `a, *b, c = x` is not supported.
|
8. In a starred unpacked assignment, e.g. `a, b, *c = x`, the starred variable can only be presented in the last position. `a, *b, c = x` is not supported.
|
||||||
9. `a < b < c` does not work as you expected. Use `a < b and b < c` instead.
|
9. `a < b < c` does not work as you expected. Use `a < b and b < c` instead. **(available in main branch now)**
|
@ -104,7 +104,8 @@ def sorted(iterable, reverse=False, key=None):
|
|||||||
return a
|
return a
|
||||||
|
|
||||||
##### str #####
|
##### str #####
|
||||||
def __f(self, sep):
|
def __f(self, sep=None):
|
||||||
|
sep = sep or ' '
|
||||||
if sep == "":
|
if sep == "":
|
||||||
return list(self)
|
return list(self)
|
||||||
res = []
|
res = []
|
||||||
@ -130,6 +131,22 @@ def __f(self, *args):
|
|||||||
return self
|
return self
|
||||||
str.format = __f
|
str.format = __f
|
||||||
|
|
||||||
|
def __f(self, chars=None):
|
||||||
|
chars = chars or ' \t\n\r'
|
||||||
|
i = 0
|
||||||
|
while i < len(self) and self[i] in chars:
|
||||||
|
++i
|
||||||
|
return self[i:]
|
||||||
|
str.lstrip = __f
|
||||||
|
|
||||||
|
def __f(self, chars=None):
|
||||||
|
chars = chars or ' \t\n\r'
|
||||||
|
j = len(self) - 1
|
||||||
|
while j >= 0 and self[j] in chars:
|
||||||
|
--j
|
||||||
|
return self[:j+1]
|
||||||
|
str.rstrip = __f
|
||||||
|
|
||||||
def __f(self, chars=None):
|
def __f(self, chars=None):
|
||||||
chars = chars or ' \t\n\r'
|
chars = chars or ' \t\n\r'
|
||||||
i = 0
|
i = 0
|
||||||
@ -169,8 +186,37 @@ def __f(self, reverse=False, key=None):
|
|||||||
self.reverse()
|
self.reverse()
|
||||||
list.sort = __f
|
list.sort = __f
|
||||||
|
|
||||||
def staticmethod(f):
|
def __f(self, other):
|
||||||
return f # no effect
|
for i, j in zip(self, other):
|
||||||
|
if i != j:
|
||||||
|
return i < j
|
||||||
|
return len(self) < len(other)
|
||||||
|
tuple.__lt__ = __f
|
||||||
|
list.__lt__ = __f
|
||||||
|
|
||||||
|
def __f(self, other):
|
||||||
|
for i, j in zip(self, other):
|
||||||
|
if i != j:
|
||||||
|
return i > j
|
||||||
|
return len(self) > len(other)
|
||||||
|
tuple.__gt__ = __f
|
||||||
|
list.__gt__ = __f
|
||||||
|
|
||||||
|
def __f(self, other):
|
||||||
|
for i, j in zip(self, other):
|
||||||
|
if i != j:
|
||||||
|
return i <= j
|
||||||
|
return len(self) <= len(other)
|
||||||
|
tuple.__le__ = __f
|
||||||
|
list.__le__ = __f
|
||||||
|
|
||||||
|
def __f(self, other):
|
||||||
|
for i, j in zip(self, other):
|
||||||
|
if i != j:
|
||||||
|
return i >= j
|
||||||
|
return len(self) >= len(other)
|
||||||
|
tuple.__ge__ = __f
|
||||||
|
list.__ge__ = __f
|
||||||
|
|
||||||
type.__repr__ = lambda self: "<class '" + self.__name__ + "'>"
|
type.__repr__ = lambda self: "<class '" + self.__name__ + "'>"
|
||||||
|
|
||||||
|
@ -81,3 +81,39 @@ def Counter(iterable):
|
|||||||
else:
|
else:
|
||||||
a[x] = 1
|
a[x] = 1
|
||||||
return a
|
return a
|
||||||
|
|
||||||
|
class defaultdict:
|
||||||
|
def __init__(self, default_factory) -> None:
|
||||||
|
self.default_factory = default_factory
|
||||||
|
self._a = {}
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if key not in self._a:
|
||||||
|
self._a[key] = self.default_factory()
|
||||||
|
return self._a[key]
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self._a[key] = value
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"defaultdict({self.default_factory}, {self._a})"
|
||||||
|
|
||||||
|
def __eq__(self, __o: object) -> bool:
|
||||||
|
if not isinstance(__o, defaultdict):
|
||||||
|
return False
|
||||||
|
if self.default_factory != __o.default_factory:
|
||||||
|
return False
|
||||||
|
return self._a == __o._a
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self._a)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self._a.keys()
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return self._a.values()
|
||||||
|
|
||||||
|
def items(self):
|
||||||
|
return self._a.items()
|
||||||
|
|
||||||
|
13
src/ceval.h
13
src/ceval.h
@ -69,6 +69,12 @@ __NEXT_STEP:;
|
|||||||
TARGET(POP_TOP) POP(); DISPATCH();
|
TARGET(POP_TOP) POP(); DISPATCH();
|
||||||
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
|
TARGET(DUP_TOP) PUSH(TOP()); DISPATCH();
|
||||||
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
|
TARGET(ROT_TWO) std::swap(TOP(), SECOND()); DISPATCH();
|
||||||
|
TARGET(ROT_THREE)
|
||||||
|
_0 = TOP();
|
||||||
|
TOP() = SECOND();
|
||||||
|
SECOND() = THIRD();
|
||||||
|
THIRD() = _0;
|
||||||
|
DISPATCH();
|
||||||
TARGET(PRINT_EXPR)
|
TARGET(PRINT_EXPR)
|
||||||
if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n");
|
if(TOP() != None) _stdout(this, CAST(Str&, py_repr(TOP())) + "\n");
|
||||||
POP();
|
POP();
|
||||||
@ -408,6 +414,13 @@ __NEXT_STEP:;
|
|||||||
if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
|
if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
|
||||||
else POP();
|
else POP();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
TARGET(SHORTCUT_IF_FALSE_OR_POP)
|
||||||
|
if(py_bool(TOP()) == false){ // [b, False]
|
||||||
|
STACK_SHRINK(2); // []
|
||||||
|
PUSH(vm->False); // [False]
|
||||||
|
frame->jump_abs(byte.arg);
|
||||||
|
} else POP(); // [b]
|
||||||
|
DISPATCH();
|
||||||
TARGET(LOOP_CONTINUE)
|
TARGET(LOOP_CONTINUE)
|
||||||
frame->jump_abs(co_blocks[byte.block].start);
|
frame->jump_abs(co_blocks[byte.block].start);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -178,9 +178,9 @@ inline PyObject* const PY_OP_CALL = (PyObject*)0b100011;
|
|||||||
inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
inline PyObject* const PY_OP_YIELD = (PyObject*)0b110011;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char kPlatformSep = '\\';
|
inline const char kPlatformSep = '\\';
|
||||||
#else
|
#else
|
||||||
char kPlatformSep = '/';
|
inline const char kPlatformSep = '/';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -93,12 +93,12 @@ class Compiler {
|
|||||||
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
|
rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT };
|
||||||
rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY };
|
rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
|
rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
|
||||||
rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
|
rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT };
|
||||||
rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND };
|
rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND };
|
||||||
@ -107,8 +107,8 @@ class Compiler {
|
|||||||
rules[TK("@")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("@")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY };
|
rules[TK("if")] = { nullptr, METHOD(exprTernary), PREC_TERNARY };
|
||||||
rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE };
|
rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE };
|
||||||
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST };
|
rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
|
rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND };
|
||||||
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
|
rules[TK("or")] = { nullptr, METHOD(exprOr), PREC_LOGICAL_OR };
|
||||||
rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT };
|
rules[TK("not")] = { METHOD(exprNot), nullptr, PREC_LOGICAL_NOT };
|
||||||
@ -856,8 +856,10 @@ __SUBSCR_END:
|
|||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
int namei = StrName(prev().str()).index;
|
int namei = StrName(prev().str()).index;
|
||||||
int super_namei = -1;
|
int super_namei = -1;
|
||||||
if(match(TK("(")) && match(TK("@id"))){
|
if(match(TK("("))){
|
||||||
super_namei = StrName(prev().str()).index;
|
if(match(TK("@id"))){
|
||||||
|
super_namei = StrName(prev().str()).index;
|
||||||
|
}
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
}
|
}
|
||||||
if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
|
if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
|
||||||
|
47
src/expr.h
47
src/expr.h
@ -23,6 +23,7 @@ struct Expr{
|
|||||||
virtual bool is_literal() const { return false; }
|
virtual bool is_literal() const { return false; }
|
||||||
virtual bool is_json_object() const { return false; }
|
virtual bool is_json_object() const { return false; }
|
||||||
virtual bool is_attrib() const { return false; }
|
virtual bool is_attrib() const { return false; }
|
||||||
|
virtual bool is_compare() const { return false; }
|
||||||
|
|
||||||
// for OP_DELETE_XXX
|
// for OP_DELETE_XXX
|
||||||
[[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
[[nodiscard]] virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
||||||
@ -531,6 +532,7 @@ struct FStringExpr: Expr{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _load_simple_expr(CodeEmitContext* ctx, Str expr){
|
void _load_simple_expr(CodeEmitContext* ctx, Str expr){
|
||||||
|
// TODO: pre compile this into a function
|
||||||
int dot = expr.index(".");
|
int dot = expr.index(".");
|
||||||
if(dot < 0){
|
if(dot < 0){
|
||||||
ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
|
ctx->emit(OP_LOAD_NAME, StrName(expr.sv()).index, line);
|
||||||
@ -682,8 +684,48 @@ struct BinaryExpr: Expr{
|
|||||||
Expr_ rhs;
|
Expr_ rhs;
|
||||||
std::string str() const override { return TK_STR(op); }
|
std::string str() const override { return TK_STR(op); }
|
||||||
|
|
||||||
|
bool is_compare() const override {
|
||||||
|
switch(op){
|
||||||
|
case TK("<"): case TK("<="): case TK("=="):
|
||||||
|
case TK("!="): case TK(">"): case TK(">="): return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _emit_compare(CodeEmitContext* ctx, std::vector<int>& jmps){
|
||||||
|
if(lhs->is_compare()){
|
||||||
|
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
|
||||||
|
}else{
|
||||||
|
lhs->emit(ctx); // [a]
|
||||||
|
}
|
||||||
|
rhs->emit(ctx); // [a, b]
|
||||||
|
ctx->emit(OP_DUP_TOP, BC_NOARG, line); // [a, b, b]
|
||||||
|
ctx->emit(OP_ROT_THREE, BC_NOARG, line); // [b, a, b]
|
||||||
|
switch(op){
|
||||||
|
case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break;
|
||||||
|
case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break;
|
||||||
|
case TK("=="): ctx->emit(OP_COMPARE_EQ, BC_NOARG, line); break;
|
||||||
|
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||||
|
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||||
|
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
// [b, RES]
|
||||||
|
int index = ctx->emit(OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||||
|
jmps.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
lhs->emit(ctx);
|
std::vector<int> jmps;
|
||||||
|
if(is_compare() && lhs->is_compare()){
|
||||||
|
// (a < b) < c
|
||||||
|
static_cast<BinaryExpr*>(lhs.get())->_emit_compare(ctx, jmps);
|
||||||
|
// [b, RES]
|
||||||
|
}else{
|
||||||
|
// (1 + 2) < c
|
||||||
|
lhs->emit(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
rhs->emit(ctx);
|
rhs->emit(ctx);
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
|
case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break;
|
||||||
@ -700,6 +742,7 @@ struct BinaryExpr: Expr{
|
|||||||
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
|
case TK("!="): ctx->emit(OP_COMPARE_NE, BC_NOARG, line); break;
|
||||||
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
|
case TK(">"): ctx->emit(OP_COMPARE_GT, BC_NOARG, line); break;
|
||||||
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
|
case TK(">="): ctx->emit(OP_COMPARE_GE, BC_NOARG, line); break;
|
||||||
|
|
||||||
case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
|
case TK("in"): ctx->emit(OP_CONTAINS_OP, 0, line); break;
|
||||||
case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
|
case TK("not in"): ctx->emit(OP_CONTAINS_OP, 1, line); break;
|
||||||
case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
|
case TK("is"): ctx->emit(OP_IS_OP, 0, line); break;
|
||||||
@ -714,6 +757,8 @@ struct BinaryExpr: Expr{
|
|||||||
case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
|
case TK("@"): ctx->emit(OP_BINARY_MATMUL, BC_NOARG, line); break;
|
||||||
default: FATAL_ERROR();
|
default: FATAL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i: jmps) ctx->patch_jump(i);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -79,9 +79,12 @@ enum Precedence {
|
|||||||
PREC_LOGICAL_OR, // or
|
PREC_LOGICAL_OR, // or
|
||||||
PREC_LOGICAL_AND, // and
|
PREC_LOGICAL_AND, // and
|
||||||
PREC_LOGICAL_NOT, // not
|
PREC_LOGICAL_NOT, // not
|
||||||
PREC_EQUALITY, // == !=
|
/* https://docs.python.org/3/reference/expressions.html#comparisons
|
||||||
PREC_TEST, // in / is / is not / not in
|
* Unlike C, all comparison operations in Python have the same priority,
|
||||||
PREC_COMPARISION, // < > <= >=
|
* which is lower than that of any arithmetic, shifting or bitwise operation.
|
||||||
|
* Also unlike C, expressions like a < b < c have the interpretation that is conventional in mathematics.
|
||||||
|
*/
|
||||||
|
PREC_COMPARISION, // < > <= >= != ==, in / is / is not / not in
|
||||||
PREC_BITWISE_OR, // |
|
PREC_BITWISE_OR, // |
|
||||||
PREC_BITWISE_XOR, // ^
|
PREC_BITWISE_XOR, // ^
|
||||||
PREC_BITWISE_AND, // &
|
PREC_BITWISE_AND, // &
|
||||||
|
@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
int main(int argc, char** argv){
|
int main(int argc, char** argv){
|
||||||
pkpy::VM* vm = pkpy_new_vm();
|
pkpy::VM* vm = pkpy_new_vm();
|
||||||
vm->bind_builtin_func<0>("input", [](pkpy::VM* vm, pkpy::ArgsView args){
|
pkpy::PyObject* input_f = vm->bind_builtin_func<0>("input", [](pkpy::VM* vm, pkpy::ArgsView args){
|
||||||
|
// pkpy::getline() has bugs for PIPE input on Windows
|
||||||
return VAR(pkpy::getline());
|
return VAR(pkpy::getline());
|
||||||
});
|
});
|
||||||
|
vm->_modules["sys"]->attr("stdin")->attr().set("readline", input_f);
|
||||||
if(argc == 1){
|
if(argc == 1){
|
||||||
pkpy::REPL* repl = pkpy_new_repl(vm);
|
pkpy::REPL* repl = pkpy_new_repl(vm);
|
||||||
bool need_more_lines = false;
|
bool need_more_lines = false;
|
||||||
|
@ -6,6 +6,7 @@ OPCODE(NO_OP)
|
|||||||
OPCODE(POP_TOP)
|
OPCODE(POP_TOP)
|
||||||
OPCODE(DUP_TOP)
|
OPCODE(DUP_TOP)
|
||||||
OPCODE(ROT_TWO)
|
OPCODE(ROT_TWO)
|
||||||
|
OPCODE(ROT_THREE)
|
||||||
OPCODE(PRINT_EXPR)
|
OPCODE(PRINT_EXPR)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(LOAD_CONST)
|
OPCODE(LOAD_CONST)
|
||||||
@ -75,6 +76,7 @@ OPCODE(JUMP_ABSOLUTE)
|
|||||||
OPCODE(POP_JUMP_IF_FALSE)
|
OPCODE(POP_JUMP_IF_FALSE)
|
||||||
OPCODE(JUMP_IF_TRUE_OR_POP)
|
OPCODE(JUMP_IF_TRUE_OR_POP)
|
||||||
OPCODE(JUMP_IF_FALSE_OR_POP)
|
OPCODE(JUMP_IF_FALSE_OR_POP)
|
||||||
|
OPCODE(SHORTCUT_IF_FALSE_OR_POP)
|
||||||
OPCODE(LOOP_CONTINUE)
|
OPCODE(LOOP_CONTINUE)
|
||||||
OPCODE(LOOP_BREAK)
|
OPCODE(LOOP_BREAK)
|
||||||
OPCODE(GOTO)
|
OPCODE(GOTO)
|
||||||
|
@ -104,6 +104,10 @@ inline void init_builtins(VM* _vm) {
|
|||||||
return VAR_T(VoidP, obj);
|
return VAR_T(VoidP, obj);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bind_builtin_func<1>("staticmethod", [](VM* vm, ArgsView args) {
|
||||||
|
return args[0];
|
||||||
|
});
|
||||||
|
|
||||||
_vm->bind_builtin_func<1>("__import__", [](VM* vm, ArgsView args) {
|
_vm->bind_builtin_func<1>("__import__", [](VM* vm, ArgsView args) {
|
||||||
return vm->py_import(CAST(Str&, args[0]));
|
return vm->py_import(CAST(Str&, args[0]));
|
||||||
});
|
});
|
||||||
@ -1110,8 +1114,10 @@ inline void add_module_sys(VM* vm){
|
|||||||
|
|
||||||
PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||||
PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||||
|
PyObject* stdin_ = vm->heap.gcnew<DummyInstance>(vm->tp_object, {});
|
||||||
vm->setattr(mod, "stdout", stdout_);
|
vm->setattr(mod, "stdout", stdout_);
|
||||||
vm->setattr(mod, "stderr", stderr_);
|
vm->setattr(mod, "stderr", stderr_);
|
||||||
|
vm->setattr(mod, "stdin", stdin_);
|
||||||
|
|
||||||
vm->bind_func<1>(stdout_, "write", [](VM* vm, ArgsView args) {
|
vm->bind_func<1>(stdout_, "write", [](VM* vm, ArgsView args) {
|
||||||
vm->_stdout(vm, CAST(Str&, args[0]));
|
vm->_stdout(vm, CAST(Str&, args[0]));
|
||||||
|
9
src/vm.h
9
src/vm.h
@ -1005,7 +1005,7 @@ inline Str VM::disassemble(CodeObject_ co){
|
|||||||
|
|
||||||
std::vector<int> jumpTargets;
|
std::vector<int> jumpTargets;
|
||||||
for(auto byte : co->codes){
|
for(auto byte : co->codes){
|
||||||
if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){
|
if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE || byte.op == OP_POP_JUMP_IF_FALSE || byte.op == OP_SHORTCUT_IF_FALSE_OR_POP){
|
||||||
jumpTargets.push_back(byte.arg);
|
jumpTargets.push_back(byte.arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1027,11 +1027,12 @@ inline Str VM::disassemble(CodeObject_ co){
|
|||||||
pointer = " ";
|
pointer = " ";
|
||||||
}
|
}
|
||||||
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
|
||||||
ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
|
ss << " " << pad(OP_NAMES[byte.op], 25) << " ";
|
||||||
// ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
|
// ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
|
||||||
std::string argStr = _opcode_argstr(this, byte, co.get());
|
std::string argStr = _opcode_argstr(this, byte, co.get());
|
||||||
ss << pad(argStr, 40); // may overflow
|
ss << argStr;
|
||||||
ss << co->blocks[byte.block].type;
|
// ss << pad(argStr, 40); // may overflow
|
||||||
|
// ss << co->blocks[byte.block].type;
|
||||||
if(i != co->codes.size() - 1) ss << '\n';
|
if(i != co->codes.size() - 1) ss << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
tests/31_cmp.py
Normal file
16
tests/31_cmp.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
assert 1<2
|
||||||
|
assert 1+1==2
|
||||||
|
assert 2+1>=2
|
||||||
|
|
||||||
|
assert 1<2<3
|
||||||
|
assert 1<2<3<4
|
||||||
|
assert 1<2<3<4<5
|
||||||
|
|
||||||
|
assert 1<1+1<3
|
||||||
|
assert 1<1+1<3<4
|
||||||
|
assert 1<1+1<3<2+2<5
|
||||||
|
|
||||||
|
a = [1,2,3]
|
||||||
|
assert a[0] < a[1] < a[2]
|
||||||
|
assert a[0]+1 == a[1] < a[2]
|
||||||
|
assert a[0]+1 == a[1] < a[2]+1 < 5
|
Loading…
x
Reference in New Issue
Block a user