Skip to content

Commit 3319b5a

Browse files
committed
jule: add exceptional forwarding operator
1 parent 93f656d commit 3319b5a

File tree

6 files changed

+50
-14
lines changed

6 files changed

+50
-14
lines changed

std/jule/ast/node.jule

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ struct BinaryExpr {
196196
Op: &token::Token // Operator.
197197
}
198198

199+
// Special exceptional handler scopes.
200+
let mut Ignored = new(ScopeTree) // Exception is ignored, like foo()!
201+
let mut Forwarded = new(ScopeTree) // Exception is forwarded, like foo()?
202+
199203
// Function call expression kind.
200204
struct CallExpr {
201205
Token: &token::Token
@@ -210,13 +214,6 @@ impl CallExpr {
210214
fn Unhandled(self): bool {
211215
ret self.Exception == nil
212216
}
213-
214-
// Reports whether exception is ignored.
215-
fn Ignored(self): bool {
216-
// Report true if the Unsafe field is true.
217-
// Unsafe field used mark for exception ignored calls like: x()!
218-
ret self.Exception != nil && self.Exception.Unsafe
219-
}
220217
}
221218

222219
// Typed brace instantiating expression.

std/jule/parser/expr.jule

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,13 +1045,26 @@ impl exprBuilder {
10451045
self.pushErr(t, "trailing not operator expects a function call")
10461046
break
10471047
}
1048-
if f.Ignored() {
1048+
if f.Exception == ast::Ignored {
10491049
self.pushErr(t, "function call already ignores the exceptional")
10501050
break
10511051
}
1052-
f.Exception = &ast::ScopeTree{
1053-
Unsafe: true,
1052+
f.Exception = ast::Ignored
1053+
| token::QMARK:
1054+
t := self.t
1055+
self.next()
1056+
// Trailing question-mark operator.
1057+
// It should be call expression to an exceptional function.
1058+
mut f, isFunc := ast::Unparen(x).Data.(&ast::CallExpr)
1059+
if !isFunc {
1060+
self.pushErr(t, "trailing question-mark operator expects a function call")
1061+
break
1062+
}
1063+
if f.Exception == ast::Forwarded {
1064+
self.pushErr(t, "function call already forwards the exceptional")
1065+
break
10541066
}
1067+
f.Exception = ast::Forwarded
10551068
| token::ELSE:
10561069
t := self.t
10571070
self.next()

std/jule/sema/eval.jule

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2229,9 +2229,31 @@ impl eval {
22292229
| fc.Unhandled():
22302230
self.pushErr(fc.Token, log::UnhandledExceptional)
22312231
self.pushSuggestion(log::HandleExceptional)
2232-
| fc.Ignored():
2233-
// Ok.
2234-
break
2232+
| fc.Exception == ast::Ignored:
2233+
model.Except = nil
2234+
| fc.Exception == ast::Forwarded:
2235+
mut s, (ok) := self.lookup.(&scopeChecker)
2236+
if ok {
2237+
if s.isDeferred() {
2238+
self.s.pushErr(fc.Token, "function call forwards exception in a deferred scope")
2239+
} else {
2240+
mut root := s.getRoot()
2241+
if root.owner.Decl.Exceptional {
2242+
model.Except = s.getChild()
2243+
mut ec := buildVoidValue()
2244+
ec.Model = &BuiltinErrorCallExpr{
2245+
Func: root.owner,
2246+
Err: &Value{
2247+
Model: self.evalVar(buildErrorVar(model.Except, fc), fc.Token).Model,
2248+
},
2249+
}
2250+
model.Except.Stmts = append(model.Except.Stmts, ec)
2251+
break
2252+
}
2253+
}
2254+
}
2255+
self.s.pushErr(fc.Token, "function call forwards exceptional in non-exceptional scope")
2256+
self.s.pushSuggestion("make the function exceptional to forward")
22352257
|:
22362258
// Handled with scope.
22372259
self.processExceptionalHandler(f, fc, v)

std/jule/sema/model.jule

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ struct FuncCallExpr {
111111
IsCo: bool
112112
Expr: Expr
113113
Args: []Expr
114-
Except: &Scope
114+
Except: &Scope // Nil for ignored.
115115
Assigned: bool
116116
}
117117

std/jule/token/scan.jule

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,9 @@ impl Scanner {
596596
token.ID = COLON
597597
token.Kind = ":"
598598
}
599+
| '?':
600+
token.ID = QMARK
601+
token.Kind = "?"
599602
| ';':
600603
token.ID = SEMICOLON
601604
token.Kind = ";"

std/jule/token/token.jule

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
SEP // ::
1616
HASH // #
1717
ELLIPSIS // ...
18+
QMARK // ?
1819

1920
COMMENT // /*..*/ or //...
2021
NAME // identifier

0 commit comments

Comments
 (0)