Skip to content

Commit a1c4b3a

Browse files
committed
Update script runtime and interpreter engine
1 parent 3c992fa commit a1c4b3a

25 files changed

+1471
-956
lines changed

src/main/java/com/relogiclabs/jschema/internal/engine/Evaluator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
@FunctionalInterface
66
public interface Evaluator {
7-
EValue evaluate(ScopeContext scope);
7+
EValue evaluate(ScriptScope scope);
88
}

src/main/java/com/relogiclabs/jschema/internal/engine/ScriptErrorHelper.java

+107-85
Large diffs are not rendered by default.

src/main/java/com/relogiclabs/jschema/internal/engine/ScriptContext.java renamed to src/main/java/com/relogiclabs/jschema/internal/engine/ScriptGlobalScope.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import lombok.Getter;
55

66
@Getter
7-
public class ScriptContext extends ScopeContext {
7+
public class ScriptGlobalScope extends ScriptScope {
88
private final RuntimeContext runtime;
99

10-
public ScriptContext(RuntimeContext runtime) {
10+
public ScriptGlobalScope(RuntimeContext runtime) {
1111
super(null);
1212
this.runtime = runtime;
1313
}

src/main/java/com/relogiclabs/jschema/internal/engine/ScriptOperation.java

-15
This file was deleted.

src/main/java/com/relogiclabs/jschema/internal/engine/ScopeContext.java renamed to src/main/java/com/relogiclabs/jschema/internal/engine/ScriptScope.java

+21-23
Original file line numberDiff line numberDiff line change
@@ -3,52 +3,50 @@
33
import com.relogiclabs.jschema.exception.ScriptFunctionException;
44
import com.relogiclabs.jschema.exception.ScriptVariableException;
55
import com.relogiclabs.jschema.internal.script.GFunction;
6-
import com.relogiclabs.jschema.internal.script.GReference;
6+
import com.relogiclabs.jschema.internal.script.GLeftValue;
77
import com.relogiclabs.jschema.tree.RuntimeContext;
88
import com.relogiclabs.jschema.type.EValue;
99
import lombok.Getter;
1010

1111
import java.util.HashMap;
1212
import java.util.Map;
1313

14-
import static com.relogiclabs.jschema.internal.library.ScriptLibrary.resolveStatic;
15-
import static com.relogiclabs.jschema.internal.script.GFunction.CONSTRAINT_PREFIX;
16-
import static com.relogiclabs.jschema.internal.util.StringHelper.concat;
17-
import static com.relogiclabs.jschema.message.ErrorCode.FUNS02;
18-
import static com.relogiclabs.jschema.message.ErrorCode.FUNS03;
14+
import static com.relogiclabs.jschema.internal.library.ScriptLibrary3.resolveStatic;
15+
import static com.relogiclabs.jschema.internal.tree.EFunction.CONSTRAINT_PREFIX;
16+
import static com.relogiclabs.jschema.message.ErrorCode.FUND01;
17+
import static com.relogiclabs.jschema.message.ErrorCode.FUND02;
1918
import static com.relogiclabs.jschema.message.ErrorCode.VARD01;
2019
import static org.apache.commons.lang3.StringUtils.substringBefore;
2120

22-
public class ScopeContext {
23-
@Getter private final ScopeContext parent;
21+
public class ScriptScope {
22+
@Getter private final ScriptScope parent;
2423
private final Map<String, EValue> symbols;
2524

26-
public ScopeContext(ScopeContext parent) {
25+
public ScriptScope(ScriptScope parent) {
2726
this.parent = parent;
2827
this.symbols = new HashMap<>();
2928
}
3029

31-
public GReference addVariable(String name, EValue value) {
32-
if(symbols.containsKey(name)) throw new ScriptVariableException(VARD01,
33-
concat("Variable '", name, "' already defined in the scope"));
34-
var reference = new GReference(value);
35-
symbols.put(name, reference);
36-
return reference;
30+
public GLeftValue addVariable(String name, EValue value) {
31+
var lvalue = new GLeftValue(value);
32+
var oldValue = symbols.put(name, lvalue);
33+
if(oldValue == null) return lvalue;
34+
throw new ScriptVariableException(VARD01,
35+
"Variable '" + name + "' already defined in the scope");
3736
}
3837

3938
public void addFunction(String name, GFunction function) {
40-
if(symbols.containsKey(name)) {
41-
if(name.startsWith(CONSTRAINT_PREFIX))
42-
throw failOnDuplicateDefinition(FUNS02, "Constraint", name);
43-
else throw failOnDuplicateDefinition(FUNS03, "Subroutine", name);
44-
}
45-
symbols.put(name, function);
39+
var oldValue = symbols.put(name, function);
40+
if(oldValue == null) return;
41+
if(name.startsWith(CONSTRAINT_PREFIX))
42+
throw failOnDuplicateDefinition(FUND01, "Constraint", name);
43+
else throw failOnDuplicateDefinition(FUND02, "Subroutine", name);
4644
}
4745

4846
private static ScriptFunctionException failOnDuplicateDefinition(String code,
4947
String functionType, String name) {
50-
return new ScriptFunctionException(code, concat(functionType, " function '",
51-
substringBefore(name, '#'), "' with matching parameter(s) already defined"));
48+
return new ScriptFunctionException(code, functionType + " function '"
49+
+ substringBefore(name, '#') + "' with matching parameter(s) already defined");
5250
}
5351

5452
public EValue resolve(String name) {

src/main/java/com/relogiclabs/jschema/internal/engine/ScriptTreeHelper.java

+36-34
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package com.relogiclabs.jschema.internal.engine;
22

3-
import com.relogiclabs.jschema.internal.antlr.SchemaLexer;
3+
import com.relogiclabs.jschema.internal.antlr.SchemaParser;
44
import com.relogiclabs.jschema.internal.script.GDouble;
5-
import com.relogiclabs.jschema.internal.script.GFunction;
65
import com.relogiclabs.jschema.internal.script.GInteger;
6+
import com.relogiclabs.jschema.internal.script.GLeftValue;
77
import com.relogiclabs.jschema.internal.script.GObject;
88
import com.relogiclabs.jschema.internal.script.GParameter;
99
import com.relogiclabs.jschema.internal.script.GRange;
10-
import com.relogiclabs.jschema.internal.script.GReference;
1110
import com.relogiclabs.jschema.tree.RuntimeContext;
1211
import com.relogiclabs.jschema.type.EArray;
1312
import com.relogiclabs.jschema.type.EBoolean;
@@ -27,10 +26,13 @@
2726
import java.util.stream.Collectors;
2827

2928
import static com.relogiclabs.jschema.internal.engine.ScriptErrorHelper.failOnDuplicateParameterName;
30-
import static com.relogiclabs.jschema.internal.engine.ScriptErrorHelper.failOnFixedArgument;
31-
import static com.relogiclabs.jschema.internal.engine.ScriptErrorHelper.failOnVariadicArgument;
32-
import static com.relogiclabs.jschema.internal.script.GFunction.CONSTRAINT_PREFIX;
29+
import static com.relogiclabs.jschema.internal.engine.ScriptErrorHelper.failOnFixedArity;
30+
import static com.relogiclabs.jschema.internal.engine.ScriptErrorHelper.failOnVariadicArity;
31+
import static com.relogiclabs.jschema.internal.script.GFunction.CONSTRAINT_MODE;
32+
import static com.relogiclabs.jschema.internal.script.GFunction.FUTURE_MODE;
33+
import static com.relogiclabs.jschema.internal.script.GFunction.SUBROUTINE_MODE;
3334
import static com.relogiclabs.jschema.internal.script.RFunction.hasVariadic;
35+
import static com.relogiclabs.jschema.internal.util.CommonHelper.hasFlag;
3436
import static com.relogiclabs.jschema.internal.util.StreamHelper.halt;
3537
import static java.util.stream.Collectors.toMap;
3638

@@ -39,7 +41,7 @@ public final class ScriptTreeHelper {
3941
private static final String TRYOF_ERROR = "error";
4042

4143
private ScriptTreeHelper() {
42-
throw new UnsupportedOperationException();
44+
throw new UnsupportedOperationException("This class is not intended for instantiation");
4345
}
4446

4547
public static boolean areEqual(EValue v1, EValue v2, RuntimeContext runtime) {
@@ -55,7 +57,7 @@ public static boolean areEqual(EValue v1, EValue v2, RuntimeContext runtime) {
5557
if(v1 instanceof EUndefined && v2 instanceof EUndefined) return true;
5658
if(v1 instanceof EArray a1 && v2 instanceof EArray a2) {
5759
if(a1.size() != a2.size()) return false;
58-
for(int i = 0; i < a1.size(); i++)
60+
for(var i = 0; i < a1.size(); i++)
5961
if(!areEqual(a1.get(i), a2.get(i), runtime)) return false;
6062
return true;
6163
}
@@ -71,46 +73,44 @@ public static boolean areEqual(EValue v1, EValue v2, RuntimeContext runtime) {
7173
}
7274

7375
public static EValue dereference(EValue value) {
74-
while(value instanceof GReference reference)
75-
value = reference.getValue();
76+
while(value instanceof GLeftValue lvalue)
77+
value = lvalue.getValue();
7678
return value;
7779
}
7880

79-
static int getFunctionMode(TerminalNode constraint, TerminalNode future, TerminalNode subroutine) {
80-
return getFunctionMode(constraint) | getFunctionMode(future) | getFunctionMode(subroutine);
81+
static int getFunctionMode(TerminalNode constraint, TerminalNode future,
82+
TerminalNode subroutine) {
83+
return getFunctionMode(constraint)
84+
| getFunctionMode(future)
85+
| getFunctionMode(subroutine);
8186
}
8287

8388
private static int getFunctionMode(TerminalNode node) {
8489
if(node == null) return 0;
8590
return switch(node.getSymbol().getType()) {
86-
case SchemaLexer.G_CONSTRAINT -> GFunction.CONSTRAINT_MODE;
87-
case SchemaLexer.G_FUTURE -> GFunction.FUTURE_MODE;
88-
case SchemaLexer.G_SUBROUTINE -> GFunction.SUBROUTINE_MODE;
91+
case SchemaParser.G_CONSTRAINT -> CONSTRAINT_MODE;
92+
case SchemaParser.G_FUTURE -> FUTURE_MODE;
93+
case SchemaParser.G_SUBROUTINE -> SUBROUTINE_MODE;
8994
default -> 0;
9095
};
9196
}
9297

93-
static ENumber increment(ENumber number) {
94-
if(number instanceof EInteger i) return GInteger.of(i.getValue() + 1);
95-
return GDouble.of(number.toDouble() + 1);
96-
}
97-
98-
static ENumber decrement(ENumber number) {
99-
if(number instanceof EInteger i) return GInteger.of(i.getValue() - 1);
100-
return GDouble.of(number.toDouble() - 1);
98+
public static boolean isConstraint(int mode) {
99+
return hasFlag(mode, CONSTRAINT_MODE);
101100
}
102101

103-
static String formatFunctionName(String baseName, GParameter[] parameters) {
104-
if(hasVariadic(parameters)) return baseName + "#...";
105-
return baseName + "#" + parameters.length;
102+
static ENumber increment(ENumber number) {
103+
if(number instanceof EInteger i) return GInteger.from(i.getValue() + 1);
104+
return GDouble.from(number.toDouble() + 1);
106105
}
107106

108-
static String toConstraintName(String functionName) {
109-
return CONSTRAINT_PREFIX.concat(functionName);
107+
static ENumber decrement(ENumber number) {
108+
if(number instanceof EInteger i) return GInteger.from(i.getValue() - 1);
109+
return GDouble.from(number.toDouble() - 1);
110110
}
111111

112112
static GParameter[] toParameters(List<TerminalNode> identifiers,
113-
TerminalNode ellipsis) {
113+
TerminalNode ellipsis) {
114114
identifiers.stream().collect(toMap(ParseTree::getText, Function.identity(),
115115
(i1, i2) -> halt(failOnDuplicateParameterName(i2))
116116
));
@@ -122,8 +122,10 @@ static GParameter[] toParameters(List<TerminalNode> identifiers,
122122

123123
public static void areCompatible(GParameter[] parameters, List<EValue> arguments, String code) {
124124
if(hasVariadic(parameters)) {
125-
if(arguments.size() < parameters.length - 1) throw failOnVariadicArgument(code);
126-
} else if(arguments.size() != parameters.length) throw failOnFixedArgument(code);
125+
if(arguments.size() < parameters.length - 1) throw failOnVariadicArity(code);
126+
return;
127+
}
128+
if(arguments.size() != parameters.length) throw failOnFixedArity(code);
127129
}
128130

129131
public static String stringify(Object object) {
@@ -132,9 +134,9 @@ public static String stringify(Object object) {
132134
}
133135

134136
static GObject createTryofMonad(EValue value, EValue error) {
135-
GObject object = new GObject(2);
136-
object.set(TRYOF_VALUE, value);
137-
object.set(TRYOF_ERROR, error);
137+
var object = new GObject(2);
138+
object.put(TRYOF_VALUE, value);
139+
object.put(TRYOF_ERROR, error);
138140
return object;
139141
}
140142

0 commit comments

Comments
 (0)