mirror of https://github.com/exaloop/codon.git
Fix #250 (raise ... from)
parent
543068d903
commit
48c848cf52
|
@ -391,13 +391,14 @@ std::string TryStmt::toString(int indent) const {
|
|||
: "");
|
||||
}
|
||||
|
||||
ThrowStmt::ThrowStmt(Expr *expr, bool transformed)
|
||||
: AcceptorExtend(), expr(expr), transformed(transformed) {}
|
||||
ThrowStmt::ThrowStmt(Expr *expr, Expr *from, bool transformed)
|
||||
: AcceptorExtend(), expr(expr), from(from), transformed(transformed) {}
|
||||
ThrowStmt::ThrowStmt(const ThrowStmt &stmt, bool clean)
|
||||
: AcceptorExtend(stmt, clean), expr(ast::clone(stmt.expr, clean)),
|
||||
transformed(stmt.transformed) {}
|
||||
from(ast::clone(stmt.from, clean)), transformed(stmt.transformed) {}
|
||||
std::string ThrowStmt::toString(int indent) const {
|
||||
return format("(throw{})", expr ? " " + expr->toString(indent) : "");
|
||||
return format("(throw{}{})", expr ? " " + expr->toString(indent) : "",
|
||||
from ? format(" :from {}", from->toString(indent)) : "");
|
||||
}
|
||||
|
||||
GlobalStmt::GlobalStmt(std::string var, bool nonLocal)
|
||||
|
|
|
@ -439,16 +439,19 @@ private:
|
|||
/// Throw statement (raise expr).
|
||||
/// @li: raise a
|
||||
struct ThrowStmt : public AcceptorExtend<ThrowStmt, Stmt> {
|
||||
explicit ThrowStmt(Expr *expr = nullptr, bool transformed = false);
|
||||
explicit ThrowStmt(Expr *expr = nullptr, Expr *from = nullptr,
|
||||
bool transformed = false);
|
||||
ThrowStmt(const ThrowStmt &, bool);
|
||||
|
||||
Expr *getExpr() const { return expr; }
|
||||
Expr *getFrom() const { return from; }
|
||||
bool isTransformed() const { return transformed; }
|
||||
|
||||
ACCEPT(ThrowStmt, ASTVisitor, expr, transformed);
|
||||
ACCEPT(ThrowStmt, ASTVisitor, expr, from, transformed);
|
||||
|
||||
private:
|
||||
Expr *expr;
|
||||
Expr *from;
|
||||
// True if a statement was transformed during type-checking stage
|
||||
// (to avoid setting up ExcHeader multiple times).
|
||||
bool transformed;
|
||||
|
|
|
@ -138,10 +138,11 @@ del_stmt <- 'del' SPACE tlist(',', expression) {
|
|||
return_stmt <- 'return' (SPACE expressions)? {
|
||||
return asts(Return, LOC, !VS.empty() ? ac_expr(V0) : nullptr);
|
||||
}
|
||||
# TODO: raise expression 'from' expression
|
||||
raise_stmt <- 'raise' (SPACE expression)? {
|
||||
return asts(Throw, LOC, !VS.empty() ? ac_expr(V0) : nullptr);
|
||||
}
|
||||
raise_stmt <-
|
||||
/ 'raise' SPACE expression (SPACE 'from' SPACE expression)? {
|
||||
return asts(Throw, LOC, ac_expr(V0), VS.size() > 1 ? ac_expr(V1) : nullptr);
|
||||
}
|
||||
/ 'raise' { return asts(Throw, LOC, nullptr); }
|
||||
print_stmt <-
|
||||
/ 'print' SPACE star_expression (_ ',' _ star_expression)* (_ <','>)? {
|
||||
return asts(Print, LOC, VS.transform<Expr*>(), !VS.tokens.empty());
|
||||
|
@ -448,7 +449,7 @@ custom_small_stmt__PREDICATE {
|
|||
expressions <- tlist(',', expression) { return wrap_tuple(CTX, VS, LOC); }
|
||||
expression <-
|
||||
/ lambdef { return ac_expr(V0); }
|
||||
/ disjunction SPACE 'if' SPACE disjunction SPACE 'else' SPACE expression {
|
||||
/ disjunction SPACE? 'if' SPACE? disjunction SPACE? 'else' SPACE? expression {
|
||||
return aste(If, LOC, ac_expr(V1), ac_expr(V0), ac_expr(V2));
|
||||
}
|
||||
/ pipe { return ac_expr(V0); }
|
||||
|
@ -471,7 +472,7 @@ pipe <-
|
|||
}
|
||||
/ disjunction { return ac_expr(V0); }
|
||||
disjunction <-
|
||||
/ conjunction (SPACE 'or' SPACE conjunction)+ {
|
||||
/ conjunction (SPACE? 'or' SPACE? conjunction)+ {
|
||||
auto b = aste(Binary, LOC, ac_expr(V0), "||", ac_expr(V1));
|
||||
for (int i = 2; i < VS.size(); i++)
|
||||
b = aste(Binary, LOC, b, "||", ac_expr(VS[i]));
|
||||
|
@ -479,7 +480,7 @@ disjunction <-
|
|||
}
|
||||
/ conjunction { return ac_expr(V0); }
|
||||
conjunction <-
|
||||
/ inversion (SPACE 'and' SPACE inversion)+ {
|
||||
/ inversion (SPACE? 'and' SPACE? inversion)+ {
|
||||
auto b = aste(Binary, LOC, ac_expr(V0), "&&", ac_expr(V1));
|
||||
for (int i = 2; i < VS.size(); i++)
|
||||
b = aste(Binary, LOC, b, "&&", ac_expr(VS[i]));
|
||||
|
@ -636,7 +637,7 @@ for_if_clauses <- for_if_clause (SPACE for_if_clause)* {
|
|||
return v;
|
||||
}
|
||||
for_if_clause <- 'for' SPACE star_targets SPACE 'in' SPACE disjunction
|
||||
(SPACE 'if' SPACE disjunction)* {
|
||||
(SPACE? 'if' SPACE? disjunction)* {
|
||||
std::vector<Stmt*> v{asts(For, LOC, ac_expr(V0), ac_expr(V1), nullptr)};
|
||||
auto tail = VS.transform<Expr*>(2);
|
||||
for (auto &t: tail)
|
||||
|
|
|
@ -347,7 +347,10 @@ void FormatVisitor::visit(GlobalStmt *stmt) {
|
|||
}
|
||||
|
||||
void FormatVisitor::visit(ThrowStmt *stmt) {
|
||||
result = fmt::format("{} {}", keyword("raise"), transform(stmt->getExpr()));
|
||||
result = fmt::format("{} {}{}", keyword("raise"), transform(stmt->getExpr()),
|
||||
stmt->getFrom() ? fmt::format(" {} {}", keyword("from"),
|
||||
transform(stmt->getFrom()))
|
||||
: "");
|
||||
}
|
||||
|
||||
void FormatVisitor::visit(FunctionStmt *fstmt) {
|
||||
|
|
|
@ -158,7 +158,12 @@ void TypecheckVisitor::visit(ThrowStmt *stmt) {
|
|||
stmt->expr = transform(N<CallExpr>(
|
||||
N<IdExpr>("__internal__.set_header:0"), stmt->getExpr(),
|
||||
N<StringExpr>(ctx->getBase()->name), N<StringExpr>(stmt->getSrcInfo().file),
|
||||
N<IntExpr>(stmt->getSrcInfo().line), N<IntExpr>(stmt->getSrcInfo().col)));
|
||||
N<IntExpr>(stmt->getSrcInfo().line), N<IntExpr>(stmt->getSrcInfo().col),
|
||||
stmt->getFrom()
|
||||
? (Expr *)N<CallExpr>(N<DotExpr>(N<IdExpr>("__internal__"), "class_super"),
|
||||
stmt->getFrom(),
|
||||
N<IdExpr>("std.internal.types.error.BaseException.0"))
|
||||
: N<CallExpr>(N<IdExpr>("NoneType"))));
|
||||
}
|
||||
if (stmt->getExpr()->isDone())
|
||||
stmt->setDone();
|
||||
|
|
|
@ -296,7 +296,10 @@ public:
|
|||
transform(stmt->suite);
|
||||
}
|
||||
void visit(GlobalStmt *stmt) override {}
|
||||
void visit(ThrowStmt *stmt) override { transform(stmt->expr); }
|
||||
void visit(ThrowStmt *stmt) override {
|
||||
transform(stmt->expr);
|
||||
transform(stmt->from);
|
||||
}
|
||||
void visit(FunctionStmt *stmt) override {
|
||||
transform(stmt->ret);
|
||||
for (auto &a : stmt->items) {
|
||||
|
@ -486,7 +489,10 @@ public:
|
|||
stmt->suite = SuiteStmt::wrap(transform(stmt->suite));
|
||||
}
|
||||
void visit(GlobalStmt *stmt) override {}
|
||||
void visit(ThrowStmt *stmt) override { stmt->expr = transform(stmt->expr); }
|
||||
void visit(ThrowStmt *stmt) override {
|
||||
stmt->expr = transform(stmt->expr);
|
||||
stmt->from = transform(stmt->from);
|
||||
}
|
||||
void visit(FunctionStmt *stmt) override {
|
||||
stmt->ret = transform(stmt->ret);
|
||||
for (auto &a : stmt->items) {
|
||||
|
|
|
@ -157,6 +157,7 @@ struct SeqExcHeader_t {
|
|||
seq_int_t line;
|
||||
seq_int_t col;
|
||||
void *python_type;
|
||||
void *cause;
|
||||
};
|
||||
|
||||
void seq_exc_init(int flags) {
|
||||
|
|
|
@ -486,7 +486,7 @@ class __internal__:
|
|||
raise NameError(f"name '{s}' is not defined")
|
||||
|
||||
@__hidden__
|
||||
def set_header(e, func, file, line, col):
|
||||
def set_header(e, func, file, line, col, cause):
|
||||
if not isinstance(e, BaseException):
|
||||
compile_error("exceptions must derive from BaseException")
|
||||
|
||||
|
@ -494,6 +494,8 @@ class __internal__:
|
|||
e.file = file
|
||||
e.line = line
|
||||
e.col = col
|
||||
if cause is not None:
|
||||
e.cause = cause
|
||||
return e
|
||||
|
||||
def kwargs_get(kw, key: Static[str], default):
|
||||
|
|
|
@ -11,6 +11,7 @@ class BaseException:
|
|||
line: int
|
||||
col: int
|
||||
python_type: cobj
|
||||
cause: Optional[BaseException]
|
||||
|
||||
def __init__(self, typename: str, message: str = ""):
|
||||
self.typename = typename
|
||||
|
@ -20,6 +21,7 @@ class BaseException:
|
|||
self.line = 0
|
||||
self.col = 0
|
||||
self.python_type = BaseException._pytype
|
||||
self.cause = __internal__.opt_ref_new(T=BaseException)
|
||||
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
@ -27,6 +29,10 @@ class BaseException:
|
|||
def __repr__(self):
|
||||
return f'{self.typename}({self.message.__repr__()})'
|
||||
|
||||
@property
|
||||
def __cause__(self):
|
||||
return self.cause
|
||||
|
||||
class Exception(Static[BaseException]):
|
||||
_pytype: ClassVar[cobj] = cobj()
|
||||
def __init__(self, typename: str, msg: str = ""):
|
||||
|
|
|
@ -93,4 +93,4 @@ optional = Optional
|
|||
def unwrap(opt: Optional[T], T: type) -> T:
|
||||
if opt.__has__():
|
||||
return opt.__val__()
|
||||
raise ValueError("optional is None")
|
||||
raise ValueError(f"optional unpack failed: expected {T.__class__.__name__}, got None")
|
||||
|
|
|
@ -44,3 +44,31 @@ except MyError as e:
|
|||
raise 'hello'
|
||||
#! exceptions must derive from BaseException
|
||||
|
||||
#%% raise_from,barebones
|
||||
def foo(bar):
|
||||
try:
|
||||
bar()
|
||||
except ValueError as e:
|
||||
raise RuntimeError("oops") from e
|
||||
raise RuntimeError("oops")
|
||||
|
||||
def bar1():
|
||||
raise ValueError("bar1")
|
||||
try:
|
||||
foo(bar1)
|
||||
except RuntimeError as e:
|
||||
print(e.message, e.__cause__) #: oops bar1
|
||||
|
||||
def bar2():
|
||||
raise ValueError("bar2")
|
||||
try:
|
||||
foo(bar2)
|
||||
except RuntimeError as e:
|
||||
print(e.message, e.__cause__) #: oops bar2
|
||||
|
||||
def bar3():
|
||||
pass
|
||||
try:
|
||||
foo(bar3)
|
||||
except RuntimeError as e:
|
||||
print(e.message, e.__cause__) #: oops None
|
|
@ -230,7 +230,7 @@ Optional(5) |> foo2 #: 5
|
|||
try:
|
||||
Optional[int]() |> foo2
|
||||
except ValueError as e:
|
||||
print e.message #: optional is None
|
||||
print e.message #: optional unpack failed: expected int, got None
|
||||
|
||||
#%% pipe_prepend_error,barebones
|
||||
def foo2(a: int):
|
||||
|
|
|
@ -11,3 +11,19 @@ def foo(return_, pass_, yield_, break_, continue_, print_, assert_):
|
|||
print foo([1], [1], [1], [1], [1], [1], [1])
|
||||
#: ([1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7])
|
||||
|
||||
#%% spaces,barebones
|
||||
def space_test():
|
||||
x = 0.77
|
||||
y = 0.86
|
||||
z = x/(1if((1if(y==0)else(y))==0)else((1if(y==0)else(y))))
|
||||
print(z) #: 0.895349
|
||||
|
||||
h = "hello"
|
||||
b = ((True)or(False))or((("sR2Kt7"))==(h))
|
||||
print(b) #: True
|
||||
|
||||
h2: Optional[str] = "hi"
|
||||
h3 = "r"
|
||||
b2 = (((h2)==None)and(h3)==("r"))
|
||||
print(b2) #: False
|
||||
space_test()
|
Loading…
Reference in New Issue