From 6e7e78cca8580793425ee3e26fc4bf0a98b16d04 Mon Sep 17 00:00:00 2001
From: Pieter12345
Date: Fri, 25 Mar 2022 05:45:30 +0100
Subject: [PATCH 1/4] Remove unreachable catch block in array_size
---
.../core/functions/ArrayHandling.java | 25 ++++++++-----------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
index 61aacacbd..6e0aef18d 100644
--- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
+++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
@@ -264,22 +264,19 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
} else if(args[0].isInstanceOf(ArrayAccess.TYPE)) {
com.laytonsmith.core.natives.interfaces.Iterable aa
= (com.laytonsmith.core.natives.interfaces.Iterable) args[0];
- if(index instanceof CSlice) {
+ if(index instanceof CSlice cslice) {
//It's a range
- int start = (int) ((CSlice) index).getStart();
- int finish = (int) ((CSlice) index).getFinish();
- try {
- //Convert negative indexes
- if(start < 0) {
- start = (int) aa.size() + start;
- }
- if(finish < 0) {
- finish = (int) aa.size() + finish;
- }
- return aa.slice(start, finish + 1, t);
- } catch (NumberFormatException e) {
- throw new CRECastException("Ranges must be integer numbers, i.e., [0..5]", t);
+ int start = (int) cslice.getStart();
+ int finish = (int) cslice.getFinish();
+
+ //Convert negative indexes
+ if(start < 0) {
+ start = (int) aa.size() + start;
+ }
+ if(finish < 0) {
+ finish = (int) aa.size() + finish;
}
+ return aa.slice(start, finish + 1, t);
} else if(index.isInstanceOf(CInt.TYPE)) {
return aa.get(ArgumentValidation.getInt32(index, t), t);
} else {
From 146f7e60531d924395d4175ad5629efadbf4907e Mon Sep 17 00:00:00 2001
From: Pieter12345
Date: Fri, 25 Mar 2022 05:46:04 +0100
Subject: [PATCH 2/4] Remove unreachable catch block in array_set
---
.../java/com/laytonsmith/core/functions/ArrayHandling.java | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
index 6e0aef18d..df9321ad3 100644
--- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
+++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
@@ -421,11 +421,7 @@ public Mixed execs(Target t, Environment env, Script parent, ParseTree... nodes)
@Override
public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntimeException {
if(args[0].isInstanceOf(CArray.TYPE)) {
- try {
- ((CArray) args[0]).set(args[1], args[2], t);
- } catch (IndexOutOfBoundsException e) {
- throw new CREIndexOverflowException("The index " + args[1].val() + " is out of bounds", t);
- }
+ ((CArray) args[0]).set(args[1], args[2], t);
return args[2];
}
throw new CRECastException("Argument 1 of " + this.getName() + " must be an array", t);
From 635577f494eb3a5ce5c47620a5b6963fb946a533 Mon Sep 17 00:00:00 2001
From: Pieter12345
Date: Fri, 25 Mar 2022 05:54:25 +0100
Subject: [PATCH 3/4] Remove unreachable catch block in array_set
---
.../java/com/laytonsmith/core/functions/ArrayHandling.java | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
index df9321ad3..8ac83c66e 100644
--- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
+++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
@@ -410,11 +410,7 @@ public Mixed execs(Target t, Environment env, Script parent, ParseTree... nodes)
if(!(array.isInstanceOf(CArray.TYPE))) {
throw new CRECastException("Argument 1 of " + this.getName() + " must be an array", t);
}
- try {
- ((CArray) array).set(index, value, t);
- } catch (IndexOutOfBoundsException e) {
- throw new CREIndexOverflowException("The index " + new CString(index).getQuote() + " is out of bounds", t);
- }
+ ((CArray) array).set(index, value, t);
return value;
}
From 360816703792527769e175efbeedc533898e74a7 Mon Sep 17 00:00:00 2001
From: Pieter12345
Date: Fri, 25 Mar 2022 07:00:46 +0100
Subject: [PATCH 4/4] Implement signatures for some ArrayHandling functions
---
.../core/functions/ArrayHandling.java | 262 ++++++++++++------
1 file changed, 177 insertions(+), 85 deletions(-)
diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
index 8ac83c66e..7963adfec 100644
--- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
+++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java
@@ -16,7 +16,9 @@
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.Script;
import com.laytonsmith.core.compiler.FileOptions;
-import com.laytonsmith.core.compiler.analysis.StaticAnalysis;
+import com.laytonsmith.core.compiler.signature.FunctionSignatures;
+import com.laytonsmith.core.compiler.signature.FunctionSignatures.MatchType;
+import com.laytonsmith.core.compiler.signature.SignatureBuilder;
import com.laytonsmith.core.constructs.CArray;
import com.laytonsmith.core.constructs.CBoolean;
import com.laytonsmith.core.constructs.CClassType;
@@ -100,12 +102,8 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 1) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- }
- return CInt.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CInt.TYPE).param(CArray.TYPE, "array", "The array to get the size of.").build();
}
@Override
@@ -288,17 +286,27 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 2 || argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(0), ArrayAccess.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireAnyType(argTypes.get(1),
- new CClassType[] {CInt.TYPE, CSlice.TYPE, CString.TYPE}, argTargets.get(1), env, exceptions);
- if(argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(2), Mixed.TYPE, argTargets.get(2), env, exceptions);
- }
- }
- return CClassType.AUTO;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CClassType.AUTO)
+ .param(ArrayAccess.TYPE, "array", "The array.")
+ .param(CInt.TYPE, "index", "The array index.")
+ .param(Mixed.TYPE, "default",
+ "The value that is returned if no element at the given index exists.", true)
+ .throwsEx(CREIndexOverflowException.class,
+ "When no element exists at the given index, and no default value is given.")
+ .newSignature(CClassType.AUTO)
+ .param(ArrayAccess.TYPE, "array", "The array.")
+ .param(CString.TYPE, "key", "The array index key.")
+ .param(Mixed.TYPE, "default",
+ "The value that is returned if no element at the given index exists.", true)
+ .throwsEx(CREIndexOverflowException.class,
+ "When no element exists at the given index, and no default value is given.")
+ .newSignature(CArray.TYPE, "An array containing the values selected by the slice.")
+ .param(ArrayAccess.TYPE, "array", "The array.")
+ .param(CSlice.TYPE, "indexRange", "The array index range slice.")
+ .throwsEx(CREIndexOverflowException.class,
+ "When no element exists at an index within the given range.")
+ .build();
}
@Override
@@ -424,16 +432,16 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireAnyType(argTypes.get(1),
- new CClassType[] {CInt.TYPE, CSlice.TYPE, CString.TYPE}, argTargets.get(1), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(2), Mixed.TYPE, argTargets.get(2), env, exceptions);
- return argTypes.get(2);
- }
- return CClassType.AUTO;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CClassType.AUTO, "The value that was set, to allow for chaining.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(CInt.TYPE, "index", "The array index.")
+ .param(Mixed.TYPE, "value", "The value to set.")
+ .newSignature(CClassType.AUTO, "The value that was set, to allow for chaining.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(CString.TYPE, "key", "The array index key.")
+ .param(Mixed.TYPE, "value", "The value to set.")
+ .build();
}
@Override
@@ -519,15 +527,12 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() >= 2) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- for(int i = 1; i < argTypes.size(); i++) {
- StaticAnalysis.requireType(argTypes.get(i), Mixed.TYPE, argTargets.get(i), env, exceptions);
- }
- }
- return CVoid.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CVoid.TYPE)
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "value", "The first value to push.")
+ .varParam(Mixed.TYPE, "values", "Additional values to push.")
+ .build();
}
@Override
@@ -627,14 +632,12 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(1), Mixed.TYPE, argTargets.get(1), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(2), CInt.TYPE, argTargets.get(2), env, exceptions);
- }
- return CVoid.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CVoid.TYPE)
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "value", "The value to insert.")
+ .param(CInt.TYPE, "index", "The array index at which to insert the value.")
+ .build();
}
@Override
@@ -708,13 +711,12 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommand
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 2) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(1), Mixed.TYPE, argTargets.get(1), env, exceptions);
- }
- return CBoolean.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CBoolean.TYPE, "{@code true} if a value {@code v} is in the array for"
+ + " which {@code v == value}, {@code false} otherwise.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "value", "The value to check for.")
+ .build();
}
@Override
@@ -818,13 +820,12 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 2) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(1), Mixed.TYPE, argTargets.get(1), env, exceptions);
- }
- return CBoolean.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CBoolean.TYPE, "{@code true} if a value {@code v} is in the array for"
+ + " which {@code equals_ic(v, value)}, {@code false} otherwise.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "value", "The value to check for.")
+ .build();
}
@Override
@@ -872,13 +873,12 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws CancelCommand
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 2) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(1), Mixed.TYPE, argTargets.get(1), env, exceptions);
- }
- return CBoolean.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CBoolean.TYPE, "{@code true} if a value {@code v} is in the array for"
+ + " which {@code v === value}, {@code false} otherwise.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "value", "The value to check for.")
+ .build();
}
@Override
@@ -1004,15 +1004,13 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() >= 1) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- for(int i = 1; i < argTypes.size(); i++) {
- StaticAnalysis.requireType(argTypes.get(i), Mixed.TYPE, argTargets.get(i), env, exceptions);
- }
- }
- return CBoolean.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CBoolean.TYPE,
+ "{@code true} if the index or indices exist(s), {@code false} otherwise.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "index", "The array index to check for.")
+ .varParam(Mixed.TYPE, "index", "Additional nested array indices to check for.")
+ .build();
}
@Override
@@ -1110,16 +1108,13 @@ public CArray exec(Target t, Environment env, Mixed... args) throws ConfigRuntim
}
@Override
- public CClassType getReturnType(Target t, List argTypes, List argTargets,
- Environment env, Set exceptions) {
- if(argTypes.size() == 2 || argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(0), CArray.TYPE, argTargets.get(0), env, exceptions);
- StaticAnalysis.requireType(argTypes.get(1), CInt.TYPE, argTargets.get(1), env, exceptions);
- if(argTypes.size() == 3) {
- StaticAnalysis.requireType(argTypes.get(2), Mixed.TYPE, argTargets.get(2), env, exceptions);
- }
- }
- return CArray.TYPE;
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE, "A reference to the passed array, to allow for chaining.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(CInt.TYPE, "size", "The size to enlarge the array to.")
+ .param(Mixed.TYPE, "fill",
+ "The value to fill the new indices with. Defaults to {@code null}.", true)
+ .build();
}
@Override
@@ -1204,6 +1199,15 @@ public CArray exec(Target t, Environment env, Mixed... args) throws ConfigRuntim
return ret;
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE)
+ .param(CInt.TYPE, "start", "The start value. Defaults to 0.", true)
+ .param(CInt.TYPE, "finish", "The finish value.")
+ .param(CInt.TYPE, "increment", "The value increment. Defaults to 1.", true)
+ .build();
+ }
+
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
@@ -1275,6 +1279,13 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE, "An array containing the array keys.")
+ .param(ArrayAccess.TYPE, "array", "The array.")
+ .build();
+ }
+
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
@@ -1341,6 +1352,13 @@ public Mixed exec(Target t, Environment env, Mixed... args) throws ConfigRuntime
}
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE, "The normalized array.")
+ .param(ArrayAccess.TYPE, "array", "The array to generate the normalized array for.")
+ .build();
+ }
+
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
@@ -1425,6 +1443,15 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
return newArray;
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE, "The array containing all entries from the given arrays.")
+ .param(ArrayAccess.TYPE, "array1", "The first array.")
+ .param(ArrayAccess.TYPE, "array2", "The second array.")
+ .varParam(ArrayAccess.TYPE, "arrays", "Additional arrays.")
+ .build();
+ }
+
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
@@ -1499,6 +1526,15 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
}
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(Mixed.TYPE, "The removed value, or {@code null} if nothing was removed.")
+ .param(CArray.TYPE, "array", "The array.")
+ .param(Mixed.TYPE, "index", "The array index.")
+ .throwsEx(CRECastException.class, "When the array is non-associative and the index is not an int.")
+ .build();
+ }
+
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
@@ -1569,6 +1605,14 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
return new CString(b.toString(), t);
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CString.TYPE, "The imploded array string.")
+ .param(ArrayAccess.TYPE, "array", "The array.")
+ .param(CString.TYPE, "glue", "The glue to place between glued values. Defaults to ' '.", true)
+ .build();
+ }
+
@Override
public MSVersion since() {
return MSVersion.V3_3_0;
@@ -1625,6 +1669,16 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
return new CString(b.toString(), t);
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CString.TYPE, "The imploded associative array string.")
+ .param(CArray.TYPE, "array", "The associative array.")
+ .param(CString.TYPE, "innerGlue", "The glue to place between the array keys and their values.")
+ .param(CString.TYPE, "outerGlue", "The glue to place between different key-value pairs.")
+ .throwsEx(CRECastException.class, "When a non-associative array is passed.")
+ .build();
+ }
+
@Override
public String getName() {
return "map_implode";
@@ -1701,6 +1755,14 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
return new CSlice(ArgumentValidation.getInt(args[0], t), ArgumentValidation.getInt(args[1], t), t);
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CSlice.TYPE)
+ .param(CInt.TYPE, "start", "The start value.")
+ .param(CInt.TYPE, "end", "The end value.")
+ .build();
+ }
+
@Override
public MSVersion since() {
return MSVersion.V3_3_1;
@@ -1777,6 +1839,21 @@ public Mixed exec(Target t, Environment environment, Mixed... args) throws Confi
return ca;
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE,
+ "A reference to the passed array, to allow for chaining.", MatchType.MATCH_FIRST)
+ .param(CArray.TYPE, "array", "The array.")
+ .param(CClosure.TYPE, "sortClosure", "A closure to which two values v1 and v2 are passed."
+ + " It should return {@code true} if {@code v1 > v2}, {@code true} if {@code v1 < v2}"
+ + " and {@code null} if {@code v1 == v2}.")
+ .newSignature(CArray.TYPE, "A reference to the passed array, to allow for chaining.")
+ .param(CArray.TYPE, "array", "The array.")
+ // TODO - Make this CArray.ArraySortType once this is a valid CClassType, and remove MATCH_FIRST.
+ .param(Mixed.TYPE, "sortType", "The array sort type.", true)
+ .build();
+ }
+
private CArray customSort(CArray ca, CClosure closure, Target t) {
if(ca.size() <= 1) {
return ca;
@@ -1988,6 +2065,21 @@ public void run() {
return CVoid.VOID;
}
+ @Override
+ public FunctionSignatures getSignatures() {
+ return new SignatureBuilder(CArray.TYPE,
+ "A reference to the passed array, to allow for chaining.", MatchType.MATCH_FIRST)
+ .param(CArray.TYPE, "array", "The array.")
+ .param(CClosure.TYPE, "sortClosure", "A closure to which two values v1 and v2 are passed."
+ + " It should return {@code true} if {@code v1 > v2}, {@code true} if {@code v1 < v2}"
+ + " and {@code null} if {@code v1 == v2}.")
+ .newSignature(CArray.TYPE, "A reference to the passed array, to allow for chaining.")
+ .param(CArray.TYPE, "array", "The array.")
+ // TODO - Make this CArray.ArraySortType once this is a valid CClassType, and remove MATCH_FIRST.
+ .param(Mixed.TYPE, "sortType", "The array sort type.", true)
+ .build();
+ }
+
@Override
public String getName() {
return "array_sort_async";