-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDotOperationAst.java
More file actions
150 lines (125 loc) · 4.74 KB
/
DotOperationAst.java
File metadata and controls
150 lines (125 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package org.piccode.ast;
import com.github.tomaslanger.chalk.Chalk;
import java.util.concurrent.ExecutionException;
import org.piccode.piccodescript.TargetEnvironment;
import org.piccode.rt.Context;
import org.piccode.rt.PiccodeArray;
import org.piccode.rt.PiccodeException;
import org.piccode.rt.PiccodeModule;
import org.piccode.rt.PiccodeNumber;
import org.piccode.rt.PiccodeObject;
import org.piccode.rt.PiccodeSimpleNote;
import org.piccode.rt.PiccodeString;
import org.piccode.rt.PiccodeTuple;
import org.piccode.rt.PiccodeValue;
/**
*
* @author hexaredecimal
*/
public class DotOperationAst extends Ast {
public Ast lhs;
public Ast rhs;
public DotOperationAst(Ast lhs, Ast rhs) {
this.lhs = lhs;
this.rhs = rhs;
}
@Override
public String toString() {
return lhs + "." + rhs;
}
@Override
public PiccodeValue execute(Integer frame) {
if (lhs instanceof IdentifierAst id && Context.top.getValue(id.text) != null && Context.top.getValue(id.text) instanceof PiccodeModule) {
var err = new PiccodeException(file, line, column, "Cannot access the module `" + id.text + "` using dot. Please use `::` instead");
err.frame = frame;
throw err;
}
var left = lhs.execute(frame);
if (left instanceof PiccodeArray arr && rhs instanceof IdentifierAst id && id.text.equals("len")) {
return new PiccodeNumber("" + arr.array().length);
}
if (left instanceof PiccodeString str && rhs instanceof IdentifierAst id && id.text.equals("len")) {
return new PiccodeNumber("" + str.toString().length());
} else if (left instanceof PiccodeArray arr) {
return processArrayIndexing(arr.array(), rhs.execute(frame), frame);
} else if (left instanceof PiccodeTuple tupl) {
return processArrayIndexing(tupl.array(), rhs.execute(frame), frame);
}
if (!(left instanceof PiccodeObject)) {
var err = new PiccodeException(file, line, column, "Invalid expression on the side of `.` : " + lhs + " has value " + left + " which is not an object");
err.frame = frame;
err.addNote(new PiccodeSimpleNote("Pehaphs consider adding a check to verify if " + lhs + " is indeed an object."));
throw err;
}
var obj = (PiccodeObject) left;
String key = null;
if (rhs instanceof IdentifierAst id
&& id.text.equals("await")
&& obj.obj.containsKey("uuid")) {
var uuid = obj.obj.get("uuid").raw().toString();
var future = Context.getFuture(uuid);
if (future == null) {
var err = new PiccodeException(file, line, column, "Invalid reference to a future: " + Chalk.on(uuid).red());
err.frame = frame;
throw err;
}
try {
var result = future.get();
return result;
} catch (InterruptedException | ExecutionException ex) {
var cause = ex.getCause();
if (cause instanceof PiccodeException pex) {
pex.message += ". Thread id: " + frame;
throw pex;
}
var err = new PiccodeException(file, line, column, "Internal error: " + ex.getMessage());
err.frame = frame;
throw err;
}
}
if (rhs instanceof IdentifierAst id) {
key = id.text;
} else {
key = rhs.execute(frame).raw().toString();
}
var value = obj.getValue(key);
if (value == null) {
var err = new PiccodeException(file, line, column, "Field `" + key + "` is not part of " + obj.raw());
err.frame = frame;
throw err;
}
return value;
}
private PiccodeValue processArrayIndexing(PiccodeValue[] arr, PiccodeValue execute, Integer frame) {
if (!(execute instanceof PiccodeNumber)) {
var err = new PiccodeException(file, line, column, "Attempt to index array value with non numeric index: " + rhs + " which evaluates to " + execute + " is used as an index");
err.frame = frame;
throw err;
}
int index = (int) ((double) execute.raw());
if (index < 0 || index >= arr.length) {
var err = new PiccodeException(file, line, column, "Array index out of bounds: " + lhs + " evaluates to an array with size" + arr.length + " which is indexed with " + execute);
err.frame = frame;
throw err;
}
return arr[index];
}
private PiccodeValue processTupleIndexing(PiccodeValue[] arr, PiccodeValue execute, Integer frame) {
if (!(execute instanceof PiccodeNumber)) {
var err = new PiccodeException(file, line, column, "Attempt to index a tuple value with non numeric index: " + rhs + " which evaluates to " + execute + " is used as an index");
err.frame = frame;
throw err;
}
int index = (int) ((double) execute.raw());
if (index < 0 || index >= arr.length) {
var err = new PiccodeException(file, line, column, "Array index out of bounds: " + lhs + " evaluates to a tuple with size" + arr.length + " which is indexed with " + execute);
err.frame = frame;
throw err;
}
return arr[index];
}
@Override
public String codeGen(TargetEnvironment target) {
return String.format("%s.%s", lhs, rhs);
}
}