Skip to content

Commit b8e6b8e

Browse files
authored
Merge in select generics classes from genericsTake2. (#1406)
This cherry-picked merge is phase 1 of merging in support for generics. By itself, this code does nothing, but some changes to CClassType are necessarily not dark. Most methods stubbed, but some actually call in to the dark code, but should not be used yet.
1 parent a6f7348 commit b8e6b8e

39 files changed

Lines changed: 4678 additions & 28 deletions

src/main/java/com/laytonsmith/PureUtilities/Common/StringUtils.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,30 @@ public static String Join(List list, String glue) {
303303
return Join(list, glue, null, null, null);
304304
}
305305

306+
/**
307+
* Joins a list together, rendering each item with the custom renderer.
308+
* @param <T> The list type
309+
* @param list The list to concatenate
310+
* @param glue The glue to use
311+
* @param renderer The item renderer. If null, toString will be used by default on each item.
312+
* @return The concatenated string
313+
*/
314+
public static <T> String Join(List<T> list, String glue, Renderer<T> renderer) {
315+
return Join(list, glue, null, null, null, renderer);
316+
}
317+
318+
/**
319+
* Joins an array together, rendering each item with the custom renderer.
320+
* @param <T> The array type
321+
* @param list The array to concatenate
322+
* @param glue The glue to use
323+
* @param renderer The item renderer. If null, toString will be used by default on each item.
324+
* @return The concatenated string
325+
*/
326+
public static <T> String Join(T[] list, String glue, Renderer<T> renderer) {
327+
return Join(list, glue, null, null, null, renderer);
328+
}
329+
306330
/**
307331
* Joins a list together (using StringBuilder's {@link StringBuilder#append(Object)} method
308332
* to "toString" the Object) using the specified string for glue.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.laytonsmith.PureUtilities;
2+
3+
import java.util.Objects;
4+
import java.util.Optional;
5+
6+
/**
7+
* The {@code Either} class can contain neither of, or one of either the specified types of values.
8+
* @param <L> The first possible type.
9+
* @param <R> The second possible type.
10+
*/
11+
public final class Either<L, R> {
12+
13+
/**
14+
* Creates a new Either object with the first possible type.
15+
* @param <L> The first possible type, which is the type of the input parameter.
16+
* @param <R> The other possible type, which this value will not contain.
17+
* @param value The value to store.
18+
* @return A new Either object.
19+
*/
20+
public static <L, R> Either<L, R> left(L value) {
21+
return new Either<>(Optional.of(value), Optional.empty());
22+
}
23+
24+
/**
25+
* Creates a new Either object with the second possible type.
26+
* @param <L> The other possible type, which this value will not contain.
27+
* @param <R> The second possible type, which is the type of the input parameter.
28+
* @param value The value to store.
29+
* @return A new Either object.
30+
*/
31+
public static <L, R> Either<L, R> right(R value) {
32+
return new Either<>(Optional.empty(), Optional.of(value));
33+
}
34+
35+
/**
36+
* Creates a new Either object, which does not contain any value.
37+
* @param <L> The first possible type.
38+
* @param <R> The second possible type.
39+
* @return A new, empty, Either object.
40+
*/
41+
public static <L, R> Either<L, R> neither() {
42+
return new Either<>(Optional.empty(), Optional.empty());
43+
}
44+
45+
private final Optional<L> left;
46+
private final Optional<R> right;
47+
48+
private Either(Optional<L> left, Optional<R> right) {
49+
this.left = left;
50+
this.right = right;
51+
}
52+
53+
/**
54+
* Returns the left value. May be empty, even if the other value is also empty.
55+
* @return
56+
*/
57+
public Optional<L> getLeft() {
58+
return this.left;
59+
}
60+
61+
/**
62+
* Returns the left value. May be empty, even if the other value is also empty.
63+
* @return
64+
*/
65+
public Optional<R> getRight() {
66+
return this.right;
67+
}
68+
69+
/**
70+
* Returns if there was a left side.
71+
* @return
72+
*/
73+
public boolean hasLeft() {
74+
return this.left.isPresent();
75+
}
76+
77+
/**
78+
* Returns if there was a right side.
79+
* @return
80+
*/
81+
public boolean hasRight() {
82+
return this.right.isPresent();
83+
}
84+
85+
@Override
86+
public int hashCode() {
87+
int hash = 3;
88+
hash = 19 * hash + Objects.hashCode(this.left);
89+
hash = 19 * hash + Objects.hashCode(this.right);
90+
return hash;
91+
}
92+
93+
@Override
94+
public boolean equals(Object obj) {
95+
if(this == obj) {
96+
return true;
97+
}
98+
if(obj == null) {
99+
return false;
100+
}
101+
if(getClass() != obj.getClass()) {
102+
return false;
103+
}
104+
final Either<?, ?> other = (Either<?, ?>) obj;
105+
if(!Objects.equals(this.left, other.left)) {
106+
return false;
107+
}
108+
return Objects.equals(this.right, other.right);
109+
}
110+
111+
@Override
112+
public String toString() {
113+
return "Either{" + "left=" + left + ", right=" + right + '}';
114+
}
115+
116+
}

src/main/java/com/laytonsmith/core/MethodScriptCompiler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.laytonsmith.core.compiler.TokenStream;
2222
import com.laytonsmith.core.compiler.analysis.StaticAnalysis;
2323
import com.laytonsmith.core.constructs.CBareString;
24-
import com.laytonsmith.core.constructs.CClassType;
2524
import com.laytonsmith.core.constructs.CDecimal;
2625
import com.laytonsmith.core.constructs.CDouble;
2726
import com.laytonsmith.core.constructs.CFunction;
@@ -37,6 +36,7 @@
3736
import com.laytonsmith.core.constructs.CVoid;
3837
import com.laytonsmith.core.constructs.Construct;
3938
import com.laytonsmith.core.constructs.IVariable;
39+
import com.laytonsmith.core.constructs.SourceType;
4040
import com.laytonsmith.core.constructs.Target;
4141
import com.laytonsmith.core.constructs.Token;
4242
import com.laytonsmith.core.constructs.Token.TType;
@@ -1753,11 +1753,11 @@ public static ParseTree compile(TokenStream stream, Environment environment,
17531753
ParseTree previous = tree.getChildAt(tree.getChildren().size() - 1);
17541754
// TODO: Add LHSType as well, though this will not work as is with user objects. It may need
17551755
// to be moved into a node modifier or something.
1756-
if(!(previous.getData() instanceof CClassType)) {
1756+
if(!(previous.getData() instanceof SourceType)) {
17571757
throw new ConfigCompileException("Unexpected varargs token (\"...\"). This can only be used with types.", t.target);
17581758
}
1759-
if(previous.getData() instanceof CClassType c) {
1760-
previous.setData(c.asVarargs());
1759+
if(previous.getData() instanceof SourceType st) {
1760+
previous.setData(st.asVariadicType(null));
17611761
}
17621762
continue;
17631763
} else if(t.type == TType.LIT) {

src/main/java/com/laytonsmith/core/Procedure.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public Procedure(String name, CClassType returnType, List<IVariable> varList, Sm
6868
this.procComment = procComment;
6969
for(int i = 0; i < varList.size(); i++) {
7070
IVariable var = varList.get(i);
71-
if(var.getDefinedType().isVarargs() && i != varList.size() - 1) {
71+
if(var.getDefinedType().isVariadicType() && i != varList.size() - 1) {
7272
throw new CREFormatException("Varargs can only be added to the last argument.", t);
7373
}
7474
try {
@@ -77,7 +77,7 @@ public Procedure(String name, CClassType returnType, List<IVariable> varList, Sm
7777
this.varList.put(var.getVariableName(), var);
7878
}
7979
this.varIndex.add(var);
80-
if(var.getDefinedType().isVarargs() && var.ival() != CNull.UNDEFINED) {
80+
if(var.getDefinedType().isVariadicType() && var.ival() != CNull.UNDEFINED) {
8181
throw new CREFormatException("Varargs may not have default values", t);
8282
}
8383
this.originals.put(var.getVariableName(), var.ival());
@@ -218,10 +218,10 @@ public Mixed execute(List<Mixed> args, Environment oldEnv, Target t) {
218218
arguments.push(c, t);
219219
if(this.varIndex.size() > varInd
220220
|| (!this.varIndex.isEmpty()
221-
&& this.varIndex.get(this.varIndex.size() - 1).getDefinedType().isVarargs())) {
221+
&& this.varIndex.get(this.varIndex.size() - 1).getDefinedType().isVariadicType())) {
222222
IVariable var;
223223
if(varInd < this.varIndex.size() - 1
224-
|| !this.varIndex.get(this.varIndex.size() - 1).getDefinedType().isVarargs()) {
224+
|| !this.varIndex.get(this.varIndex.size() - 1).getDefinedType().isVariadicType()) {
225225
var = this.varIndex.get(varInd);
226226
} else {
227227
var = this.varIndex.get(this.varIndex.size() - 1);
@@ -242,7 +242,7 @@ public Mixed execute(List<Mixed> args, Environment oldEnv, Target t) {
242242
}
243243

244244
// Type check vararg parameter.
245-
if(var.getDefinedType().isVarargs()) {
245+
if(var.getDefinedType().isVariadicType()) {
246246
if(InstanceofUtil.isInstanceof(c.typeof(), var.getDefinedType().getVarargsBaseType(), env)) {
247247
vararg.push(c, t);
248248
continue;

src/main/java/com/laytonsmith/core/compiler/FileOptions.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ public static enum SuppressWarning implements Documentation {
368368
MSVersion.V3_3_5, SeverityLevel.MEDIUM),
369369
UnexpectedStatement("In strict mode, unexpected statements are an error, but in non-strict mode, they are"
370370
+ " a warning.", MSVersion.V3_3_5, SeverityLevel.HIGH),
371+
GenericTypeOverrides("When using generics, defining a typename which matches an in-scope actual object type"
372+
+ " can lead to confusion, since references to the original type will no longer reference the"
373+
+ " actual type, but rather the typename. Thus, this should be avoided.", MSVersion.V3_3_5,
374+
SeverityLevel.HIGH),
371375
PossibleUnexpectedExecution("If the parenthesis following a token is on a different line as the previous"
372376
+ " token, and it in general looks like a value that might be executable, this warning is"
373377
+ " issued, as it will cause an attempt at executing the previous statement. This"

src/main/java/com/laytonsmith/core/compiler/signature/FunctionSignature.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.laytonsmith.PureUtilities.Common.StringUtils;
99
import com.laytonsmith.core.constructs.CClassType;
1010
import com.laytonsmith.core.constructs.InstanceofUtil;
11+
import com.laytonsmith.core.constructs.generics.GenericDeclaration;
1112
import com.laytonsmith.core.environments.Environment;
1213

1314
/**
@@ -44,6 +45,13 @@ public FunctionSignature(ReturnType returnType) {
4445
this(returnType, new ArrayList<>(), new ArrayList<>(), false);
4546
}
4647

48+
/**
49+
* Stub for generics support — not yet implemented.
50+
*/
51+
public GenericDeclaration getGenericDeclaration() {
52+
throw new UnsupportedOperationException("Not yet implemented");
53+
}
54+
4755
protected void addParam(Param param) {
4856
this.params.add(param);
4957
}

src/main/java/com/laytonsmith/core/constructs/Auto.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
public class Auto {
99

1010
public static final CClassType TYPE = CClassType.AUTO;
11+
public static final LeftHandSideType LHSTYPE = TYPE.asLeftHandSideType();
1112
}

src/main/java/com/laytonsmith/core/constructs/CArray.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import com.laytonsmith.core.MSLog;
88
import com.laytonsmith.core.MSVersion;
99
import com.laytonsmith.core.LogLevel;
10+
import com.laytonsmith.core.constructs.generics.GenericParameters;
11+
import com.laytonsmith.core.environments.Environment;
1012
import com.laytonsmith.core.exceptions.CRE.CRECastException;
1113
import com.laytonsmith.core.exceptions.CRE.CREFormatException;
1214
import com.laytonsmith.core.exceptions.CRE.CREIndexOverflowException;
@@ -58,6 +60,27 @@ public CArray(Target t) {
5860
this(t, 0, (Mixed[]) null);
5961
}
6062

63+
/**
64+
* Constructor with generic parameters and environment. GenericParameters are ignored for now.
65+
*/
66+
public CArray(Target t, GenericParameters genericParameters, Environment env) {
67+
this(t);
68+
}
69+
70+
/**
71+
* Constructor with initial capacity, generic parameters and environment. GenericParameters are ignored for now.
72+
*/
73+
public CArray(Target t, int initialCapacity, GenericParameters genericParameters, Environment env) {
74+
this(t, initialCapacity);
75+
}
76+
77+
/**
78+
* Constructor with items, generic parameters and environment. GenericParameters are ignored for now.
79+
*/
80+
public CArray(Target t, GenericParameters genericParameters, Environment env, Mixed... items) {
81+
this(t, items);
82+
}
83+
6184
public CArray(Target t, Mixed... items) {
6285
this(t, 0, items);
6386
}

0 commit comments

Comments
 (0)