mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
some refactor
This commit is contained in:
parent
8d3bb6faa5
commit
d64863fd43
@ -56,8 +56,8 @@ class Compiler {
|
|||||||
void consume_end_stmt();
|
void consume_end_stmt();
|
||||||
|
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
void EXPR(bool push_stack=true);
|
void EXPR();
|
||||||
void EXPR_TUPLE(bool push_stack=true);
|
void EXPR_TUPLE();
|
||||||
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>
|
||||||
@ -91,7 +91,6 @@ class Compiler {
|
|||||||
void exprBytes();
|
void exprBytes();
|
||||||
void exprFString();
|
void exprFString();
|
||||||
void exprLambda();
|
void exprLambda();
|
||||||
void exprTuple();
|
|
||||||
void exprOr();
|
void exprOr();
|
||||||
void exprAnd();
|
void exprAnd();
|
||||||
void exprTernary();
|
void exprTernary();
|
||||||
@ -104,6 +103,8 @@ class Compiler {
|
|||||||
void exprCall();
|
void exprCall();
|
||||||
void exprName();
|
void exprName();
|
||||||
void exprAttrib();
|
void exprAttrib();
|
||||||
|
void exprSlice0();
|
||||||
|
void exprSlice1();
|
||||||
void exprSubscr();
|
void exprSubscr();
|
||||||
void exprLiteral0();
|
void exprLiteral0();
|
||||||
|
|
||||||
|
@ -71,8 +71,7 @@ struct Token{
|
|||||||
|
|
||||||
// https://docs.python.org/3/reference/expressions.html#operator-precedence
|
// https://docs.python.org/3/reference/expressions.html#operator-precedence
|
||||||
enum Precedence {
|
enum Precedence {
|
||||||
PREC_NONE,
|
PREC_LOWEST,
|
||||||
PREC_TUPLE, // ,
|
|
||||||
PREC_LAMBDA, // lambda
|
PREC_LAMBDA, // lambda
|
||||||
PREC_TERNARY, // ?:
|
PREC_TERNARY, // ?:
|
||||||
PREC_LOGICAL_OR, // or
|
PREC_LOGICAL_OR, // or
|
||||||
@ -93,7 +92,7 @@ enum Precedence {
|
|||||||
PREC_UNARY, // - not ~
|
PREC_UNARY, // - not ~
|
||||||
PREC_EXPONENT, // **
|
PREC_EXPONENT, // **
|
||||||
PREC_PRIMARY, // f() x[] a.b 1:2
|
PREC_PRIMARY, // f() x[] a.b 1:2
|
||||||
PREC_HIGHEST,pyth
|
PREC_HIGHEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StringType { NORMAL_STRING, RAW_STRING, F_STRING, NORMAL_BYTES };
|
enum StringType { NORMAL_STRING, RAW_STRING, F_STRING, NORMAL_BYTES };
|
||||||
|
@ -266,9 +266,6 @@ def long(*args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
# builtin exceptions
|
# builtin exceptions
|
||||||
class SyntaxError(Exception): pass
|
|
||||||
class IndentationError(SyntaxError): pass
|
|
||||||
|
|
||||||
class StackOverflowError(Exception): pass
|
class StackOverflowError(Exception): pass
|
||||||
class IOError(Exception): pass
|
class IOError(Exception): pass
|
||||||
class NotImplementedError(Exception): pass
|
class NotImplementedError(Exception): pass
|
||||||
|
172
src/compiler.cpp
172
src/compiler.cpp
@ -72,7 +72,7 @@ namespace pkpy{
|
|||||||
count += 1;
|
count += 1;
|
||||||
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
// http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
|
||||||
#define PK_METHOD(name) &Compiler::name
|
#define PK_METHOD(name) &Compiler::name
|
||||||
#define PK_NO_INFIX nullptr, PREC_NONE
|
#define PK_NO_INFIX nullptr, PREC_LOWEST
|
||||||
for(TokenIndex i=0; i<kTokenCount; i++) rules[i] = { nullptr, PK_NO_INFIX };
|
for(TokenIndex i=0; i<kTokenCount; i++) rules[i] = { nullptr, PK_NO_INFIX };
|
||||||
rules[TK(".")] = { nullptr, PK_METHOD(exprAttrib), PREC_PRIMARY };
|
rules[TK(".")] = { nullptr, PK_METHOD(exprAttrib), PREC_PRIMARY };
|
||||||
rules[TK("(")] = { PK_METHOD(exprGroup), PK_METHOD(exprCall), PREC_PRIMARY };
|
rules[TK("(")] = { PK_METHOD(exprGroup), PK_METHOD(exprCall), PREC_PRIMARY };
|
||||||
@ -101,7 +101,6 @@ namespace pkpy{
|
|||||||
rules[TK("^")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_BITWISE_XOR };
|
rules[TK("^")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_BITWISE_XOR };
|
||||||
rules[TK("@")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_FACTOR };
|
rules[TK("@")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_FACTOR };
|
||||||
rules[TK("if")] = { nullptr, PK_METHOD(exprTernary), PREC_TERNARY };
|
rules[TK("if")] = { nullptr, PK_METHOD(exprTernary), PREC_TERNARY };
|
||||||
rules[TK(",")] = { nullptr, PK_METHOD(exprTuple), PREC_TUPLE };
|
|
||||||
rules[TK("not in")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("not in")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("is not")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_COMPARISION };
|
rules[TK("is not")] = { nullptr, PK_METHOD(exprBinaryOp), PREC_COMPARISION };
|
||||||
rules[TK("and") ] = { nullptr, PK_METHOD(exprAnd), PREC_LOGICAL_AND };
|
rules[TK("and") ] = { nullptr, PK_METHOD(exprAnd), PREC_LOGICAL_AND };
|
||||||
@ -119,6 +118,8 @@ namespace pkpy{
|
|||||||
rules[TK("@long")] = { PK_METHOD(exprLong), PK_NO_INFIX };
|
rules[TK("@long")] = { PK_METHOD(exprLong), PK_NO_INFIX };
|
||||||
rules[TK("@imag")] = { PK_METHOD(exprImag), PK_NO_INFIX };
|
rules[TK("@imag")] = { PK_METHOD(exprImag), PK_NO_INFIX };
|
||||||
rules[TK("@bytes")] = { PK_METHOD(exprBytes), PK_NO_INFIX };
|
rules[TK("@bytes")] = { PK_METHOD(exprBytes), PK_NO_INFIX };
|
||||||
|
rules[TK(":")] = { PK_METHOD(exprSlice0), PK_METHOD(exprSlice1), PREC_PRIMARY };
|
||||||
|
|
||||||
#undef PK_METHOD
|
#undef PK_METHOD
|
||||||
#undef PK_NO_INFIX
|
#undef PK_NO_INFIX
|
||||||
}
|
}
|
||||||
@ -164,12 +165,23 @@ namespace pkpy{
|
|||||||
if (!match_end_stmt()) SyntaxError("expected statement end");
|
if (!match_end_stmt()) SyntaxError("expected statement end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::EXPR(bool push_stack) {
|
void Compiler::EXPR() {
|
||||||
parse_expression(PREC_TUPLE+1, push_stack);
|
parse_expression(PREC_LOWEST+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::EXPR_TUPLE(bool push_stack) {
|
void Compiler::EXPR_TUPLE() {
|
||||||
parse_expression(PREC_TUPLE, push_stack);
|
EXPR();
|
||||||
|
if(!match(TK(","))) return;
|
||||||
|
// tuple expression
|
||||||
|
std::vector<Expr_> items;
|
||||||
|
items.push_back(ctx()->s_expr.popx());
|
||||||
|
do {
|
||||||
|
if(curr().brackets_level) match_newlines_repl();
|
||||||
|
if(!is_expression()) break;
|
||||||
|
EXPR(); items.push_back(ctx()->s_expr.popx());
|
||||||
|
if(curr().brackets_level) match_newlines_repl();
|
||||||
|
} while(match(TK(",")));
|
||||||
|
ctx()->s_expr.push(make_expr<TupleExpr>(std::move(items)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case for `for loop` and `comp`
|
// special case for `for loop` and `comp`
|
||||||
@ -217,21 +229,6 @@ namespace pkpy{
|
|||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::exprTuple(){
|
|
||||||
std::vector<Expr_> items;
|
|
||||||
items.push_back(ctx()->s_expr.popx());
|
|
||||||
do {
|
|
||||||
if(curr().brackets_level) match_newlines_repl();
|
|
||||||
if(!is_expression()) break;
|
|
||||||
EXPR();
|
|
||||||
items.push_back(ctx()->s_expr.popx());
|
|
||||||
if(curr().brackets_level) match_newlines_repl();
|
|
||||||
} while(match(TK(",")));
|
|
||||||
ctx()->s_expr.push(make_expr<TupleExpr>(
|
|
||||||
std::move(items)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Compiler::exprOr(){
|
void Compiler::exprOr(){
|
||||||
auto e = make_expr<OrExpr>();
|
auto e = make_expr<OrExpr>();
|
||||||
e->lhs = ctx()->s_expr.popx();
|
e->lhs = ctx()->s_expr.popx();
|
||||||
@ -419,71 +416,41 @@ namespace pkpy{
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Compiler::exprSlice0() {
|
||||||
|
auto slice = make_expr<SliceExpr>();
|
||||||
|
if(is_expression()){ // :<expr>
|
||||||
|
EXPR();
|
||||||
|
slice->stop = ctx()->s_expr.popx();
|
||||||
|
// try optional step
|
||||||
|
if(match(TK(":"))){
|
||||||
|
EXPR();
|
||||||
|
slice->step = ctx()->s_expr.popx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx()->s_expr.push(std::move(slice));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compiler::exprSlice1() {
|
||||||
|
auto slice = make_expr<SliceExpr>();
|
||||||
|
slice->start = ctx()->s_expr.popx();
|
||||||
|
if(is_expression()){ // <expr>:<expr>
|
||||||
|
EXPR();
|
||||||
|
slice->stop = ctx()->s_expr.popx();
|
||||||
|
// try optional step
|
||||||
|
if(match(TK(":"))){
|
||||||
|
EXPR();
|
||||||
|
slice->step = ctx()->s_expr.popx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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[...]
|
e->a = ctx()->s_expr.popx(); // a[...]
|
||||||
auto slice = make_expr<SliceExpr>();
|
EXPR_TUPLE(); // a[<expr>]
|
||||||
bool is_slice = false;
|
e->b = ctx()->s_expr.popx();
|
||||||
// a[<0> <state:1> : state<3> : state<5>]
|
consume(TK("]"));
|
||||||
int state = 0;
|
|
||||||
do{
|
|
||||||
match_newlines_repl();
|
|
||||||
switch(state){
|
|
||||||
case 0:
|
|
||||||
if(match(TK(":"))){
|
|
||||||
is_slice=true;
|
|
||||||
state=2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(match(TK("]"))) SyntaxError();
|
|
||||||
EXPR_TUPLE();
|
|
||||||
slice->start = ctx()->s_expr.popx();
|
|
||||||
state=1;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if(match(TK(":"))){
|
|
||||||
is_slice=true;
|
|
||||||
state=2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(match(TK("]"))) goto __SUBSCR_END;
|
|
||||||
SyntaxError("expected ':' or ']'");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if(match(TK(":"))){
|
|
||||||
state=4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(match(TK("]"))) goto __SUBSCR_END;
|
|
||||||
EXPR_TUPLE();
|
|
||||||
slice->stop = ctx()->s_expr.popx();
|
|
||||||
state=3;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
if(match(TK(":"))){
|
|
||||||
state=4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(match(TK("]"))) goto __SUBSCR_END;
|
|
||||||
SyntaxError("expected ':' or ']'");
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
if(match(TK("]"))) goto __SUBSCR_END;
|
|
||||||
EXPR_TUPLE();
|
|
||||||
slice->step = ctx()->s_expr.popx();
|
|
||||||
state=5;
|
|
||||||
break;
|
|
||||||
case 5: consume(TK("]")); goto __SUBSCR_END;
|
|
||||||
}
|
|
||||||
match_newlines_repl();
|
|
||||||
}while(true);
|
|
||||||
__SUBSCR_END:
|
|
||||||
if(is_slice){
|
|
||||||
e->b = std::move(slice);
|
|
||||||
}else{
|
|
||||||
PK_ASSERT(state == 1)
|
|
||||||
e->b = std::move(slice->start);
|
|
||||||
}
|
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,15 +563,18 @@ __EAT_DOTS_END:
|
|||||||
|
|
||||||
bool Compiler::is_expression(){
|
bool Compiler::is_expression(){
|
||||||
PrattCallback prefix = rules[curr().type].prefix;
|
PrattCallback prefix = rules[curr().type].prefix;
|
||||||
return prefix != nullptr;
|
// slice expression is restricted to be used in subscript
|
||||||
|
return prefix != nullptr && curr().type != TK(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::parse_expression(int precedence, bool push_stack) {
|
void Compiler::parse_expression(int precedence, bool push_stack) {
|
||||||
PrattCallback prefix = rules[curr().type].prefix;
|
PrattCallback prefix = rules[curr().type].prefix;
|
||||||
if (prefix == nullptr) SyntaxError(Str("expected an expression, got ") + TK_STR(curr().type));
|
if (prefix == nullptr || curr().type == TK(":")){
|
||||||
|
SyntaxError(Str("expected an expression, got ") + TK_STR(curr().type));
|
||||||
|
}
|
||||||
advance();
|
advance();
|
||||||
(this->*prefix)();
|
(this->*prefix)();
|
||||||
while (rules[curr().type].precedence >= precedence) {
|
while (rules[curr().type].precedence >= precedence && curr().type != TK(":")) {
|
||||||
TokenIndex op = curr().type;
|
TokenIndex op = curr().type;
|
||||||
advance();
|
advance();
|
||||||
PrattCallback infix = rules[op].infix;
|
PrattCallback infix = rules[op].infix;
|
||||||
@ -615,7 +585,8 @@ __EAT_DOTS_END:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::compile_if_stmt() {
|
void Compiler::compile_if_stmt() {
|
||||||
EXPR(false); // condition
|
EXPR(); // condition
|
||||||
|
ctx()->emit_expr();
|
||||||
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"))) {
|
||||||
@ -635,7 +606,8 @@ __EAT_DOTS_END:
|
|||||||
|
|
||||||
void Compiler::compile_while_loop() {
|
void Compiler::compile_while_loop() {
|
||||||
CodeBlock* block = ctx()->enter_block(CodeBlockType::WHILE_LOOP);
|
CodeBlock* block = ctx()->enter_block(CodeBlockType::WHILE_LOOP);
|
||||||
EXPR(false); // condition
|
EXPR(); // condition
|
||||||
|
ctx()->emit_expr();
|
||||||
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, ctx()->get_loop(), BC_KEEPLINE);
|
ctx()->emit_(OP_LOOP_CONTINUE, ctx()->get_loop(), BC_KEEPLINE);
|
||||||
@ -651,7 +623,7 @@ __EAT_DOTS_END:
|
|||||||
void Compiler::compile_for_loop() {
|
void Compiler::compile_for_loop() {
|
||||||
Expr_ vars = EXPR_VARS();
|
Expr_ vars = EXPR_VARS();
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
EXPR_TUPLE(false);
|
EXPR_TUPLE(); ctx()->emit_expr();
|
||||||
ctx()->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||||
CodeBlock* block = ctx()->enter_block(CodeBlockType::FOR_LOOP);
|
CodeBlock* block = ctx()->enter_block(CodeBlockType::FOR_LOOP);
|
||||||
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
|
||||||
@ -681,7 +653,8 @@ __EAT_DOTS_END:
|
|||||||
StrName as_name;
|
StrName as_name;
|
||||||
consume(TK("except"));
|
consume(TK("except"));
|
||||||
if(is_expression()){
|
if(is_expression()){
|
||||||
EXPR(false); // push assumed type on to the stack
|
EXPR(); // push assumed type on to the stack
|
||||||
|
ctx()->emit_expr();
|
||||||
ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
ctx()->emit_(OP_EXCEPTION_MATCH, BC_NOARG, prev().line);
|
||||||
if(match(TK("as"))){
|
if(match(TK("as"))){
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
@ -802,7 +775,7 @@ __EAT_DOTS_END:
|
|||||||
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(false);
|
EXPR_TUPLE(); ctx()->emit_expr();
|
||||||
// if yield present, mark the function as generator
|
// if yield present, mark the function as 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);
|
||||||
@ -810,7 +783,7 @@ __EAT_DOTS_END:
|
|||||||
break;
|
break;
|
||||||
case TK("yield from"):
|
case TK("yield from"):
|
||||||
if (contexts.size() <= 1) SyntaxError("'yield from' outside function");
|
if (contexts.size() <= 1) SyntaxError("'yield from' outside function");
|
||||||
EXPR_TUPLE(false);
|
EXPR_TUPLE(); ctx()->emit_expr();
|
||||||
// if yield from present, mark the function as generator
|
// if yield from present, mark the function as generator
|
||||||
ctx()->co->is_generator = true;
|
ctx()->co->is_generator = true;
|
||||||
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
|
ctx()->emit_(OP_GET_ITER, BC_NOARG, kw_line);
|
||||||
@ -826,7 +799,7 @@ __EAT_DOTS_END:
|
|||||||
if(match_end_stmt()){
|
if(match_end_stmt()){
|
||||||
ctx()->emit_(OP_RETURN_VALUE, 1, kw_line);
|
ctx()->emit_(OP_RETURN_VALUE, 1, kw_line);
|
||||||
}else{
|
}else{
|
||||||
EXPR_TUPLE(false);
|
EXPR_TUPLE(); ctx()->emit_expr();
|
||||||
// check if it is a generator
|
// check if it is a generator
|
||||||
if(ctx()->co->is_generator) SyntaxError("'return' with argument inside generator function");
|
if(ctx()->co->is_generator) SyntaxError("'return' with argument inside generator function");
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
@ -878,11 +851,13 @@ __EAT_DOTS_END:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TK("assert"):{
|
case TK("assert"):{
|
||||||
EXPR(false); // condition
|
EXPR(); // condition
|
||||||
|
ctx()->emit_expr();
|
||||||
int index = ctx()->emit_(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
|
int index = ctx()->emit_(OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line);
|
||||||
int has_msg = 0;
|
int has_msg = 0;
|
||||||
if(match(TK(","))){
|
if(match(TK(","))){
|
||||||
EXPR(false); // message
|
EXPR(); // message
|
||||||
|
ctx()->emit_expr();
|
||||||
has_msg = 1;
|
has_msg = 1;
|
||||||
}
|
}
|
||||||
ctx()->emit_(OP_RAISE_ASSERT, has_msg, kw_line);
|
ctx()->emit_(OP_RAISE_ASSERT, has_msg, kw_line);
|
||||||
@ -898,7 +873,7 @@ __EAT_DOTS_END:
|
|||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
break;
|
||||||
case TK("raise"): {
|
case TK("raise"): {
|
||||||
EXPR(false);
|
EXPR(); ctx()->emit_expr();
|
||||||
ctx()->emit_(OP_RAISE, BC_NOARG, kw_line);
|
ctx()->emit_(OP_RAISE, BC_NOARG, kw_line);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
} break;
|
} break;
|
||||||
@ -910,7 +885,8 @@ __EAT_DOTS_END:
|
|||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
} break;
|
} break;
|
||||||
case TK("with"): {
|
case TK("with"): {
|
||||||
EXPR(false); // [ <expr> ]
|
EXPR(); // [ <expr> ]
|
||||||
|
ctx()->emit_expr();
|
||||||
ctx()->enter_block(CodeBlockType::CONTEXT_MANAGER);
|
ctx()->enter_block(CodeBlockType::CONTEXT_MANAGER);
|
||||||
Expr_ as_name;
|
Expr_ as_name;
|
||||||
if(match(TK("as"))){
|
if(match(TK("as"))){
|
||||||
@ -1197,7 +1173,7 @@ __EAT_DOTS_END:
|
|||||||
match_newlines(); // skip possible leading '\n'
|
match_newlines(); // skip possible leading '\n'
|
||||||
|
|
||||||
if(mode()==EVAL_MODE) {
|
if(mode()==EVAL_MODE) {
|
||||||
EXPR_TUPLE(false);
|
EXPR_TUPLE(); ctx()->emit_expr();
|
||||||
consume(TK("@eof"));
|
consume(TK("@eof"));
|
||||||
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
|
||||||
pop_context();
|
pop_context();
|
||||||
|
@ -709,6 +709,10 @@ void VM::init_builtin_types(){
|
|||||||
if(tp_staticmethod != _new_type_object("staticmethod")) exit(-3);
|
if(tp_staticmethod != _new_type_object("staticmethod")) exit(-3);
|
||||||
if(tp_classmethod != _new_type_object("classmethod")) exit(-3);
|
if(tp_classmethod != _new_type_object("classmethod")) exit(-3);
|
||||||
|
|
||||||
|
// SyntaxError and IndentationError must be created here
|
||||||
|
Type tp_syntax_error = _new_type_object("SyntaxError", tp_exception, true);
|
||||||
|
Type tp_indentation_error = _new_type_object("IndentationError", tp_syntax_error, true);
|
||||||
|
|
||||||
this->None = heap._new<Dummy>(_new_type_object("NoneType"));
|
this->None = heap._new<Dummy>(_new_type_object("NoneType"));
|
||||||
this->NotImplemented = heap._new<Dummy>(_new_type_object("NotImplementedType"));
|
this->NotImplemented = heap._new<Dummy>(_new_type_object("NotImplementedType"));
|
||||||
this->Ellipsis = heap._new<Dummy>(_new_type_object("ellipsis"));
|
this->Ellipsis = heap._new<Dummy>(_new_type_object("ellipsis"));
|
||||||
@ -735,6 +739,8 @@ void VM::init_builtin_types(){
|
|||||||
builtins->attr().set("NotImplemented", NotImplemented);
|
builtins->attr().set("NotImplemented", NotImplemented);
|
||||||
builtins->attr().set("slice", _t(tp_slice));
|
builtins->attr().set("slice", _t(tp_slice));
|
||||||
builtins->attr().set("Exception", _t(tp_exception));
|
builtins->attr().set("Exception", _t(tp_exception));
|
||||||
|
builtins->attr().set("SyntaxError", _t(tp_syntax_error));
|
||||||
|
builtins->attr().set("IndentationError", _t(tp_indentation_error));
|
||||||
|
|
||||||
post_init();
|
post_init();
|
||||||
this->_main = new_module("__main__");
|
this->_main = new_module("__main__");
|
||||||
@ -1164,7 +1170,7 @@ PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Native
|
|||||||
CodeObject_ co;
|
CodeObject_ co;
|
||||||
try{
|
try{
|
||||||
// fn(a, b, *c, d=1) -> None
|
// fn(a, b, *c, d=1) -> None
|
||||||
co = compile("def " + Str(sig) + " : pass", "<bind>", EXEC_MODE);
|
co = compile(fmt("def ", sig, " : pass"), "<bind>", EXEC_MODE);
|
||||||
}catch(const Exception&){
|
}catch(const Exception&){
|
||||||
throw std::runtime_error("invalid signature: " + std::string(sig));
|
throw std::runtime_error("invalid signature: " + std::string(sig));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user