mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
This commit is contained in:
parent
d2becdb9f5
commit
88c0102e79
@ -57,7 +57,7 @@ class Compiler {
|
|||||||
|
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
void EXPR();
|
void EXPR();
|
||||||
void EXPR_TUPLE();
|
void EXPR_TUPLE(bool allow_slice=false);
|
||||||
Expr_ EXPR_VARS(); // special case for `for loop` and `comp`
|
Expr_ EXPR_VARS(); // special case for `for loop` and `comp`
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
@ -111,8 +111,8 @@ class Compiler {
|
|||||||
void compile_block_body(void (Compiler::*callback)()=nullptr);
|
void compile_block_body(void (Compiler::*callback)()=nullptr);
|
||||||
void compile_normal_import();
|
void compile_normal_import();
|
||||||
void compile_from_import();
|
void compile_from_import();
|
||||||
bool is_expression();
|
bool is_expression(bool allow_slice=false);
|
||||||
void parse_expression(int precedence, bool push_stack=true);
|
void parse_expression(int precedence, bool allow_slice=false);
|
||||||
void compile_if_stmt();
|
void compile_if_stmt();
|
||||||
void compile_while_loop();
|
void compile_while_loop();
|
||||||
void compile_for_loop();
|
void compile_for_loop();
|
||||||
|
@ -169,16 +169,17 @@ namespace pkpy{
|
|||||||
parse_expression(PREC_LOWEST+1);
|
parse_expression(PREC_LOWEST+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::EXPR_TUPLE() {
|
void Compiler::EXPR_TUPLE(bool allow_slice) {
|
||||||
EXPR();
|
parse_expression(PREC_LOWEST+1, allow_slice);
|
||||||
if(!match(TK(","))) return;
|
if(!match(TK(","))) return;
|
||||||
// tuple expression
|
// tuple expression
|
||||||
std::vector<Expr_> items;
|
std::vector<Expr_> items;
|
||||||
items.push_back(ctx()->s_expr.popx());
|
items.push_back(ctx()->s_expr.popx());
|
||||||
do {
|
do {
|
||||||
if(curr().brackets_level) match_newlines_repl();
|
if(curr().brackets_level) match_newlines_repl();
|
||||||
if(!is_expression()) break;
|
if(!is_expression(allow_slice)) break;
|
||||||
EXPR(); items.push_back(ctx()->s_expr.popx());
|
parse_expression(PREC_LOWEST+1, allow_slice);
|
||||||
|
items.push_back(ctx()->s_expr.popx());
|
||||||
if(curr().brackets_level) match_newlines_repl();
|
if(curr().brackets_level) match_newlines_repl();
|
||||||
} while(match(TK(",")));
|
} while(match(TK(",")));
|
||||||
ctx()->s_expr.push(make_expr<TupleExpr>(std::move(items)));
|
ctx()->s_expr.push(make_expr<TupleExpr>(std::move(items)));
|
||||||
@ -223,7 +224,8 @@ namespace pkpy{
|
|||||||
consume(TK(":"));
|
consume(TK(":"));
|
||||||
}
|
}
|
||||||
// https://github.com/blueloveTH/pocketpy/issues/37
|
// https://github.com/blueloveTH/pocketpy/issues/37
|
||||||
parse_expression(PREC_LAMBDA + 1, false);
|
parse_expression(PREC_LAMBDA + 1);
|
||||||
|
ctx()->emit_expr();
|
||||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||||
pop_context();
|
pop_context();
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
@ -418,38 +420,48 @@ namespace pkpy{
|
|||||||
|
|
||||||
void Compiler::exprSlice0() {
|
void Compiler::exprSlice0() {
|
||||||
auto slice = make_expr<SliceExpr>();
|
auto slice = make_expr<SliceExpr>();
|
||||||
if(is_expression()){ // :<expr>
|
if(is_expression()){ // :<stop>
|
||||||
EXPR();
|
EXPR();
|
||||||
slice->stop = ctx()->s_expr.popx();
|
slice->stop = ctx()->s_expr.popx();
|
||||||
// try optional step
|
// try optional step
|
||||||
if(match(TK(":"))){
|
if(match(TK(":"))){ // :<stop>:<step>
|
||||||
EXPR();
|
EXPR();
|
||||||
slice->step = ctx()->s_expr.popx();
|
slice->step = ctx()->s_expr.popx();
|
||||||
}
|
}
|
||||||
}
|
}else if(match(TK(":"))){
|
||||||
|
if(is_expression()){ // ::<step>
|
||||||
|
EXPR();
|
||||||
|
slice->step = ctx()->s_expr.popx();
|
||||||
|
} // else ::
|
||||||
|
} // else :
|
||||||
ctx()->s_expr.push(std::move(slice));
|
ctx()->s_expr.push(std::move(slice));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::exprSlice1() {
|
void Compiler::exprSlice1() {
|
||||||
auto slice = make_expr<SliceExpr>();
|
auto slice = make_expr<SliceExpr>();
|
||||||
slice->start = ctx()->s_expr.popx();
|
slice->start = ctx()->s_expr.popx();
|
||||||
if(is_expression()){ // <expr>:<expr>
|
if(is_expression()){ // <start>:<stop>
|
||||||
EXPR();
|
EXPR();
|
||||||
slice->stop = ctx()->s_expr.popx();
|
slice->stop = ctx()->s_expr.popx();
|
||||||
// try optional step
|
// try optional step
|
||||||
if(match(TK(":"))){
|
if(match(TK(":"))){ // <start>:<stop>:<step>
|
||||||
EXPR();
|
EXPR();
|
||||||
slice->step = ctx()->s_expr.popx();
|
slice->step = ctx()->s_expr.popx();
|
||||||
}
|
}
|
||||||
}
|
}else if(match(TK(":"))){ // <start>::<step>
|
||||||
|
EXPR();
|
||||||
|
slice->step = ctx()->s_expr.popx();
|
||||||
|
} // else <start>:
|
||||||
ctx()->s_expr.push(std::move(slice));
|
ctx()->s_expr.push(std::move(slice));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::exprSubscr() {
|
void Compiler::exprSubscr() {
|
||||||
auto e = make_expr<SubscrExpr>();
|
auto e = make_expr<SubscrExpr>();
|
||||||
e->a = ctx()->s_expr.popx(); // a[...]
|
match_newlines_repl();
|
||||||
EXPR_TUPLE(); // a[<expr>]
|
e->a = ctx()->s_expr.popx(); // a
|
||||||
e->b = ctx()->s_expr.popx();
|
EXPR_TUPLE(true);
|
||||||
|
e->b = ctx()->s_expr.popx(); // a[<expr>]
|
||||||
|
match_newlines_repl();
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
@ -561,27 +573,25 @@ __EAT_DOTS_END:
|
|||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::is_expression(){
|
bool Compiler::is_expression(bool allow_slice){
|
||||||
PrattCallback prefix = rules[curr().type].prefix;
|
PrattCallback prefix = rules[curr().type].prefix;
|
||||||
// slice expression is restricted to be used in subscript
|
return prefix != nullptr && (allow_slice || curr().type!=TK(":"));
|
||||||
return prefix != nullptr && curr().type != TK(":");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::parse_expression(int precedence, bool push_stack) {
|
void Compiler::parse_expression(int precedence, bool allow_slice) {
|
||||||
PrattCallback prefix = rules[curr().type].prefix;
|
PrattCallback prefix = rules[curr().type].prefix;
|
||||||
if (prefix == nullptr || curr().type == TK(":")){
|
if (prefix==nullptr || (curr().type==TK(":") && !allow_slice)){
|
||||||
SyntaxError(Str("expected an expression, got ") + TK_STR(curr().type));
|
SyntaxError(Str("expected an expression, got ") + TK_STR(curr().type));
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
(this->*prefix)();
|
(this->*prefix)();
|
||||||
while (rules[curr().type].precedence >= precedence && curr().type != TK(":")) {
|
while (rules[curr().type].precedence >= precedence && (allow_slice || curr().type!=TK(":"))) {
|
||||||
TokenIndex op = curr().type;
|
TokenIndex op = curr().type;
|
||||||
advance();
|
advance();
|
||||||
PrattCallback infix = rules[op].infix;
|
PrattCallback infix = rules[op].infix;
|
||||||
PK_ASSERT(infix != nullptr);
|
PK_ASSERT(infix != nullptr);
|
||||||
(this->*infix)();
|
(this->*infix)();
|
||||||
}
|
}
|
||||||
if(!push_stack) ctx()->emit_expr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_if_stmt() {
|
void Compiler::compile_if_stmt() {
|
||||||
|
@ -1016,6 +1016,16 @@ void init_builtins(VM* _vm) {
|
|||||||
return VAR(Slice(args[1], args[2], args[3]));
|
return VAR(Slice(args[1], args[2], args[3]));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_vm->bind__eq__(VM::tp_slice, [](VM* vm, PyObject* _0, PyObject* _1){
|
||||||
|
const Slice& self = _CAST(Slice&, _0);
|
||||||
|
if(!is_non_tagged_type(_1, vm->tp_slice)) return vm->NotImplemented;
|
||||||
|
const Slice& other = _CAST(Slice&, _1);
|
||||||
|
if(vm->py_ne(self.start, other.start)) return vm->False;
|
||||||
|
if(vm->py_ne(self.stop, other.stop)) return vm->False;
|
||||||
|
if(vm->py_ne(self.step, other.step)) return vm->False;
|
||||||
|
return vm->True;
|
||||||
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyObject* _0) {
|
||||||
const Slice& self = _CAST(Slice&, _0);
|
const Slice& self = _CAST(Slice&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
|
@ -101,3 +101,18 @@ a.append(0)
|
|||||||
a.append([1, 2, a])
|
a.append([1, 2, a])
|
||||||
|
|
||||||
assert repr(a) == "[0, [1, 2, [...]]]"
|
assert repr(a) == "[0, [1, 2, [...]]]"
|
||||||
|
|
||||||
|
# slice extras
|
||||||
|
class A:
|
||||||
|
def __getitem__(self, index):
|
||||||
|
return index
|
||||||
|
|
||||||
|
assert A()[1:2, 3] == (slice(1, 2, None), 3)
|
||||||
|
assert A()[1:2, 3:4] == (slice(1, 2, None), slice(3, 4, None))
|
||||||
|
assert A()[1:2, 3:4, 5] == (slice(1, 2, None), slice(3, 4, None), 5)
|
||||||
|
assert A()[:, :] == (slice(None, None, None), slice(None, None, None))
|
||||||
|
assert A()[::, :] == (slice(None, None, None), slice(None, None, None))
|
||||||
|
assert A()[::, :2] == (slice(None, None, None), slice(None, 2, None))
|
||||||
|
assert A()['b':'c':1, :] == (slice('b', 'c', 1), slice(None, None, None))
|
||||||
|
assert A()[1:2, :A()[3:4, ::-1]] == (slice(1, 2, None), slice(None, (slice(3, 4, None), slice(None, None, -1)), None))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user