mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 23:31:35 +03:00
Avoid nulls in Array.items (#5736)
Put `Nothing` into an empty array rather than `null`. When running with `assert` on (unit tests), check the content of the array and `AssertError` quickly when a `null` is found.
This commit is contained in:
parent
dfea59c24d
commit
78aab133c7
@ -21,7 +21,7 @@ public class GetStackTraceNode extends Node {
|
|||||||
public static Array stackTraceToArray(Throwable exception) {
|
public static Array stackTraceToArray(Throwable exception) {
|
||||||
var elements = TruffleStackTrace.getStackTrace(exception);
|
var elements = TruffleStackTrace.getStackTrace(exception);
|
||||||
if (elements == null) return new Array();
|
if (elements == null) return new Array();
|
||||||
var ret = new Array(elements.size());
|
var ret = Array.allocate(elements.size());
|
||||||
for (int i = 0; i < elements.size(); i++) {
|
for (int i = 0; i < elements.size(); i++) {
|
||||||
var element = elements.get(i);
|
var element = elements.get(i);
|
||||||
ret.getItems()[i] = element.getGuestObject();
|
ret.getItems()[i] = element.getGuestObject();
|
||||||
|
@ -133,7 +133,7 @@ public abstract class Atom implements TruffleObject {
|
|||||||
public Array getMembers(boolean includeInternal) {
|
public Array getMembers(boolean includeInternal) {
|
||||||
Map<String, Function> members = constructor.getDefinitionScope().getMethods().get(constructor.getType());
|
Map<String, Function> members = constructor.getDefinitionScope().getMethods().get(constructor.getType());
|
||||||
if (members == null) {
|
if (members == null) {
|
||||||
return new Array(0);
|
return Array.allocate(0);
|
||||||
}
|
}
|
||||||
Object[] mems = members.keySet().toArray();
|
Object[] mems = members.keySet().toArray();
|
||||||
return new Array(mems);
|
return new Array(mems);
|
||||||
|
@ -39,6 +39,7 @@ public final class Array implements TruffleObject {
|
|||||||
description = "Creates an array with given elements.",
|
description = "Creates an array with given elements.",
|
||||||
autoRegister = false)
|
autoRegister = false)
|
||||||
public Array(Object... items) {
|
public Array(Object... items) {
|
||||||
|
assert noNulls(items);
|
||||||
this.items = items;
|
this.items = items;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,9 +50,25 @@ public final class Array implements TruffleObject {
|
|||||||
*/
|
*/
|
||||||
@Builtin.Method(
|
@Builtin.Method(
|
||||||
description = "Creates an uninitialized array of a given size.",
|
description = "Creates an uninitialized array of a given size.",
|
||||||
autoRegister = false)
|
autoRegister = false,
|
||||||
public Array(long size) {
|
name = "new")
|
||||||
this.items = new Object[(int) size];
|
public static Array allocate(long size) {
|
||||||
|
var arr = new Object[(int) size];
|
||||||
|
var ctx = EnsoContext.get(null);
|
||||||
|
var nothing = ctx.getBuiltins().nothing();
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
arr[i] = nothing;
|
||||||
|
}
|
||||||
|
return new Array(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final boolean noNulls(Object[] arr) {
|
||||||
|
for (int i = 0; i < arr.length; i++) {
|
||||||
|
if (arr[i] == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the elements of this array as a java array. */
|
/** @return the elements of this array as a java array. */
|
||||||
@ -107,7 +124,7 @@ public final class Array implements TruffleObject {
|
|||||||
/** @return an empty array */
|
/** @return an empty array */
|
||||||
@Builtin.Method(description = "Creates an empty Array", autoRegister = false)
|
@Builtin.Method(description = "Creates an empty Array", autoRegister = false)
|
||||||
public static Object empty() {
|
public static Object empty() {
|
||||||
return new Array();
|
return allocate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return an identity array */
|
/** @return an identity array */
|
||||||
|
@ -74,7 +74,7 @@ public final class Vector implements TruffleObject {
|
|||||||
long slice_end = Math.min(this_length, end);
|
long slice_end = Math.min(this_length, end);
|
||||||
|
|
||||||
if (slice_start >= slice_end) {
|
if (slice_start >= slice_end) {
|
||||||
return new Vector(new Array(0));
|
return new Vector(Array.allocate(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((slice_start == 0) && (slice_end == this_length)) {
|
if ((slice_start == 0) && (slice_end == this_length)) {
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.enso.interpreter.test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.enso.polyglot.RuntimeOptions;
|
||||||
|
import org.graalvm.polyglot.Context;
|
||||||
|
import org.graalvm.polyglot.Language;
|
||||||
|
import org.graalvm.polyglot.Source;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ArrayTest {
|
||||||
|
private Context ctx;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void prepareCtx() {
|
||||||
|
this.ctx = Context.newBuilder()
|
||||||
|
.allowExperimentalOptions(true)
|
||||||
|
.allowIO(true)
|
||||||
|
.allowAllAccess(true)
|
||||||
|
.logHandler(new ByteArrayOutputStream())
|
||||||
|
.option(
|
||||||
|
RuntimeOptions.LANGUAGE_HOME_OVERRIDE,
|
||||||
|
Paths.get("../../distribution/component").toFile().getAbsolutePath()
|
||||||
|
).build();
|
||||||
|
final Map<String, Language> langs = ctx.getEngine().getLanguages();
|
||||||
|
assertNotNull("Enso found: " + langs, langs.get("enso"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dontExposeNullsOutOfArray() throws Exception {
|
||||||
|
final URI facUri = new URI("memory://choose.enso");
|
||||||
|
final Source facSrc = Source.newBuilder("enso", """
|
||||||
|
from Standard.Base import all
|
||||||
|
|
||||||
|
null =
|
||||||
|
a = Array.new 1
|
||||||
|
b = a.at 0
|
||||||
|
b
|
||||||
|
""", "nulls.enso")
|
||||||
|
.uri(facUri)
|
||||||
|
.buildLiteral();
|
||||||
|
|
||||||
|
var module = ctx.eval(facSrc);
|
||||||
|
var res = module.invokeMember("eval_expression", "null");
|
||||||
|
assertTrue("i null", res.isNull());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user