|
1 | 1 | package org.piccode.ast; |
2 | 2 |
|
3 | 3 | import com.github.tomaslanger.chalk.Chalk; |
4 | | -import org.piccode.piccodescript.Piccode; |
| 4 | +import java.util.ArrayList; |
| 5 | +import java.util.function.Function; |
5 | 6 | import org.piccode.piccodescript.TargetEnvironment; |
| 7 | +import org.piccode.rt.Context; |
6 | 8 | import org.piccode.rt.PiccodeBoolean; |
7 | 9 | import org.piccode.rt.PiccodeException; |
8 | 10 | import org.piccode.rt.PiccodeNumber; |
| 11 | +import org.piccode.rt.PiccodeReturnException; |
9 | 12 | import org.piccode.rt.PiccodeString; |
| 13 | +import org.piccode.rt.PiccodeTuple; |
| 14 | +import org.piccode.rt.PiccodeUnit; |
10 | 15 | import org.piccode.rt.PiccodeValue; |
11 | 16 |
|
12 | 17 | /** |
13 | 18 | * |
14 | 19 | * @author hexaredecimal |
15 | 20 | */ |
16 | | -public class BinOpAst extends Ast { |
| 21 | +public class CatchAst extends Ast { |
17 | 22 |
|
18 | 23 | public Ast lhs; |
19 | | - public String op; |
20 | 24 | public Ast rhs; |
21 | 25 |
|
22 | | - public BinOpAst(Ast lhs, String op, Ast rhs) { |
| 26 | + public CatchAst(Ast lhs, Ast rhs) { |
23 | 27 | this.lhs = lhs; |
24 | | - this.op = op; |
25 | 28 | this.rhs = rhs; |
26 | 29 | } |
27 | 30 |
|
28 | 31 | @Override |
29 | 32 | public String toString() { |
30 | | - return lhs + " " + op + " " + rhs; |
| 33 | + return lhs + " catch " + rhs; |
31 | 34 | } |
32 | 35 |
|
33 | 36 | @Override |
34 | 37 | 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; |
75 | 53 | } |
76 | 54 |
|
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 | + } |
90 | 57 |
|
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 | + } |
94 | 83 | } |
95 | | - } |
96 | 84 |
|
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; |
100 | 98 | } |
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; |
116 | 99 | } |
117 | 100 |
|
118 | 101 | @Override |
119 | 102 | public String codeGen(TargetEnvironment target) { |
120 | | - return String.format("%s %s %s", lhs, op, rhs); |
| 103 | + return String.format("%s %s", lhs, rhs); |
121 | 104 | } |
122 | 105 | } |
0 commit comments