This commit is contained in:
blueloveTH 2023-04-01 21:57:05 +08:00
parent ea86ea3a34
commit 83d6ac2e78
6 changed files with 88 additions and 270 deletions

BIN
.github/workflows.rar vendored Normal file

Binary file not shown.

View File

@ -1,129 +0,0 @@
name: build
on: [push, pull_request]
jobs:
build_win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Setup Clang
uses: egor-tensin/setup-clang@v1
with:
version: 15
platform: x64
- name: Compiling
shell: bash
run: |
python3 build.py windows
python3 build.py windows -lib
mkdir -p output/windows/x86_64
cp pocketpy.exe output/windows/x86_64
cp pocketpy.dll output/windows/x86_64
- uses: actions/upload-artifact@v3
with:
path: output
- name: Unit Test
run: python3 scripts/run_tests.py
- name: Benchmark
run: python3 scripts/run_tests.py benchmark
build_web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v12
with:
version: 3.1.25
actions-cache-folder: 'emsdk-cache'
- name: Verify emsdk
run: emcc -v
- name: Compiling
run: |
mkdir -p output/web/lib
python3 build.py web
cp web/lib/* output/web/lib
- uses: crazy-max/ghaction-github-pages@v3
with:
target_branch: gh-pages
build_dir: web
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- uses: actions/upload-artifact@v3
with:
path: output
build_linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Clang
uses: egor-tensin/setup-clang@v1
with:
version: 15
platform: x64
- name: Coverage Test
run: |
sudo apt install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15 libclang-rt-15-dev
python3 preprocess.py
bash run_tests.sh
- uses: actions/upload-artifact@v3
with:
name: coverage
path: .coverage
- name: Compiling
run: |
python3 build.py linux
python3 build.py linux -lib
mkdir -p output/linux/x86_64
cp pocketpy output/linux/x86_64
cp pocketpy.so output/linux/x86_64
- uses: actions/upload-artifact@v3
with:
path: output
- name: Unit Test
run: python3 scripts/run_tests.py
- name: Benchmark
run: python3 scripts/run_tests.py benchmark
build_android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.3.0'
channel: 'stable'
cache: true
- run: flutter --version
- name: Compiling
run: |
python3 amalgamate.py
cd plugins/flutter/example
flutter build apk --split-debug-info=.debug-info --split-per-abi
cd build/app/outputs/flutter-apk
mkdir -p output/android/arm64-v8a
mkdir -p output/android/armeabi-v7a
mkdir -p output/android/x86_64
unzip -q app-arm64-v8a-release.apk -d tmp
mv tmp/lib/arm64-v8a/libpocketpy.so output/android/arm64-v8a/libpocketpy.so
rm -rf tmp
unzip -q app-armeabi-v7a-release.apk -d tmp
mv tmp/lib/armeabi-v7a/libpocketpy.so output/android/armeabi-v7a/libpocketpy.so
rm -rf tmp
unzip -q app-x86_64-release.apk -d tmp
mv tmp/lib/x86_64/libpocketpy.so output/android/x86_64/libpocketpy.so
rm -rf tmp
- uses: actions/upload-artifact@v3
with:
path: plugins/flutter/example/build/app/outputs/flutter-apk/output
build_macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- run: |
python3 amalgamate.py
cd plugins/macos/pocketpy
mkdir -p output/macos
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
cp -r build/Release/pocketpy.bundle output/macos
- uses: actions/upload-artifact@v3
with:
path: plugins/macos/pocketpy/output

View File

@ -1,13 +1,14 @@
#pragma once #pragma once
#include "common.h"
#include "vm.h" #include "vm.h"
#include "ref.h" #include "ref.h"
namespace pkpy{ namespace pkpy{
inline PyObject* VM::run_frame(Frame* frame){ inline PyObject* VM::run_frame(Frame* frame){
while(frame->has_next_bytecode()){ while(true){
heap._auto_collect(this); heap._auto_collect(this); // gc
const Bytecode& byte = frame->next_bytecode(); const Bytecode& byte = frame->next_bytecode();
switch (byte.op) switch (byte.op)
@ -320,15 +321,7 @@ inline PyObject* VM::run_frame(Frame* frame){
default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented"); default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
} }
} }
UNREACHABLE();
if(frame->co->src->mode == EVAL_MODE || frame->co->src->mode == JSON_MODE){
if(frame->_data.size() != 1) throw std::runtime_error("_data.size() != 1 in EVAL/JSON_MODE");
return frame->pop_value(this);
}
#if DEBUG_EXTRA_CHECK
if(!frame->_data.empty()) throw std::runtime_error("_data.size() != 0 in EXEC_MODE");
#endif
return None;
} }
} // namespace pkpy } // namespace pkpy

View File

@ -20,8 +20,6 @@ struct PrattRule{
Precedence precedence; Precedence precedence;
}; };
enum ExprAction { EXPR_PUSH_STACK, EXPR_RVALUE, EXPR_LVALUE };
class Compiler { class Compiler {
std::unique_ptr<Lexer> lexer; std::unique_ptr<Lexer> lexer;
stack<CodeEmitContext> contexts; stack<CodeEmitContext> contexts;
@ -42,8 +40,10 @@ class Compiler {
} }
void pop_context(){ void pop_context(){
if(!ctx()->s_expr.empty()){ if(!ctx()->s_expr.empty()) UNREACHABLE();
ctx()->emit_expr(); if(ctx()->co->codes.back().op != OP_RETURN_VALUE){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
} }
ctx()->co->optimize(vm); ctx()->co->optimize(vm);
contexts.pop(); contexts.pop();
@ -164,16 +164,12 @@ private:
if (!match_end_stmt()) SyntaxError("expected statement end"); if (!match_end_stmt()) SyntaxError("expected statement end");
} }
void exprLiteral(){ void EXPR(ExprAction action=EXPR_PUSH_STACK) {
ctx()->s_expr.push( parse_expression(PREC_TUPLE + 1, action);
expr_prev_line<LiteralExpr>(prev().value)
);
} }
void exprFString(){ void EXPR_TUPLE(ExprAction action=EXPR_PUSH_STACK) {
ctx()->s_expr.push( parse_expression(PREC_TUPLE, action);
expr_prev_line<FStringExpr>(std::get<Str>(prev().value))
);
} }
template <typename T, typename... Args> template <typename T, typename... Args>
@ -183,6 +179,19 @@ private:
return expr; return expr;
} }
/********************************************/
// PASS
void exprLiteral(){
ctx()->s_expr.push(expr_prev_line<LiteralExpr>(prev().value));
}
// PASS
void exprFString(){
ctx()->s_expr.push(expr_prev_line<FStringExpr>(std::get<Str>(prev().value)));
}
// PASS
void exprLambda(){ void exprLambda(){
auto e = expr_prev_line<LambdaExpr>(); auto e = expr_prev_line<LambdaExpr>();
e->func.name = "<lambda>"; e->func.name = "<lambda>";
@ -192,42 +201,14 @@ private:
consume(TK(":")); consume(TK(":"));
} }
e->func.code = push_context(lexer->src, "<lambda>"); e->func.code = push_context(lexer->src, "<lambda>");
EXPR(); // https://github.com/blueloveTH/pocketpy/issues/37
EXPR(true);
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));
} }
// assignment是一种特殊的无返回值表达式他不应该位于PREC中
void exprInplaceAssign(){
auto e = expr_prev_line<InplaceAssignExpr>();
e->op = prev().type;
e->lhs = ctx()->s_expr.popx();
// lhs cannot be a assignment expression, i.e. a = b += c is not allowed
if(e->lhs->is_assignment()) SyntaxError();
EXPR_TUPLE();
e->rhs = ctx()->s_expr.popx();
ctx()->s_expr.push(std::move(e));
}
void EXPR(ExprAction action=EXPR_PUSH_STACK) {
parse_expression(PREC_TUPLE + 1, action);
}
void EXPR_TUPLE(ExprAction action=EXPR_PUSH_STACK) {
parse_expression(PREC_TUPLE, action);
}
void exprAssign(){ void exprAssign(){
auto e = expr_prev_line<AssignExpr>();
e->lhs = ctx()->s_expr.popx();
// lhs cannot be a assignment expression, i.e. a = b = c is not allowed
// however in cpython, it is allowed, we'll fix it later
if(e->lhs->is_assignment()) SyntaxError();
EXPR_TUPLE();
e->rhs = ctx()->s_expr.popx();
ctx()->s_expr.push(std::move(e));
// if(co()->codes.empty()) UNREACHABLE(); // if(co()->codes.empty()) UNREACHABLE();
// bool is_load_name_ref = co()->codes.back().op == OP_LOAD_NAME_REF; // bool is_load_name_ref = co()->codes.back().op == OP_LOAD_NAME_REF;
// int _name_arg = co()->codes.back().arg; // int _name_arg = co()->codes.back().arg;
@ -277,6 +258,7 @@ private:
// co()->_rvalue -= 1; // co()->_rvalue -= 1;
} }
// PASS
void exprTuple(){ void exprTuple(){
auto e = expr_prev_line<TupleExpr>(); auto e = expr_prev_line<TupleExpr>();
do { do {
@ -286,6 +268,7 @@ private:
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprOr(){ void exprOr(){
auto e = expr_prev_line<OrExpr>(); auto e = expr_prev_line<OrExpr>();
e->lhs = ctx()->s_expr.popx(); e->lhs = ctx()->s_expr.popx();
@ -294,14 +277,16 @@ private:
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprAnd(){ void exprAnd(){
auto e = expr_prev_line<OrExpr>(); auto e = expr_prev_line<AndExpr>();
e->lhs = ctx()->s_expr.popx(); e->lhs = ctx()->s_expr.popx();
parse_expression(PREC_LOGICAL_AND + 1); parse_expression(PREC_LOGICAL_AND + 1);
e->rhs = ctx()->s_expr.popx(); e->rhs = ctx()->s_expr.popx();
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprTernary(){ void exprTernary(){
auto e = expr_prev_line<TernaryExpr>(); auto e = expr_prev_line<TernaryExpr>();
e->cond = ctx()->s_expr.popx(); e->cond = ctx()->s_expr.popx();
@ -313,6 +298,7 @@ private:
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprBinaryOp(){ void exprBinaryOp(){
auto e = expr_prev_line<BinaryExpr>(); auto e = expr_prev_line<BinaryExpr>();
e->op = prev().type; e->op = prev().type;
@ -322,85 +308,56 @@ private:
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprNot() { void exprNot() {
parse_expression(PREC_LOGICAL_NOT + 1); parse_expression(PREC_LOGICAL_NOT + 1);
ctx()->s_expr.push( ctx()->s_expr.push(expr_prev_line<NotExpr>(ctx()->s_expr.popx()));
expr_prev_line<NotExpr>(ctx()->s_expr.popx())
);
} }
// PASS
void exprUnaryOp(){ void exprUnaryOp(){
TokenIndex type = prev().type; TokenIndex op = prev().type;
parse_expression(PREC_UNARY + 1); parse_expression(PREC_UNARY + 1);
Expr_ e; switch(op){
switch(type){
case TK("-"): case TK("-"):
e = expr_prev_line<NegatedExpr>(ctx()->s_expr.popx()); ctx()->s_expr.push(expr_prev_line<NegatedExpr>(ctx()->s_expr.popx()));
break;
case TK("*"): case TK("*"):
e = expr_prev_line<StarredExpr>(ctx()->s_expr.popx()); ctx()->s_expr.push(expr_prev_line<StarredExpr>(ctx()->s_expr.popx()));
break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
ctx()->s_expr.push(std::move(e));
} }
// () is just for change precedence // PASS
void exprGroup(){ void exprGroup(){
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
EXPR_TUPLE(); EXPR_TUPLE(); // () is just for change precedence
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
consume(TK(")")); consume(TK(")"));
} }
// void _consume_comp(Opcode op0, Opcode op1, int _patch, int _body_start){ // PASS
// int _body_end_return = emit(OP_JUMP_ABSOLUTE, -1);
// int _body_end = co()->codes.size();
// co()->codes[_patch].op = OP_JUMP_ABSOLUTE;
// co()->codes[_patch].arg = _body_end;
// emit(op0, 0);
// EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
// match_newlines(mode()==REPL_MODE);
// int _skipPatch = emit(OP_JUMP_ABSOLUTE);
// int _cond_start = co()->codes.size();
// int _cond_end_return = -1;
// if(match(TK("if"))) {
// EXPR_TUPLE();
// _cond_end_return = emit(OP_JUMP_ABSOLUTE, -1);
// }
// patch_jump(_skipPatch);
// emit(OP_GET_ITER);
// co()->_enter_block(FOR_LOOP);
// emit(OP_FOR_ITER);
// if(_cond_end_return != -1) { // there is an if condition
// emit(OP_JUMP_ABSOLUTE, _cond_start);
// patch_jump(_cond_end_return);
// int ifpatch = emit(OP_POP_JUMP_IF_FALSE);
// emit(OP_JUMP_ABSOLUTE, _body_start);
// patch_jump(_body_end_return);
// emit(op1);
// patch_jump(ifpatch);
// }else{
// emit(OP_JUMP_ABSOLUTE, _body_start);
// patch_jump(_body_end_return);
// emit(op1);
// }
// emit(OP_LOOP_CONTINUE, -1, true);
// co()->_exit_block();
// match_newlines(mode()==REPL_MODE);
// }
template<typename T> template<typename T>
void _consume_comp(Expr_ expr){ void _consume_comp(Expr_ expr){
static_assert(std::is_base_of<CompExpr, T>::value); static_assert(std::is_base_of<CompExpr, T>::value);
std::unique_ptr<CompExpr> ce = std::make_unique<T>(); std::unique_ptr<CompExpr> ce = std::make_unique<T>();
ce->expr = std::move(expr); ce->expr = std::move(expr);
// ... EXPR_TUPLE(); // must be a lvalue
ce->vars = ctx()->s_expr.popx();
consume(TK("in"));
EXPR();
ce->iter = ctx()->s_expr.popx();
match_newlines(mode()==REPL_MODE);
if(match(TK("if"))){
EXPR();
ce->cond = ctx()->s_expr.popx();
}
ctx()->s_expr.push(std::move(ce)); ctx()->s_expr.push(std::move(ce));
match_newlines(mode()==REPL_MODE);
} }
// PASS
void exprList() { void exprList() {
auto e = expr_prev_line<ListExpr>(); auto e = expr_prev_line<ListExpr>();
do { do {
@ -414,15 +371,15 @@ private:
consume(TK("]")); consume(TK("]"));
return; return;
} }
} while (match(TK(",")));
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
} while (match(TK(",")));
consume(TK("]")); consume(TK("]"));
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// {...} may be dict or set // PASS
void exprMap() { void exprMap() {
bool parsing_dict = false; bool parsing_dict = false; // {...} may be dict or set
std::vector<Expr_> items; std::vector<Expr_> items;
do { do {
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
@ -446,6 +403,7 @@ private:
consume(TK("}")); consume(TK("}"));
return; return;
} }
match_newlines(mode()==REPL_MODE);
} while (match(TK(","))); } while (match(TK(",")));
consume(TK("}")); consume(TK("}"));
if(items.size()==0 || parsing_dict){ if(items.size()==0 || parsing_dict){
@ -457,8 +415,10 @@ private:
} }
} }
// PASS
void exprCall() { void exprCall() {
auto e = expr_prev_line<CallExpr>(); auto e = expr_prev_line<CallExpr>();
e->callable = ctx()->s_expr.popx();
do { do {
match_newlines(mode()==REPL_MODE); match_newlines(mode()==REPL_MODE);
if (curr().type==TK(")")) break; if (curr().type==TK(")")) break;
@ -487,12 +447,12 @@ private:
// } // }
} }
// PASS
void exprName(){ void exprName(){
ctx()->s_expr.push( ctx()->s_expr.push(expr_prev_line<NameExpr>(prev().str(), name_scope()));
expr_prev_line<NameExpr>(prev().str(), name_scope())
);
} }
// PASS
void exprAttrib() { void exprAttrib() {
consume(TK("@id")); consume(TK("@id"));
ctx()->s_expr.push( ctx()->s_expr.push(
@ -500,6 +460,7 @@ private:
); );
} }
// PASS
void exprSubscr() { void exprSubscr() {
auto e = expr_prev_line<SubscrExpr>(); auto e = expr_prev_line<SubscrExpr>();
std::vector<Expr_> items; std::vector<Expr_> items;
@ -526,10 +487,9 @@ private:
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} }
// PASS
void exprLiteral0() { void exprLiteral0() {
ctx()->s_expr.push( ctx()->s_expr.push(expr_prev_line<Literal0Expr>(prev().type));
expr_prev_line<Literal0Expr>(prev().type)
);
} }
void compile_block_body() { void compile_block_body() {
@ -599,7 +559,7 @@ private:
consume_end_stmt(); consume_end_stmt();
} }
void parse_expression(int precedence, ExprAction action=EXPR_PUSH_STACK) { void parse_expression(int precedence, bool push_stack=true) {
advance(); advance();
PrattCallback prefix = rules[prev().type].prefix; PrattCallback prefix = rules[prev().type].prefix;
if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(prev().type)); if (prefix == nullptr) SyntaxError(Str("expected an expression, but got ") + TK_STR(prev().type));
@ -611,16 +571,11 @@ private:
if(infix == nullptr) throw std::runtime_error("(infix == nullptr) is true"); if(infix == nullptr) throw std::runtime_error("(infix == nullptr) is true");
(this->*infix)(); (this->*infix)();
} }
switch(action){ if(!push_stack) ctx()->emit_expr();
case EXPR_PUSH_STACK: break;
case EXPR_RVALUE: ctx()->emit_rvalue(); break;
case EXPR_LVALUE: ctx()->emit_lvalue(); break;
default: UNREACHABLE();
}
} }
void compile_if_stmt() { void compile_if_stmt() {
EXPR(EXPR_RVALUE); // condition EXPR(true); // condition
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line); int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
compile_block_body(); compile_block_body();
if (match(TK("elif"))) { if (match(TK("elif"))) {
@ -640,7 +595,7 @@ private:
void compile_while_loop() { void compile_while_loop() {
ctx()->enter_block(WHILE_LOOP); ctx()->enter_block(WHILE_LOOP);
EXPR(EXPR_RVALUE); // condition EXPR(true); // condition
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line); int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
compile_block_body(); compile_block_body();
ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
@ -649,9 +604,10 @@ private:
} }
void compile_for_loop() { void compile_for_loop() {
EXPR_TUPLE(EXPR_LVALUE); EXPR_TUPLE();
ctx()->emit_lvalue();
consume(TK("in")); consume(TK("in"));
EXPR_TUPLE(EXPR_RVALUE); EXPR(true);
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
ctx()->enter_block(FOR_LOOP); ctx()->enter_block(FOR_LOOP);
ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
@ -689,10 +645,8 @@ private:
} }
void compile_decorated(){ void compile_decorated(){
EXPR(EXPR_RVALUE); EXPR(true);
if(!match_newlines(mode()==REPL_MODE)){ if(!match_newlines(mode()==REPL_MODE)) SyntaxError();
SyntaxError("expected a new line after '@'");
}
ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line); ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line);
consume(TK("def")); consume(TK("def"));
compile_function(); compile_function();
@ -718,7 +672,7 @@ private:
break; break;
case TK("yield"): case TK("yield"):
if (contexts.size() <= 1) SyntaxError("'yield' outside function"); if (contexts.size() <= 1) SyntaxError("'yield' outside function");
EXPR_TUPLE(EXPR_RVALUE); EXPR_TUPLE(true);
// if yield present, the function is a generator // if yield present, the function is a generator
ctx()->co->is_generator = true; ctx()->co->is_generator = true;
ctx()->emit(OP_YIELD_VALUE, BC_NOARG, kw_line); ctx()->emit(OP_YIELD_VALUE, BC_NOARG, kw_line);
@ -729,7 +683,7 @@ private:
if(match_end_stmt()){ if(match_end_stmt()){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line); ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
}else{ }else{
EXPR_TUPLE(EXPR_RVALUE); EXPR_TUPLE(true);
consume_end_stmt(); consume_end_stmt();
} }
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, kw_line); ctx()->emit(OP_RETURN_VALUE, BC_NOARG, kw_line);
@ -746,13 +700,14 @@ private:
case TK("pass"): consume_end_stmt(); break; case TK("pass"): consume_end_stmt(); break;
/*************************************************/ /*************************************************/
case TK("assert"): case TK("assert"):
EXPR_TUPLE(EXPR_RVALUE); EXPR_TUPLE(true);
// TODO: change OP_ASSERT impl in ceval.h // TODO: change OP_ASSERT impl in ceval.h
ctx()->emit(OP_ASSERT, BC_NOARG, kw_line); ctx()->emit(OP_ASSERT, BC_NOARG, kw_line);
consume_end_stmt(); consume_end_stmt();
break; break;
case TK("del"): case TK("del"):
EXPR_TUPLE(EXPR_LVALUE); EXPR_TUPLE();
ctx()->emit_lvalue();
ctx()->emit(OP_DELETE_REF, BC_NOARG, kw_line); ctx()->emit(OP_DELETE_REF, BC_NOARG, kw_line);
consume_end_stmt(); consume_end_stmt();
break; break;
@ -767,7 +722,7 @@ private:
consume(TK("@id")); consume(TK("@id"));
int dummy_t = ctx()->add_name(prev().str(), NAME_SPECIAL); int dummy_t = ctx()->add_name(prev().str(), NAME_SPECIAL);
if(match(TK("(")) && !match(TK(")"))){ if(match(TK("(")) && !match(TK(")"))){
EXPR(EXPR_RVALUE); consume(TK(")")); EXPR(true); consume(TK(")"));
}else{ }else{
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
} }
@ -775,7 +730,7 @@ private:
consume_end_stmt(); consume_end_stmt();
} break; } break;
case TK("with"): { case TK("with"): {
EXPR(EXPR_RVALUE); EXPR(true);
consume(TK("as")); consume(TK("as"));
consume(TK("@id")); consume(TK("@id"));
int index = ctx()->add_name(prev().str(), name_scope()); int index = ctx()->add_name(prev().str(), name_scope());
@ -953,6 +908,7 @@ public:
if(mode()==EVAL_MODE) { if(mode()==EVAL_MODE) {
EXPR_TUPLE(); EXPR_TUPLE();
consume(TK("@eof")); consume(TK("@eof"));
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context(); pop_context();
return code; return code;
}else if(mode()==JSON_MODE){ }else if(mode()==JSON_MODE){
@ -962,6 +918,7 @@ public:
else if(match(TK("["))) exprList(); else if(match(TK("["))) exprList();
else SyntaxError("expect a JSON object or array"); else SyntaxError("expect a JSON object or array");
consume(TK("@eof")); consume(TK("@eof"));
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context(); pop_context();
return code; return code;
} }

View File

@ -343,6 +343,7 @@ struct AttribExpr: Expr{
}; };
struct CallExpr: Expr{ struct CallExpr: Expr{
Expr_ callable;
std::vector<Expr_> args; std::vector<Expr_> args;
std::vector<std::pair<Str, Expr_>> kwargs; std::vector<std::pair<Str, Expr_>> kwargs;
Str str() const override { return "()"; } Str str() const override { return "()"; }

View File

@ -53,10 +53,6 @@ struct Frame {
// return ss.str(); // return ss.str();
// } // }
bool has_next_bytecode() const {
return _next_ip < co->codes.size();
}
PyObject* pop(){ PyObject* pop(){
#if DEBUG_EXTRA_CHECK #if DEBUG_EXTRA_CHECK
if(_data.empty()) throw std::runtime_error("_data.empty() is true"); if(_data.empty()) throw std::runtime_error("_data.empty() is true");