Skip to content

Commit 17d38c2

Browse files
committed
ast: Implement error handling using the catch keyword
1 parent 7074e47 commit 17d38c2

File tree

2 files changed

+78
-82
lines changed

2 files changed

+78
-82
lines changed
Lines changed: 65 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,105 @@
11
package org.piccode.ast;
22

33
import com.github.tomaslanger.chalk.Chalk;
4-
import org.piccode.piccodescript.Piccode;
4+
import java.util.ArrayList;
5+
import java.util.function.Function;
56
import org.piccode.piccodescript.TargetEnvironment;
7+
import org.piccode.rt.Context;
68
import org.piccode.rt.PiccodeBoolean;
79
import org.piccode.rt.PiccodeException;
810
import org.piccode.rt.PiccodeNumber;
11+
import org.piccode.rt.PiccodeReturnException;
912
import org.piccode.rt.PiccodeString;
13+
import org.piccode.rt.PiccodeTuple;
14+
import org.piccode.rt.PiccodeUnit;
1015
import org.piccode.rt.PiccodeValue;
1116

1217
/**
1318
*
1419
* @author hexaredecimal
1520
*/
16-
public class BinOpAst extends Ast {
21+
public class CatchAst extends Ast {
1722

1823
public Ast lhs;
19-
public String op;
2024
public Ast rhs;
2125

22-
public BinOpAst(Ast lhs, String op, Ast rhs) {
26+
public CatchAst(Ast lhs, Ast rhs) {
2327
this.lhs = lhs;
24-
this.op = op;
2528
this.rhs = rhs;
2629
}
2730

2831
@Override
2932
public String toString() {
30-
return lhs + " " + op + " " + rhs;
33+
return lhs + " catch " + rhs;
3134
}
3235

3336
@Override
3437
public PiccodeValue execute(Integer frame) {
35-
var left = lhs.execute(frame);
36-
var right = rhs.execute(frame);
37-
38-
if (left instanceof PiccodeNumber lf && right instanceof PiccodeNumber rh) {
39-
double result = 0;
40-
if (op.equals("+")) {
41-
result = (double) lf.raw() + (double) rh.raw();
42-
return new PiccodeNumber(String.valueOf(result));
43-
}
44-
if (op.equals("-")) {
45-
result = (double) lf.raw() - (double) rh.raw();
46-
return new PiccodeNumber(String.valueOf(result));
47-
}
48-
if (op.equals("*")) {
49-
result = (double) lf.raw() * (double) rh.raw();
50-
return new PiccodeNumber(String.valueOf(result));
51-
}
52-
if (op.equals("/")) {
53-
result = (double) lf.raw() / (double) rh.raw();
54-
return new PiccodeNumber(String.valueOf(result));
55-
}
56-
if (op.equals("%")) {
57-
result = (double) lf.raw() % (double) rh.raw();
58-
return new PiccodeNumber(String.valueOf(result));
59-
}
60-
61-
if (op.equals(">")) {
62-
return new PiccodeBoolean((double) lf.raw() > (double) rh.raw() ? "true" : "false");
63-
}
64-
65-
if (op.equals("<")) {
66-
return new PiccodeBoolean((double) lf.raw() < (double) rh.raw() ? "true" : "false");
67-
}
68-
69-
if (op.equals(">=")) {
70-
return new PiccodeBoolean((double) lf.raw() >= (double) rh.raw() ? "true" : "false");
71-
}
72-
73-
if (op.equals("<=")) {
74-
return new PiccodeBoolean((double) lf.raw() <= (double) rh.raw() ? "true" : "false");
38+
var ctx = frame == null
39+
? Context.top
40+
: Context.getContextAt(frame);
41+
42+
return executeOnElse(frame, lhs, (node) -> {
43+
try {
44+
var result = node.execute(frame);
45+
ctx.dropScope();
46+
return result;
47+
} catch (PiccodeReturnException ret) {
48+
ctx.dropScope();
49+
return ret.value;
50+
} catch (Exception e1) {
51+
ctx.dropScope();
52+
throw e1;
7553
}
7654

77-
if (op.equals("<<")) {
78-
result = ((int) (double)lf.raw()) << ((int) (double)rh.raw());
79-
return new PiccodeNumber(String.valueOf(result));
80-
}
81-
if (op.equals(">>")) {
82-
result = ((int) (double)lf.raw()) >> ((int) (double)rh.raw());
83-
return new PiccodeNumber(String.valueOf(result));
84-
}
85-
86-
if (op.equals("|")) {
87-
result = ((int) (double)lf.raw()) | ((int) (double)rh.raw());
88-
return new PiccodeNumber(String.valueOf(result));
89-
}
55+
});
56+
}
9057

91-
if (op.equals("&")) {
92-
result = ((int) (double)lf.raw()) & ((int) (double)rh.raw());
93-
return new PiccodeNumber(String.valueOf(result));
58+
private PiccodeValue executeOnElse(Integer frame, Ast node, Function<Ast, PiccodeValue> other) {
59+
try {
60+
var result = node.execute(frame);
61+
if (result instanceof PiccodeTuple tupl) {
62+
var last = tupl.nodes.getLast();
63+
if (!(last instanceof PiccodeUnit)) {
64+
var ctx = frame == null
65+
? Context.top
66+
: Context.getContextAt(frame);
67+
ctx.pushScope();
68+
ctx.putLocal("err", last);
69+
result = other.apply(rhs);
70+
return result;
71+
} else {
72+
var nodes = new ArrayList<PiccodeValue>();
73+
var size = tupl.nodes.size();
74+
for (var index = 0; index < size - 1; index++) {
75+
var _node = tupl.nodes.get(index);
76+
nodes.add(_node);
77+
}
78+
79+
return nodes.size() > 1 ?
80+
new PiccodeTuple(nodes)
81+
: nodes.getLast();
82+
}
9483
}
95-
}
9684

97-
if (op.equals("+")) {
98-
var result = String.format("%s%s", left.raw(), right.raw());
99-
return new PiccodeString(result);
85+
return result;
86+
} catch (PiccodeReturnException ret) {
87+
return ret.value;
88+
} catch (PiccodeException e) {
89+
throw e;
90+
} catch (Exception e) {
91+
var ctx = frame == null
92+
? Context.top
93+
: Context.getContextAt(frame);
94+
ctx.pushScope();
95+
ctx.putLocal("err", new PiccodeString(e.toString()));
96+
var result = other.apply(rhs);
97+
return result;
10098
}
101-
102-
if (op.equals("==")) {
103-
return new PiccodeBoolean(left.equals(right) ? "true" : "false");
104-
}
105-
106-
if (op.equals("!=")) {
107-
return new PiccodeBoolean(left.equals(right) ? "true" : "false");
108-
}
109-
110-
var err = new PiccodeException(file, line, column,"Operator `" + Chalk.on(op).blue() + "` cannot be used with types "
111-
+ Chalk.on(left.type()).red()
112-
+ " and " + Chalk.on(right.type()).red());
113-
114-
err.frame = frame;
115-
throw err;
11699
}
117100

118101
@Override
119102
public String codeGen(TargetEnvironment target) {
120-
return String.format("%s %s %s", lhs, op, rhs);
103+
return String.format("%s %s", lhs, rhs);
121104
}
122105
}

src/main/java/org/piccode/ast/PiccodeVisitor.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,12 @@ public Ast visitExpr(ExprContext expr) {
281281
return visitString(expr.STRING());
282282
}
283283

284+
if (expr.CATCH_TOK() != null) {
285+
var tok = expr.CATCH_TOK().getSymbol();
286+
var result = finalizeAstNode(visitCatch(expr), tok);
287+
return result;
288+
}
289+
284290
if (expr.ADD() != null) {
285291
var tok = expr.ADD().getSymbol();
286292
var result = finalizeAstNode(visitBinOp("+", expr), tok);
@@ -696,10 +702,17 @@ private Ast visitConsOperation(ExprContext expr) {
696702
return new ListConstAst(lhs, rhs);
697703
}
698704

705+
private Ast visitCatch(ExprContext expr) {
706+
var lhs = visitExpr(expr.expr().getFirst());
707+
var rhs = visitExpr(expr.expr().getLast());
708+
return new CatchAst(lhs, rhs);
709+
}
710+
699711
private Ast finalizeAstNode(Ast result, Token tok) {
700712
result.line = tok.getLine();
701713
result.column = tok.getCharPositionInLine();
702714
result.file = fileName;
703715
return result;
704716
}
717+
705718
}

0 commit comments

Comments
 (0)