Skip to content

Commit 5e7ed38

Browse files
committed
Add script data type implementations
1 parent 0185c7d commit 5e7ed38

File tree

13 files changed

+555
-0
lines changed

13 files changed

+555
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.exception.ScriptCommonException;
4+
import com.relogiclabs.jschema.type.EArray;
5+
import com.relogiclabs.jschema.type.EValue;
6+
import lombok.EqualsAndHashCode;
7+
import lombok.Getter;
8+
9+
import java.util.ArrayList;
10+
import java.util.Collection;
11+
import java.util.List;
12+
13+
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
14+
import static com.relogiclabs.jschema.internal.util.StringHelper.joinWith;
15+
import static com.relogiclabs.jschema.message.ErrorCode.INDX01;
16+
17+
@Getter
18+
@EqualsAndHashCode
19+
public final class GArray implements EArray {
20+
private static final int MAX_LIMIT = Short.MAX_VALUE;
21+
private final List<EValue> elements;
22+
23+
private GArray(int size) {
24+
this.elements = new ArrayList<>(size);
25+
}
26+
27+
public GArray(Collection<? extends EValue> collection) {
28+
this.elements = new ArrayList<>(collection.size());
29+
for(var v : collection) elements.add(new GReference(v));
30+
}
31+
32+
public static GArray filledFrom(EValue value, int size) {
33+
var array = new GArray(size);
34+
for(int i = 0; i < size; i++) array.elements.add(new GReference(value));
35+
return array;
36+
}
37+
38+
public static GArray from(EArray array, GRange range) {
39+
var list = array.elements();
40+
var size = list.size();
41+
return new GArray(list.subList(range.getStart(size), range.getEnd(size)));
42+
}
43+
44+
@Override
45+
public EValue get(int index) {
46+
var size = elements.size();
47+
if(index < size) return elements.get(index);
48+
if(index > MAX_LIMIT) throw new ScriptCommonException(INDX01,
49+
concat("Array index ", index, " exceeds maximum size limit"));
50+
if(index > size) throw new ArrayIndexOutOfBoundsException(index);
51+
var element = new GReference(VOID);
52+
elements.add(element);
53+
return element;
54+
}
55+
56+
@Override
57+
public List<? extends EValue> elements() {
58+
return elements;
59+
}
60+
61+
@Override
62+
public String toString() {
63+
return joinWith(elements, ", ", "[", "]");
64+
}
65+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.type.EBoolean;
4+
import lombok.EqualsAndHashCode;
5+
import lombok.RequiredArgsConstructor;
6+
7+
import static lombok.AccessLevel.PRIVATE;
8+
9+
@EqualsAndHashCode
10+
@RequiredArgsConstructor(access = PRIVATE)
11+
public final class GBoolean implements EBoolean {
12+
public static final GBoolean TRUE = new GBoolean(true);
13+
public static final GBoolean FALSE = new GBoolean(false);
14+
15+
private final boolean value;
16+
17+
public static GBoolean of(boolean value) {
18+
return value? TRUE : FALSE;
19+
}
20+
21+
@Override
22+
public boolean getValue() {
23+
return value;
24+
}
25+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.type.EValue;
4+
import lombok.Getter;
5+
import lombok.RequiredArgsConstructor;
6+
7+
import static lombok.AccessLevel.PRIVATE;
8+
9+
@RequiredArgsConstructor(access = PRIVATE)
10+
public final class GControl implements EValue {
11+
private static final int BREAK_FLAG = 1;
12+
private static final int RETURN_FLAG = 2;
13+
public static final GControl BREAK = new GControl(BREAK_FLAG, VOID);
14+
15+
private final int flag;
16+
@Getter private final EValue value;
17+
18+
public static GControl ofReturn(EValue value) {
19+
return new GControl(RETURN_FLAG, value);
20+
}
21+
22+
public boolean isBreak() {
23+
return flag == BREAK_FLAG;
24+
}
25+
26+
public boolean isReturn() {
27+
return flag == RETURN_FLAG;
28+
}
29+
30+
public EValue toIteration() {
31+
return flag == BREAK_FLAG ? VOID : this;
32+
}
33+
34+
public EValue toFunction() {
35+
return value;
36+
}
37+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.type.EDouble;
4+
import lombok.EqualsAndHashCode;
5+
import lombok.Getter;
6+
import lombok.RequiredArgsConstructor;
7+
8+
@Getter
9+
@EqualsAndHashCode
10+
@RequiredArgsConstructor(staticName = "of")
11+
public final class GDouble implements EDouble {
12+
private final double value;
13+
14+
@Override
15+
public String toString() {
16+
return String.valueOf(value);
17+
}
18+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.internal.engine.Evaluator;
4+
import com.relogiclabs.jschema.internal.engine.ScopeContext;
5+
import com.relogiclabs.jschema.type.EValue;
6+
import lombok.Getter;
7+
import lombok.RequiredArgsConstructor;
8+
9+
import java.util.List;
10+
11+
import static com.relogiclabs.jschema.internal.engine.ScriptTreeHelper.areCompatible;
12+
import static com.relogiclabs.jschema.internal.util.CollectionHelper.getLast;
13+
import static com.relogiclabs.jschema.internal.util.CollectionHelper.subList;
14+
import static com.relogiclabs.jschema.internal.util.MiscellaneousHelper.hasFlag;
15+
import static com.relogiclabs.jschema.message.ErrorCode.FUNS05;
16+
17+
@Getter
18+
@RequiredArgsConstructor
19+
public final class GFunction implements RFunction {
20+
public static final String CONSTRAINT_MARKER = "@";
21+
public static final int CONSTRAINT_MODE = 1;
22+
public static final int FUTURE_MODE = 3;
23+
public static final int SUBROUTINE_MODE = 4;
24+
25+
private final GParameter[] parameters;
26+
private final boolean variadic;
27+
private final Evaluator body;
28+
private final int mode;
29+
30+
public GFunction(GParameter[] parameters, Evaluator body, int mode) {
31+
this.parameters = parameters;
32+
this.body = body;
33+
this.mode = mode;
34+
this.variadic = parameters.length != 0 && getLast(parameters).isVariadic();
35+
}
36+
37+
@Override
38+
public EValue invoke(ScopeContext functionScope, List<EValue> arguments) {
39+
return invoke(functionScope);
40+
}
41+
42+
public EValue invoke(ScopeContext functionScope) {
43+
var v1 = getBody().evaluate(functionScope);
44+
if(v1 instanceof GControl ctrl) return ctrl.getValue();
45+
return VOID;
46+
}
47+
48+
@Override
49+
public ScopeContext bind(ScopeContext parentScope, List<EValue> arguments) {
50+
areCompatible(parameters, arguments, FUNS05);
51+
var scope = new ScopeContext(parentScope);
52+
var i = 0;
53+
for(var p : parameters) {
54+
if(p.isVariadic()) scope.addVariable(p.getName(), new GArray(subList(arguments, i)));
55+
else scope.addVariable(p.getName(), arguments.get(i++));
56+
}
57+
return scope;
58+
}
59+
60+
public boolean isFuture() {
61+
return hasFlag(mode, FUTURE_MODE);
62+
}
63+
64+
public static boolean isConstraint(int mode) {
65+
return hasFlag(mode, CONSTRAINT_MODE);
66+
}
67+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.type.EInteger;
4+
import lombok.EqualsAndHashCode;
5+
import lombok.Getter;
6+
import lombok.RequiredArgsConstructor;
7+
8+
import static lombok.AccessLevel.PRIVATE;
9+
10+
@Getter
11+
@EqualsAndHashCode
12+
@RequiredArgsConstructor(access = PRIVATE)
13+
public final class GInteger implements EInteger {
14+
private static final int CACHE_SIZE = 256;
15+
private static final GInteger[] CACHE = createCache(CACHE_SIZE);
16+
private final long value;
17+
18+
public static GInteger of(long value) {
19+
if(value >= 0 && value < CACHE_SIZE) return CACHE[(int) value];
20+
return new GInteger(value);
21+
}
22+
23+
@Override
24+
public String toString() {
25+
return String.valueOf(value);
26+
}
27+
28+
private static GInteger[] createCache(int size) {
29+
GInteger[] cache = new GInteger[size];
30+
for(int i = 0; i < size; i++) cache[i] = new GInteger(i);
31+
return cache;
32+
}
33+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.relogiclabs.jschema.internal.script;
2+
3+
import com.relogiclabs.jschema.exception.ScriptCommonException;
4+
import com.relogiclabs.jschema.type.EArray;
5+
import com.relogiclabs.jschema.type.EObject;
6+
import com.relogiclabs.jschema.type.EString;
7+
import com.relogiclabs.jschema.type.EValue;
8+
import lombok.Getter;
9+
import lombok.RequiredArgsConstructor;
10+
11+
import java.util.Iterator;
12+
13+
import static com.relogiclabs.jschema.internal.engine.ScriptTreeHelper.dereference;
14+
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
15+
import static com.relogiclabs.jschema.message.ErrorCode.ITER01;
16+
import static lombok.AccessLevel.PRIVATE;
17+
18+
@Getter
19+
@RequiredArgsConstructor(access = PRIVATE)
20+
public final class GIterator implements Iterable<EValue> {
21+
private final EValue iterable;
22+
23+
public static GIterator of(EValue iterable) {
24+
return new GIterator(dereference(iterable));
25+
}
26+
27+
@Override
28+
public Iterator<EValue> iterator() {
29+
if(iterable instanceof EArray array) return iterator(array);
30+
if(iterable instanceof EObject object) return iterator(object);
31+
if(iterable instanceof EString string) return iterator(string);
32+
else throw new ScriptCommonException(ITER01,
33+
concat("Invalid type ", iterable.getType(), " for iteration"));
34+
}
35+
36+
public Iterator<EValue> iterator(EArray array) {
37+
while(array.size() == 1) {
38+
if(array.get(0) instanceof EArray)
39+
array = (EArray) array.get(0);
40+
else break;
41+
}
42+
var iterator = array.elements().iterator();
43+
return new Iterator<>() {
44+
@Override
45+
public boolean hasNext() {
46+
return iterator.hasNext();
47+
}
48+
49+
@Override
50+
public EValue next() {
51+
return iterator.next();
52+
}
53+
};
54+
}
55+
56+
public Iterator<EValue> iterator(EString string) {
57+
String value = string.getValue();
58+
return new Iterator<>() {
59+
private int index = 0;
60+
61+
@Override
62+
public boolean hasNext() {
63+
return index < value.length();
64+
}
65+
66+
@Override
67+
public EValue next() {
68+
return GString.of(value.charAt(index++));
69+
}
70+
};
71+
}
72+
73+
public Iterator<EValue> iterator(EObject object) {
74+
var iterator = object.keySet().iterator();
75+
return new Iterator<>() {
76+
@Override
77+
public boolean hasNext() {
78+
return iterator.hasNext();
79+
}
80+
81+
@Override
82+
public EValue next() {
83+
return GString.of(iterator.next());
84+
}
85+
};
86+
}
87+
}

0 commit comments

Comments
 (0)