Vector Type (#1133)

This commit is contained in:
Marcin Kostrzewa 2020-09-09 14:49:08 +02:00 committed by GitHub
parent a2accd3444
commit 6301542546
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 842 additions and 221 deletions

View File

@ -1,3 +1,5 @@
from Base import all
reverse_list = list ->
go = list -> acc -> case list of
Cons h t -> go t (Cons h acc)
@ -24,6 +26,11 @@ Number.times = act ->
res = here.reverse_list (go Nil this)
res
zeropad number =
txt = number.to_text
if number % 10 == number then "00" + txt else
if number % 100 == number then "0" + txt else txt
measure = ~act -> label -> iter_size -> num_iters ->
single_call = _ ->
x1 = System.nano_time
@ -34,5 +41,6 @@ measure = ~act -> label -> iter_size -> num_iters ->
act_it_num = num_iters - it_num
res = iter_size.times single_call
avg = here.avg_list res
IO.println (label + "/iteration:" + act_it_num.to_text + ": " + (avg/1000000).to_text + "ms")
fmt = (avg / 1000000).to_text + "." + here.zeropad ((avg / 1000) % 1000)
IO.println (label + "/iteration:" + act_it_num.to_text + ": " + fmt + "ms")
num_iters.times iteration

View File

@ -72,9 +72,12 @@ type List
list:
(Cons 0 <| Cons 1 <| Cons 2 <| Nil) . fold 0 (+)
fold : Any -> (Any -> Any -> Any) -> Any
fold init f = case this of
Nil -> init
Cons h t -> t.fold (f init h) f
fold init f =
go acc list = case list of
Nil -> acc
Cons h t -> go (f acc h) t
res = go init this
res
## Reverses the list, returning a list with the same elements, but in the
opposite order.

View File

@ -1,6 +1,46 @@
import Base.List
import Builtins
import Base.Vector
from Builtins import Number, Unit
from Builtins export all
from Base.List export Nil, Cons
from Base.Vector export Vector
## Represents a right-exclusive range of integer values.
type Range
type Range start end
## Applies a function to each element in the range.
> Example
To print all the numbers from 1 to 100 use:
1.upto 101 . each IO.println
each function =
it start end = if start == end then Unit else
function start
it start+1 end
it this.start this.end
Unit
## Combines all the elements of the range, by iteratively applying the
passed function with next elements of the range.
In general, the result of
Range start end . fold init f
is the same as
f (...(f (f init start) start+1)...) end-1
> Example
In the following example, we'll compute the sum of all elements of a
range:
Range 0 100 . fold 0 (+)
fold initial function =
it acc start end = if start == end then acc else
new_acc = function acc start
it new_acc start+1 end
res = it initial this.start this.end
res
## Creates a new right-exclusive range of integers from `this` to `n`.
Number.upto n = Range this n

View File

@ -1,5 +1,6 @@
import Base.Process.Exit_Code
from Builtins import System, True, False
from Base.Vector import Vector
from Builtins import Array, System, True, False
## The builder object that is used to create operating system processes.
type Process_Builder command arguments stdin
@ -16,7 +17,7 @@ type Process_Result exit_code stdout stderr
8
Process.execute : String -> Exit_Code
Process.execute command =
result = System.create_process command (arguments = []) (input = "") (redirectIn = True) (redirectOut = True) (redirectErr = True)
result = System.create_process command (arguments = Array.empty) (input = "") (redirectIn = True) (redirectOut = True) (redirectErr = True)
Exit_Code.from_number result.exit_code
## Call a command with a list of arguments.
@ -28,7 +29,7 @@ Process.execute command =
Hello!
Process.run_command : String -> Vector -> Exit_Code
Process.run_command command arguments =
result = System.create_process command arguments (input = "") (redirectIn = True) (redirectOut = True) (redirectErr = True)
result = System.create_process command arguments.to_array (input = "") (redirectIn = True) (redirectOut = True) (redirectErr = True)
Exit_Code.from_number result.exit_code
## Create a process using a builder returning the result of execution.
@ -41,5 +42,5 @@ Process.run_command command arguments =
Process_Result Exit_Success "test" ""
Process.create : Process_Builder -> Process_Result
Process.create b =
result = System.create_process b.command b.arguments b.stdin (redirectIn = False) (redirectOut = False) (redirectErr = False)
result = System.create_process b.command b.arguments.to_array b.stdin (redirectIn = False) (redirectOut = False) (redirectErr = False)
Process_Result (Exit_Code.from_number result.exit_code) result.stdout result.stderr

View File

@ -0,0 +1,106 @@
from Builtins import Array
from Base import all
## The basic, immutable, vector type.
A vector allows to store an arbitrary number of elements, in linear memory.
It is the recommended data structure for most applications.
> Example
A vector containing the elements `1`, `2`, and `3`, in this order is:
[1, 2, 3]
> Example
A vector containing 50 elements, each being the number `42`, can be
created by:
Vector.fill length=50 item=42
type Vector
type Vector to_array
## Gets an element from the vector at a specified index (0-based).
> Example
To get the second element of the vector `[1, 2, 3]`, use:
[1, 2, 3].at 1
at : Number -> Any
at index = this.to_array.at index
## Returns the number of elements stored in this vector.
length : Number
length = this.to_array.length
## Combines all the elements of the vector, by iteratively applying the
passed function with next elements of the vector.
In general, the result of
[l0, l1, ..., ln] . fold init f
is the same as
f (...(f (f init l0) l1)...) ln
> Example
In the following example, we'll compute the sum of all elements of a
vector:
[0, 1, 2] . fold 0 (+)
fold : Any -> (Any -> Any -> Any) -> Any
fold initial function =
arr = this.to_array
f = acc -> ix -> function acc (arr.at ix)
res = 0.upto this.length . fold initial f
res
## Creates a new vector of the given length, initializing elements using
the provided constructor function.
The constructor function is called with the consecutive indices
(0-based) of the vector elements.
> Example
To create a vector containing the numbers 1 through 50:
Vector.new 50 (ix -> ix + 1)
> Example
To create a copy of the given vector (`my_vec`):
Vector.new my_vec.length (ix -> my_vec.at ix)
new : Number -> (Number -> Any) -> Vector
new length constructor =
arr = Array.new length
0.upto length . each ix-> arr.set_at ix (constructor ix)
Vector arr
## Creates a new vector of the given length, filling the elements with
the provided constant.
> Example
A vector containing 50 elements, each being the number `42`, can be
created by:
Vector.fill length=50 item=42
fill : Number -> Any -> Vector
fill length item =
arr = Array.new length
0.upto length . each ix-> arr.set_at ix item
Vector arr
## Applies a function to each element of the vector, returning the vector of
results.
> Example
In the following example, we add `1` to each element of the vector:
[1, 2, 3] . map +1
The result of running the code above is:
[2, 3, 4]
map : (Any -> Any) -> Vector
map function =
arr = this.to_array
new_arr = Array.new arr.length
0.upto arr.length . each ix-> new_arr.set_at ix (function (arr.at ix))
Vector new_arr
## Generates a human-readable text representation of the vector.
to_text : Text
to_text =
arr = this.to_array
if arr.length == 0 then "[]" else
if arr.length == 1 then "[" + (arr.at 0 . to_text) + "]" else
folder = str -> ix -> str + ", " + (arr.at ix).to_text
tail_elems = 1.upto arr.length . fold "" folder
"[" + (arr.at 0 . to_text) + tail_elems + "]"

View File

@ -16,6 +16,7 @@ import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.MethodDoesNotExistException;
import org.enso.interpreter.runtime.error.RuntimeError;
@ -157,6 +158,16 @@ public abstract class MethodResolverNode extends Node {
return function;
}
@Specialization(guards = "cachedSymbol == symbol")
Function resolveArray(
UnresolvedSymbol symbol,
Array self,
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
@Cached(value = "resolveMethodOnArray(cachedSymbol)", allowUncached = true)
Function function) {
return function;
}
@Specialization(guards = {"cachedSymbol == symbol", "ctx.getEnvironment().isHostObject(target)"})
Function resolveHost(
UnresolvedSymbol symbol,
@ -220,11 +231,18 @@ public abstract class MethodResolverNode extends Node {
return ensureMethodExists(symbol.resolveFor(getBuiltins().any()), "Error", symbol);
}
Function resolveMethodOnArray(UnresolvedSymbol symbol) {
return ensureMethodExists(
symbol.resolveFor(getBuiltins().array().constructor(), getBuiltins().any()),
"Array",
symbol);
}
Function buildHostResolver(UnresolvedSymbol symbol, Context context) {
if (symbol.getName().equals("new")) {
return context.getBuiltins().getConstructorDispatch();
} else {
return context.getBuiltins().buildPolyglotMethodDispatch(symbol.getName());
return context.getBuiltins().buildPolyglotMethodDispatch(symbol);
}
}

View File

@ -4,7 +4,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.NodeInfo;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
@NodeInfo(shortName = "[]", description = "Creates a vector from given expressions.")
public class SequenceLiteralNode extends ExpressionNode {
@ -28,7 +28,7 @@ public class SequenceLiteralNode extends ExpressionNode {
* Executes the node.
*
* @param frame the stack frame for execution.
* @return a {@link Vector} containing the results of evaluating child expressions.
* @return a {@link Array} containing the results of evaluating child expressions.
*/
@Override
@ExplodeLoop
@ -37,6 +37,6 @@ public class SequenceLiteralNode extends ExpressionNode {
for (int i = 0; i < items.length; i++) {
itemValues[i] = items[i].executeGeneric(frame);
}
return new Vector(itemValues);
return new Array(itemValues);
}
}

View File

@ -0,0 +1,13 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(type = "Array", name = "empty", description = "Creates an empty array.")
public class EmptyNode extends Node {
Object execute(Object _this) {
return new Array();
}
}

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "at",
description = "Gets an array element at the given index.")
public class GetAtNode extends Node {
Object execute(Array _this, long index) {
return _this.getItems()[(int) index];
}
}

View File

@ -0,0 +1,13 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(type = "Array", name = "length", description = "Returns the length of an array.")
public class LengthNode extends Node {
long execute(Array _this) {
return _this.getItems().length;
}
}

View File

@ -0,0 +1,15 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "new_1",
description = "Creates an array with one given element.")
public class New1Node extends Node {
Object execute(Object _this, Object item_1) {
return new Array(item_1);
}
}

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "new_2",
description = "Creates an array with two given elements.")
public class New2Node extends Node {
Object execute(Object _this, Object item_1, Object item_2) {
return new Array(item_1, item_2);
}
}

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "new_3",
description = "Creates an array with three given elements.")
public class New3Node extends Node {
Object execute(Object _this, Object item_1, Object item_2, Object item_3) {
return new Array(item_1, item_2, item_3);
}
}

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "new_4",
description = "Creates an array with four given elements.")
public class New4Node extends Node {
Object execute(Object _this, Object item_1, Object item_2, Object item_3, Object item_4) {
return new Array(item_1, item_2, item_3, item_4);
}
}

View File

@ -0,0 +1,16 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "new",
description = "Creates an uninitialized array of a given size.")
public class NewNode extends Node {
Object execute(Object _this, long size) {
return new Array(size);
}
}

View File

@ -0,0 +1,17 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Array",
name = "set_at",
description = "Puts the given element in the given position in the array.")
public class SetAtNode extends Node {
Object execute(Array _this, long index, Object value) {
_this.getItems()[(int) index] = value;
return _this;
}
}

View File

@ -0,0 +1,15 @@
package org.enso.interpreter.node.expression.builtin.array;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
@BuiltinMethod(
type = "Array",
name = "to_array",
description = "Identity on arrays, implemented for protocol completeness.")
public class ToArrayNode extends Node {
Object execute(Object _this) {
return _this;
}
}

View File

@ -1,25 +1,15 @@
package org.enso.interpreter.node.expression.builtin.interop.generic;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.Language;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.state.Stateful;
import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "Polyglot",
@ -30,7 +20,7 @@ public class ExecuteNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create();
Object execute(Object _this, Object callable, Vector arguments) {
Object execute(Object _this, Object callable, Array arguments) {
try {
return library.execute(callable, arguments.getItems());
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) {

View File

@ -8,7 +8,7 @@ import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
@ -21,7 +21,7 @@ public class InstantiateNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create();
Object execute(Object _this, Object constructor, Vector arguments) {
Object execute(Object _this, Object constructor, Array arguments) {
try {
return library.instantiate(constructor, arguments.getItems());
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) {

View File

@ -5,7 +5,7 @@ import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
@ -17,7 +17,7 @@ public class InvokeNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create();
Object execute(Object _this, Object target, String name, Vector arguments) {
Object execute(Object _this, Object target, String name, Array arguments) {
try {
return library.invokeMember(target, name, arguments.getItems());
} catch (UnsupportedMessageException

View File

@ -54,7 +54,7 @@ public class ConstructorDispatchNode extends BuiltinRootNode {
Object cons = args[0];
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
try {
Object[] arguments = TypesGen.expectVector(args[1]).getItems();
Object[] arguments = TypesGen.expectArray(args[1]).getItems();
Object res = library.instantiate(cons, arguments);
return new Stateful(state, res);
} catch (UnsupportedMessageException

View File

@ -1,5 +1,9 @@
package org.enso.interpreter.node.expression.builtin.interop.syntax;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.ReportPolymorphism;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.*;
import com.oracle.truffle.api.nodes.NodeInfo;
@ -7,15 +11,19 @@ import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants;
import org.enso.interpreter.Language;
import org.enso.interpreter.node.callable.InvokeCallableNode;
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.state.Stateful;
import org.enso.interpreter.runtime.type.TypesGen;
@NodeInfo(shortName = "<polyglot_dispatch>", description = "Invokes a polyglot method by name.")
public class MethodDispatchNode extends BuiltinRootNode {
private MethodDispatchNode(Language language) {
@ReportPolymorphism
public abstract class MethodDispatchNode extends BuiltinRootNode {
MethodDispatchNode(Language language) {
super(language);
}
@ -23,6 +31,12 @@ public class MethodDispatchNode extends BuiltinRootNode {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create();
private @Child InvokeCallableNode invokeCallableNode =
InvokeCallableNode.build(
new CallArgumentInfo[] {new CallArgumentInfo()},
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED);
/**
* Creates an instance of this node.
*
@ -30,7 +44,7 @@ public class MethodDispatchNode extends BuiltinRootNode {
* @return a function wrapping this node
*/
public static MethodDispatchNode build(Language language) {
return new MethodDispatchNode(language);
return MethodDispatchNodeGen.create(language);
}
/**
@ -39,16 +53,21 @@ public class MethodDispatchNode extends BuiltinRootNode {
* @param frame current execution frame.
* @return the result of converting input into a string.
*/
@Override
public Stateful execute(VirtualFrame frame) {
@Specialization(guards = "symbol == cachedSymbol")
public Stateful run(
VirtualFrame frame,
@Bind("getSymbol(frame)") UnresolvedSymbol symbol,
@Cached("symbol") UnresolvedSymbol cachedSymbol,
@Cached("buildToArray(cachedSymbol)") UnresolvedSymbol toArray) {
Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
Object callable = args[0];
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
Object arguments = args[2];
Stateful casted = invokeCallableNode.execute(toArray, frame, state, new Object[] {arguments});
try {
String method = TypesGen.expectString(args[1]);
Object[] arguments = TypesGen.expectVector(args[2]).getItems();
Object res = library.invokeMember(callable, method, arguments);
return new Stateful(state, res);
Object[] castedArgs = TypesGen.expectArray(casted.getValue()).getItems();
Object res = library.invokeMember(callable, symbol.getName(), castedArgs);
return new Stateful(casted.getState(), res);
} catch (UnsupportedMessageException
| ArityException
| UnsupportedTypeException
@ -59,6 +78,15 @@ public class MethodDispatchNode extends BuiltinRootNode {
}
}
UnresolvedSymbol buildToArray(UnresolvedSymbol originalSymbol) {
return UnresolvedSymbol.build("to_array", originalSymbol.getScope());
}
UnresolvedSymbol getSymbol(VirtualFrame frame) {
return TypesGen.asUnresolvedSymbol(
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
}
/**
* Returns a language-specific name for this node.
*

View File

@ -8,7 +8,7 @@ import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.Language;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
import java.io.*;
@ -26,7 +26,7 @@ public abstract class CreateProcessNode extends Node {
abstract Object execute(
Object _this,
String command,
Vector arguments,
Array arguments,
String input,
boolean redirectIn,
boolean redirectOut,
@ -37,15 +37,15 @@ public abstract class CreateProcessNode extends Node {
Object doCreate(
Object _this,
String command,
Vector arguments,
Array arguments,
String input,
boolean redirectIn,
boolean redirectOut,
boolean redirectErr,
@CachedContext(Language.class) Context ctx) {
String[] cmd = new String[(int) arguments.getArraySize() + 1];
String[] cmd = new String[(int) arguments.getItems().length + 1];
cmd[0] = command;
System.arraycopy(arguments.getItems(), 0, cmd, 1, (int) arguments.getArraySize());
System.arraycopy(arguments.getItems(), 0, cmd, 1, (int) arguments.getItems().length);
TruffleProcessBuilder pb = ctx.getEnvironment().newProcessBuilder(cmd);
try {

View File

@ -24,7 +24,7 @@ import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.callable.CallerInfo;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.scope.LocalScope;
import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.type.Types;
@ -454,7 +454,7 @@ public class Module implements TruffleObject {
*/
@ExportMessage
Object getMembers(boolean includeInternal) {
return new Vector(
return new Array(
MethodNames.Module.GET_METHOD,
MethodNames.Module.GET_CONSTRUCTOR,
MethodNames.Module.REPARSE,

View File

@ -0,0 +1,37 @@
package org.enso.interpreter.runtime.builtin;
import org.enso.interpreter.Language;
import org.enso.interpreter.node.expression.builtin.array.*;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.scope.ModuleScope;
/** Container for builtin array-related types and functions. */
public class Array {
private final AtomConstructor array;
/**
* Creates a new instance of this class, registering all relevant bindings in the provided scope.
*
* @param language the current language instance.
* @param scope the scope for builtin methods.
*/
public Array(Language language, ModuleScope scope) {
array = new AtomConstructor("Array", scope).initializeFields();
scope.registerConstructor(array);
scope.registerMethod(array, "empty", EmptyMethodGen.makeFunction(language));
scope.registerMethod(array, "new", NewMethodGen.makeFunction(language));
scope.registerMethod(array, "new_1", New1MethodGen.makeFunction(language));
scope.registerMethod(array, "new_2", New2MethodGen.makeFunction(language));
scope.registerMethod(array, "new_3", New3MethodGen.makeFunction(language));
scope.registerMethod(array, "new_4", New4MethodGen.makeFunction(language));
scope.registerMethod(array, "length", LengthMethodGen.makeFunction(language));
scope.registerMethod(array, "to_array", ToArrayMethodGen.makeFunction(language));
scope.registerMethod(array, "at", GetAtMethodGen.makeFunction(language));
scope.registerMethod(array, "set_at", SetAtMethodGen.makeFunction(language));
}
/** @return the Array constructor. */
public AtomConstructor constructor() {
return array;
}
}

View File

@ -22,6 +22,7 @@ import org.enso.interpreter.node.expression.builtin.thread.WithInterruptHandlerM
import org.enso.interpreter.node.expression.builtin.unsafe.SetAtomFieldMethodGen;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
@ -52,6 +53,7 @@ public class Builtins {
private final Error error;
private final Bool bool;
private final System system;
private final Array array;
private final RootCallTarget interopDispatchRoot;
private final FunctionSchema interopDispatchSchema;
@ -72,6 +74,7 @@ public class Builtins {
number = new AtomConstructor("Number", scope).initializeFields();
bool = new Bool(language, scope);
error = new Error(language, scope);
array = new Array(language, scope);
function = new AtomConstructor("Function", scope).initializeFields();
text = new AtomConstructor("Text", scope).initializeFields();
debug = new AtomConstructor("Debug", scope).initializeFields();
@ -258,6 +261,10 @@ public class Builtins {
return system;
}
/** @return the container for array-related builtins. */
public Array array() {
return array;
}
/**
* Returns the builtin module scope.
@ -275,10 +282,10 @@ public class Builtins {
/**
* Builds a function dispatching to a polyglot method call.
*
* @param method the name of the method this function will dispatch to.
* @param method the name and scope of the method this function will dispatch to.
* @return a function calling {@code method} with given arguments.
*/
public Function buildPolyglotMethodDispatch(String method) {
public Function buildPolyglotMethodDispatch(UnresolvedSymbol method) {
Object[] preAppliedArr = new Object[] {null, method, null};
return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null);
}

View File

@ -33,15 +33,17 @@ public class UnresolvedSymbol implements TruffleObject {
/**
* Gets the symbol name.
*
* <p>All names for dynamic symbols are interned, making it safe to compare symbol names using the
* standard {@code ==} equality operator.
*
* @return the name of this symbol
*/
public String getName() {
return name;
}
/** @return the scope this symbol was used in. */
public ModuleScope getScope() {
return scope;
}
/**
* Resolves the symbol for a given hierarchy of constructors.
*

View File

@ -26,7 +26,7 @@ import org.enso.interpreter.runtime.callable.CallerInfo;
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.argument.Thunk;
import org.enso.interpreter.runtime.state.data.EmptyMap;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.type.Types;
import org.enso.polyglot.MethodNames;
@ -272,7 +272,7 @@ public final class Function implements TruffleObject {
*/
@ExportMessage
Object getMembers(boolean includeInternal) {
return new Vector(MethodNames.Function.EQUALS);
return new Array(MethodNames.Function.EQUALS);
}
/**

View File

@ -1,27 +1,35 @@
package org.enso.interpreter.runtime.data;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
/** An immutable array-like collection. */
/** A primitve boxed array type for use in the runtime. */
@ExportLibrary(InteropLibrary.class)
public class Vector implements TruffleObject {
private final @CompilerDirectives.CompilationFinal(dimensions = 1) Object[] items;
public class Array implements TruffleObject {
private final Object[] items;
/**
* Creates a new Vector
* Creates a new array
*
* @param items the element values
*/
public Vector(Object... items) {
public Array(Object... items) {
this.items = items;
}
/** @return the elements of this vector as an array. */
/**
* Creates an uninitialized array of the given size.
*
* @param size the size of the created array.
*/
public Array(long size) {
this.items = new Object[(int) size];
}
/** @return the elements of this array as a java array. */
public Object[] getItems() {
return items;
}
@ -57,7 +65,7 @@ public class Vector implements TruffleObject {
* @return
*/
@ExportMessage
public long getArraySize() {
long getArraySize() {
return items.length;
}
@ -68,7 +76,22 @@ public class Vector implements TruffleObject {
* @return {@code true} if the index is valid, {@code false} otherwise.
*/
@ExportMessage
public boolean isArrayElementReadable(long index) {
boolean isArrayElementReadable(long index) {
return index < getArraySize() && index >= 0;
}
@ExportMessage
void writeArrayElement(long index, Object value) {
items[(int) index] = value;
}
@ExportMessage
boolean isArrayElementModifiable(long index) {
return isArrayElementReadable(index);
}
@ExportMessage
boolean isArrayElementInsertable(long index) {
return false;
}
}

View File

@ -12,7 +12,7 @@ import org.enso.interpreter.Language;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.type.Types;
import org.enso.pkg.QualifiedName;
import org.enso.pkg.QualifiedName$;
@ -130,8 +130,8 @@ public class TopLevelScope implements TruffleObject {
* @return a collection of all the exported members.
*/
@ExportMessage
Vector getMembers(boolean includeInternal) {
return new Vector(
Array getMembers(boolean includeInternal) {
return new Array(
MethodNames.TopScope.GET_MODULE,
MethodNames.TopScope.CREATE_MODULE,
MethodNames.TopScope.REGISTER_MODULE,

View File

@ -5,15 +5,14 @@ import com.oracle.truffle.api.dsl.ImplicitCast;
import com.oracle.truffle.api.dsl.TypeSystem;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
import org.enso.interpreter.runtime.callable.argument.Thunk;
import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.Vector;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.RuntimeError;
import java.util.Optional;
/**
* This class defines the interpreter-level type system for Enso.
*
@ -33,7 +32,8 @@ import java.util.Optional;
AtomConstructor.class,
Thunk.class,
RuntimeError.class,
Vector.class
UnresolvedSymbol.class,
Array.class
})
public class Types {
@ -118,8 +118,8 @@ public class Types {
return "Thunk";
} else if (TypesGen.isRuntimeError(value)) {
return "Error " + TypesGen.asRuntimeError(value).getPayload().toString();
} else if (TypesGen.isVector(value)) {
return "Vector";
} else if (TypesGen.isArray(value)) {
return "Array";
} else {
return null;
}

View File

@ -45,6 +45,7 @@ class Passes(passes: Option[List[PassGroup]] = None) {
TypeSignatures,
AliasAnalysis,
UppercaseNames,
VectorLiterals,
AliasAnalysis,
LambdaConsolidate,
AliasAnalysis,

View File

@ -1136,7 +1136,7 @@ class IrToTruffle(
argumentExpression.setTail(argExpressionIsTail)
val displayName =
s"argument<${name.getOrElse(String.valueOf(position))}>"
s"argument<${name.map(_.name).getOrElse(String.valueOf(position))}>"
val section = value.location
.map(loc => source.createSection(loc.start, loc.end))

View File

@ -5302,6 +5302,12 @@ object IR {
def explain(originalName: IR.Name): String
}
case object UnresolvedSequenceMacro extends Reason {
override def explain(originalName: Name): String =
"No definition for the sequence macro could be found. Try" +
" importing the default definition from the Base.Vector module."
}
/**
* An error coming from an unexpected occurence of a polyglot symbol.
*
@ -5310,7 +5316,7 @@ object IR {
*/
case class UnexpectedPolyglot(context: String) extends Reason {
override def explain(originalName: Name): String =
s"The name ${originalName.name} resolved to a polyglot symbol," +
s"The name ${originalName.name} resolved to a polyglot symbol, " +
s"but polyglot symbols are not allowed in $context."
}
@ -5322,7 +5328,7 @@ object IR {
*/
case class UnexpectedMethod(context: String) extends Reason {
override def explain(originalName: Name): String =
s"The name ${originalName.name} resolved to a method," +
s"The name ${originalName.name} resolved to a method, " +
s"but methods are not allowed in $context."
}

View File

@ -57,14 +57,13 @@ case class BindingsMap(
}
private def findLocalCandidates(name: String): List[ResolvedName] = {
if (currentModule.getName.item == name) {
val conses = findConstructorCandidates(name)
val polyglot = findPolyglotCandidates(name)
val methods = findMethodCandidates(name)
val all = conses ++ polyglot ++ methods
if (all.isEmpty && currentModule.getName.item == name) {
List(ResolvedModule(currentModule))
} else {
val conses = findConstructorCandidates(name)
val polyglot = findPolyglotCandidates(name)
val methods = findMethodCandidates(name)
conses ++ polyglot ++ methods
}
} else { all }
}
private def findQualifiedImportCandidates(

View File

@ -0,0 +1,108 @@
package org.enso.compiler.pass.resolve
import org.enso.compiler.context.{InlineContext, ModuleContext}
import org.enso.compiler.core.IR
import org.enso.compiler.core.ir.MetadataStorage.ToPair
import org.enso.compiler.data.BindingsMap
import org.enso.compiler.pass.IRPass
import org.enso.compiler.pass.analyse.BindingAnalysis
case object VectorLiterals extends IRPass {
/** The type of the metadata object that the pass writes to the IR. */
override type Metadata = IRPass.Metadata.Empty
/** The type of configuration for the pass. */
override type Config = IRPass.Configuration.Default
/** The passes that this pass depends _directly_ on to run. */
override val precursorPasses: Seq[IRPass] = Seq(UppercaseNames)
/** The passes that are invalidated by running this pass. */
override val invalidatedPasses: Seq[IRPass] = Seq()
/** Executes the pass on the provided `ir`, and returns a possibly transformed
* or annotated version of `ir`.
*
* @param ir the Enso IR to process
* @param moduleContext a context object that contains the information needed
* to process a module
* @return `ir`, possibly having made transformations or annotations to that
* IR.
*/
override def runModule(
ir: IR.Module,
moduleContext: ModuleContext
): IR.Module = {
val bindings = ir.unsafeGetMetadata(
BindingAnalysis,
"no bindings analysis on the current module"
)
val vec = vectorCons(bindings)
ir.mapExpressions(doExpression(_, vec))
}
/** Executes the pass on the provided `ir`, and returns a possibly transformed
* or annotated version of `ir` in an inline context.
*
* @param ir the Enso IR to process
* @param inlineContext a context object that contains the information needed
* for inline evaluation
* @return `ir`, possibly having made transformations or annotations to that
* IR.
*/
override def runExpression(
ir: IR.Expression,
inlineContext: InlineContext
): IR.Expression = {
val bindings = inlineContext.module.getIr.unsafeGetMetadata(
BindingAnalysis,
"no bindings analysis on the current module"
)
val vec = vectorCons(bindings)
doExpression(ir, vec)
}
private def vectorCons(bindings: BindingsMap): IR.Expression = {
val module = bindings.resolvedImports
.flatMap(imp =>
imp.module :: imp.module.getIr
.unsafeGetMetadata(
BindingAnalysis,
"no binding analyis on an imported module"
)
.resolvedExports
.map(_.module)
)
.find(_.getName.toString == "Base.Vector")
val name = IR.Name.Literal("<Sequence Macro>", isReferent = true, None)
module
.map { module =>
val withRes = name.updateMetadata(
UppercaseNames -->> BindingsMap.Resolution(
BindingsMap
.ResolvedConstructor(module, BindingsMap.Cons("Vector", 1))
)
)
withRes
}
.getOrElse {
IR.Error.Resolution(name, IR.Error.Resolution.UnresolvedSequenceMacro)
}
}
private def doExpression(
ir: IR.Expression,
vec: IR.Expression
): IR.Expression =
ir.transformExpressions {
case seq: IR.Application.Literal.Sequence =>
val trans = seq.mapExpressions(doExpression(_, vec))
IR.Application.Prefix(
vec,
List(IR.CallArgument.Specified(None, trans, None, None)),
false,
None
)
}
}

View File

@ -3,4 +3,4 @@ from TestNonImportedOverloads.Util import all
X.method = 10
Main.main = Unit.util (X 1)
main = Unit.util (X 1)

View File

@ -5,4 +5,4 @@ type X a
X.method = 10
Main.main = Unit.util (X 1)
main = Unit.util (X 1)

View File

@ -1,3 +1,3 @@
from TestSimpleImports.Atom import all
Main.main = (X 1).method
main = (X 1).method

View File

@ -1,3 +1,3 @@
from Test_Hiding_Error.Atom import all hiding X
Main.main = (X 1).method
main = (X 1).method

View File

@ -1,3 +1,3 @@
from Test_Hiding_Success.Atom import all hiding Y
Main.main = (X 1).method
main = (X 1).method

View File

@ -1,3 +1,3 @@
import Test_Qualified_Error.Atom
Main.main = (X 1).method
main = (X 1).method

View File

@ -1,3 +1,3 @@
import Test_Rename.Atom as Def
Main.main = (Def.X 1).method
main = (Def.X 1).method

View File

@ -1,3 +1,3 @@
import Test_Rename_Error.Atom as Def
Main.main = (Atom.X 1).method
main = (Atom.X 1).method

View File

@ -856,21 +856,28 @@ class DataflowAnalysisTest extends CompilerTest {
val depInfo = ir.getMetadata(DataflowAnalysis).get
val vector = ir.body
val callArg = ir.body
.asInstanceOf[IR.Application.Prefix]
.arguments(0)
val vector = callArg.value
.asInstanceOf[IR.Application.Literal.Sequence]
val xDefId = mkStaticDep(ir.arguments(0).getId)
val xUseId = mkStaticDep(vector.items(0).getId)
val yId = mkStaticDep(vector.items(1).getId)
val litId = mkStaticDep(vector.items(2).getId)
val vecId = mkStaticDep(vector.getId)
val lamId = mkStaticDep(ir.getId)
val xDefId = mkStaticDep(ir.arguments(0).getId)
val xUseId = mkStaticDep(vector.items(0).getId)
val yId = mkStaticDep(vector.items(1).getId)
val litId = mkStaticDep(vector.items(2).getId)
val vecId = mkStaticDep(vector.getId)
val callArgId = mkStaticDep(callArg.getId)
val appId = mkStaticDep(ir.body.getId)
val lamId = mkStaticDep(ir.getId)
depInfo.getDirect(xDefId) shouldEqual Some(Set(xUseId))
depInfo.getDirect(xUseId) shouldEqual Some(Set(vecId))
depInfo.getDirect(yId) shouldEqual Some(Set(vecId))
depInfo.getDirect(litId) shouldEqual Some(Set(vecId))
depInfo.getDirect(vecId) shouldEqual Some(Set(lamId))
depInfo.getDirect(vecId) shouldEqual Some(Set(callArgId))
depInfo.getDirect(callArgId) shouldEqual Some(Set(appId))
depInfo.getDirect(appId) shouldEqual Some(Set(lamId))
}
"work properly for typeset literals" in {

View File

@ -150,6 +150,9 @@ class DemandAnalysisTest extends CompilerTest {
val vec = ir
.asInstanceOf[IR.Function.Lambda]
.body
.asInstanceOf[IR.Application.Prefix]
.arguments(0)
.value
.asInstanceOf[IR.Application.Literal.Sequence]
vec.items(0) shouldBe an[IR.Application.Force]

View File

@ -0,0 +1,102 @@
package org.enso.compiler.test.pass.resolve
import org.enso.compiler.Passes
import org.enso.compiler.context.{FreshNameSupply, ModuleContext}
import org.enso.compiler.core.IR
import org.enso.compiler.pass.PassConfiguration.ToPair
import org.enso.compiler.pass.analyse.AliasAnalysis
import org.enso.compiler.pass.optimise.ApplicationSaturation
import org.enso.compiler.pass.resolve.VectorLiterals
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
import org.enso.compiler.test.CompilerTest
class VectorLiteralsTest extends CompilerTest {
// === Test Setup ===========================================================
def mkModuleContext: ModuleContext =
buildModuleContext(
freshNameSupply = Some(new FreshNameSupply)
)
val passes = new Passes
val precursorPasses: PassGroup =
passes.getPrecursors(VectorLiterals).get
val passConfiguration: PassConfiguration = PassConfiguration(
AliasAnalysis -->> AliasAnalysis.Configuration(),
ApplicationSaturation -->> ApplicationSaturation.Configuration()
)
implicit val passManager: PassManager =
new PassManager(List(precursorPasses), passConfiguration)
/** Adds an extension method to analyse an Enso module.
*
* @param ir the ir to analyse
*/
implicit class AnalyseModule(ir: IR.Module) {
/** Performs tail call analysis on [[ir]].
*
* @param context the module context in which analysis takes place
* @return [[ir]], with tail call analysis metadata attached
*/
def analyse(implicit context: ModuleContext) = {
VectorLiterals.runModule(ir, context)
}
}
// === The Tests ============================================================
"Pattern resolution" should {
implicit val ctx: ModuleContext = mkModuleContext
val ir =
"""
|foo (x = [1, 2, 3]) =
| foo = ["foo", bar, [1,2,3]]
| x
|
|""".stripMargin.preprocessModule.analyse
"transform vector literals into applications" in {
val fun = ir
.bindings(0)
.asInstanceOf[IR.Module.Scope.Definition.Method.Explicit]
.body
.asInstanceOf[IR.Function.Lambda]
val arg = fun.arguments(1).defaultValue.get
arg shouldBe an[IR.Application.Prefix]
arg
.asInstanceOf[IR.Application.Prefix]
.arguments(0)
.value shouldBe an[IR.Application.Literal.Sequence]
val bodyLiteral = fun.body
.asInstanceOf[IR.Expression.Block]
.expressions(0)
.asInstanceOf[IR.Expression.Binding]
.expression
bodyLiteral shouldBe an[IR.Application.Prefix]
val outerVec =
bodyLiteral.asInstanceOf[IR.Application.Prefix].arguments(0).value
outerVec shouldBe an[IR.Application.Literal.Sequence]
val innerLiteral =
outerVec.asInstanceOf[IR.Application.Literal.Sequence].items(2)
innerLiteral shouldBe an[IR.Application.Prefix]
innerLiteral
.asInstanceOf[IR.Application.Prefix]
.arguments(0)
.value shouldBe an[IR.Application.Literal.Sequence]
}
}
}

View File

@ -1197,10 +1197,10 @@ class RuntimeServerTest
val idMain = metadata.addItem(32, 35)
val idMainA = metadata.addItem(41, 8)
val idMainP = metadata.addItem(54, 12)
val idPie = metadata.addItem(71 + 8, 1)
val idUwu = metadata.addItem(84 + 8, 1)
val idHie = metadata.addItem(97 + 8, 6)
val idXxx = metadata.addItem(117 + 8, 1)
val idPie = metadata.addItem(66 + 8, 1)
val idUwu = metadata.addItem(74 + 8, 1)
val idHie = metadata.addItem(82 + 8, 6)
val idXxx = metadata.addItem(102 + 8, 1)
val code =
"""from Builtins import all
|
@ -1208,9 +1208,9 @@ class RuntimeServerTest
| a = 123 + 21
| IO.println a
|
|Main.pie = 3
|Main.uwu = 7
|Main.hie = "hie!"
|pie = 3
|uwu = 7
|hie = "hie!"
|Number.x y = y
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
@ -1399,7 +1399,7 @@ class RuntimeServerTest
Seq(
TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)),
"Main.pie"
"here.pie"
)
)
)
@ -1430,7 +1430,7 @@ class RuntimeServerTest
Seq(
TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)),
"Main.uwu"
"here.uwu"
)
)
)
@ -1461,7 +1461,7 @@ class RuntimeServerTest
Seq(
TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)),
"Main.hie"
"here.hie"
)
)
)

View File

@ -1,7 +1,7 @@
package org.enso.interpreter.test.semantic
import org.enso.interpreter.node.callable.function.CreateFunctionNode
import org.enso.interpreter.node.callable.thunk.ForceNode
import org.enso.interpreter.node.callable.{ApplicationNode, SequenceLiteralNode}
import org.enso.interpreter.node.callable.ApplicationNode
import org.enso.interpreter.node.controlflow.CaseNode
import org.enso.interpreter.node.expression.literal.IntegerLiteralNode
import org.enso.interpreter.node.scope.{AssignmentNode, ReadLocalVariableNode}
@ -186,23 +186,6 @@ class CodeLocationsTest extends InterpreterTest {
()
}
"be correct for vector literals" in
withLocationsInstrumenter { instrumenter =>
val code = "main = [11, 2 + 2, 31 * 42, [1,2,3] ]"
instrumenter.assertNodeExists( // outer list
7,
30,
classOf[SequenceLiteralNode]
)
instrumenter.assertNodeExists( // inner list
28,
7,
classOf[SequenceLiteralNode]
)
instrumenter.assertNodeExists(19, 7, classOf[ApplicationNode]) // 31 * 42
eval(code)
}
"be correct for negated literals" in
withLocationsInstrumenter { instrumenter =>
val code = "main = (-1)"

View File

@ -14,8 +14,9 @@ class JavaInteropTest extends InterpreterTest {
val code =
"""
|polyglot java import org.enso.example.TestClass
|from Builtins import all
|
|main = TestClass.add [1, 2]
|main = TestClass.add (Array.new_2 1 2)
|""".stripMargin
eval(code) shouldEqual 3
@ -25,10 +26,11 @@ class JavaInteropTest extends InterpreterTest {
val code =
"""
|polyglot java import org.enso.example.TestClass
|from Builtins import all
|
|main =
| instance = TestClass.new [x -> x * 2]
| instance.callFunctionAndIncrement [10]
| instance = TestClass.new (Array.new_1 (x -> x * 2))
| instance.callFunctionAndIncrement (Array.new_1 10)
|""".stripMargin
eval(code) shouldEqual 21
}

View File

@ -139,23 +139,6 @@ class LambdaShorthandArgsTest extends InterpreterTest {
eval(code) shouldEqual 15
}
"work properly with vector literals" in {
val code =
"""from Builtins import all
|
|main =
| fun = [1, _, (1 + 2), _]
| vec = fun 2 4
| IO.println (Polyglot.get_array_element vec 0)
| IO.println (Polyglot.get_array_element vec 1)
| IO.println (Polyglot.get_array_element vec 2)
| IO.println (Polyglot.get_array_element vec 3)
|
|""".stripMargin
eval(code)
consumeOut shouldEqual List("1", "2", "3", "4")
}
"work properly when used with dot notation" in {
val code =
"""

View File

@ -257,16 +257,5 @@ class NamedArgumentsTest extends InterpreterTest {
eval(code) shouldEqual 10
}
"be assignable from Vectors" in {
val code =
"""from Builtins import all
|
|main =
| lam = (x=[1,3]) -> y -> y + Polyglot.get_array_element x 0 + Polyglot.get_array_element x 1
| lam y=10
|""".stripMargin
eval(code) shouldEqual 14
}
}
}

View File

@ -16,7 +16,7 @@ class PolyglotTest extends InterpreterTest {
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
| method = Polyglot.get_member class "add"
| Polyglot.execute method [1, 2]
| Polyglot.execute method (Array.new_2 1 2)
|""".stripMargin
eval(code) shouldEqual 3
@ -28,8 +28,8 @@ class PolyglotTest extends InterpreterTest {
|
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
| instance = Polyglot.new class [x -> x * 2]
| Polyglot.invoke instance "callFunctionAndIncrement" [10]
| instance = Polyglot.new class (Array.new_1 (x -> x * 2))
| Polyglot.invoke instance "callFunctionAndIncrement" (Array.new_1 10)
|""".stripMargin
eval(code) shouldEqual 21
}
@ -40,7 +40,7 @@ class PolyglotTest extends InterpreterTest {
|
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
| instance = Polyglot.new class []
| instance = Polyglot.new class Array.empty
| members = Polyglot.get_members instance
| IO.println (Polyglot.get_array_size members)
| IO.println (Polyglot.get_array_element members 0)

View File

@ -1,27 +0,0 @@
package org.enso.interpreter.test.semantic
import org.enso.interpreter.test.{InterpreterTest, InterpreterContext}
class SequenceLiteralsTest extends InterpreterTest {
override def subject: String = "Vector Literals"
override def specify(
implicit interpreterContext: InterpreterContext
): Unit = {
"create collections, with fields accessible through the Polyglot API" in {
val code =
"""from Builtins import all
|
|type My x y
|
|main =
| vec = [1, "abc", My 1 2]
| IO.println (Polyglot.get_array_element vec 0)
| IO.println (Polyglot.get_array_element vec 1)
| IO.println (Polyglot.get_array_element vec 2)
|""".stripMargin
eval(code)
consumeOut shouldEqual List("1", "abc", "My 1 2")
}
}
}

View File

@ -108,20 +108,5 @@ class SuspendedArgumentsTest extends InterpreterTest {
eval(code) shouldEqual 1
}
"work with vector literals" in {
val code =
"""from Builtins import all
|
|main =
| foo = ~x -> [x]
| block =
| IO.println "foo"
| 5
| Polyglot.get_array_element (foo block) 0
|""".stripMargin
eval(code) shouldEqual 5
consumeOut shouldEqual List("foo")
}
}
}

View File

@ -21,7 +21,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "echo" [] "" False False False
| result = System.create_process "echo" Array.empty "" False False False
| result.exit_code
|""".stripMargin
eval(code) shouldEqual 0
@ -32,7 +32,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"return error when creating nonexistent command" in {
val code =
"""from Builtins import all
|main = System.create_process "nonexistentcommandxyz" [] "" False False False
|main = System.create_process "nonexistentcommandxyz" Array.empty "" False False False
|""".stripMargin
val error = the[InterpreterException] thrownBy eval(code)
@ -46,7 +46,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "ls" ["--gibberish"] "" False False False
| result = System.create_process "ls" (Array.new_1 "--gibberish") "" False False False
| result.exit_code
|""".stripMargin
@ -60,7 +60,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "read line; echo $line"] "" True True True
| result = System.create_process "bash" (Array.new_2 "-c" "read line; echo $line") "" True True True
| result.exit_code
|""".stripMargin
@ -75,7 +75,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "PowerShell" ["-Command", "[System.Console]::ReadLine()"] "" True True True
| result = System.create_process "PowerShell" (Array.new_2 "-Command" "[System.Console]::ReadLine()") "" True True True
| result.exit_code
|""".stripMargin
@ -91,7 +91,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "wc -c"] "" True True True
| result = System.create_process "bash" (Array.new_2 "-c" "wc -c") "" True True True
| result.exit_code
|""".stripMargin
@ -106,7 +106,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "echo" ["42"] "" True True True
| result = System.create_process "echo" (Array.new_1 "42") "" True True True
| result.exit_code
|""".stripMargin
@ -121,7 +121,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "echo" ["9"] "" True True True
| result = System.create_process "echo" (Array.new_1 "9") "" True True True
| result.exit_code
|""".stripMargin
@ -135,7 +135,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "read line; printf $line"] "hello" False False False
| result = System.create_process "bash" (Array.new_2 "-c" "read line; printf $line") "hello" False False False
| result.stdout
|""".stripMargin
@ -149,7 +149,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "PowerShell" ["-Command", "[System.Console]::ReadLine()"] "hello" False False False
| result = System.create_process "PowerShell" (Array.new_2 "-Command" "[System.Console]::ReadLine()") "hello" False False False
| result.stdout
|""".stripMargin
@ -163,7 +163,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "echo" ["foobar"] "" False True True
| result = System.create_process "echo" (Array.new_1 "foobar") "" False True True
| result.exit_code
|""".stripMargin
@ -177,7 +177,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "printf '%b' '\\x01\\x0F\\x10'"] "" False True True
| result = System.create_process "bash" (Array.new_2 "-c" "printf '%b' '\\x01\\x0F\\x10'") "" False True True
| result.exit_code
|""".stripMargin
@ -191,7 +191,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "echo" ["foobar"] "" False False False
| result = System.create_process "echo" (Array.new_1 "foobar") "" False False False
| result.stdout
|""".stripMargin
@ -205,7 +205,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "printf err 1>&2"] "" False True True
| result = System.create_process "bash" (Array.new_2 "-c" "printf err 1>&2") "" False True True
| result.exit_code
|""".stripMargin
@ -219,7 +219,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "PowerShell" ["-Command", "[System.Console]::Error.WriteLine('err')"] "" False True True
| result = System.create_process "PowerShell" (Array.new_2 "-Command" "[System.Console]::Error.WriteLine('err')") "" False True True
| result.exit_code
|""".stripMargin
@ -233,7 +233,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "printf '%b' '\\xCA\\xFE\\xBA\\xBE' 1>&2"] "" False True True
| result = System.create_process "bash" (Array.new_2 "-c" "printf '%b' '\\xCA\\xFE\\xBA\\xBE' 1>&2") "" False True True
| result.exit_code
|""".stripMargin
@ -247,7 +247,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "bash" ["-c", "printf err 1>&2"] "" False False False
| result = System.create_process "bash" (Array.new_2 "-c" "printf err 1>&2") "" False False False
| result.stderr
|""".stripMargin
@ -261,7 +261,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all
|
|main =
| result = System.create_process "PowerShell" ["-Command", "[System.Console]::Error.WriteLine('err')"] "" False False False
| result = System.create_process "PowerShell" (Array.new_2 "-Command" "[System.Console]::Error.WriteLine('err')") "" False False False
| result.stderr
|""".stripMargin

View File

@ -0,0 +1,19 @@
from Base import all
import Base.Bench_Utils
gen_list len = 0.upto len . fold Nil (l -> i -> Cons i+1 l)
sum_vec vec =
arr = vec.to_array
len = vec.length
sumator = acc -> idx ->
if idx == len then acc else sumator (acc + arr.at idx) idx+1
res = sumator 0 0
res
main =
mil = 1000000
list = here.gen_list mil
vec = Vector.new mil (ix -> ix + 1)
Bench_Utils.measure (vec.fold 0 (+)) "vector fold" 1000 10
Bench_Utils.measure (list.fold 0 (+)) "list fold" 1000 10

View File

@ -1,5 +1,7 @@
import Base.Bench_Utils
import Base.List
from Base import all
polyglot java import java.lang.Long
type Counter
type Sum
@ -10,6 +12,12 @@ sum_tco = sum_to ->
res = summator 0 sum_to
res
sum_tco_java = sum_to ->
summator = acc -> current ->
if current == 0 then acc else summator (Long.sum [acc, current]) (current - 1)
res = summator 0 sum_to
res
sum_co_state_body =
n = State.get Counter
acc = State.get Sum
@ -34,6 +42,8 @@ main =
hundred_mil = 100000000
IO.println "Measuring SumTCO"
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10
IO.println "Measuring SumTCO Java"
Bench_Utils.measure (here.sum_tco_java hundred_mil) "sum_tco" 100 10
IO.println "Measuring State"
Bench_Utils.measure (here.sum_state hundred_mil) "sum_state" 100 10
IO.println "Measuring Co-State"

View File

@ -0,0 +1,8 @@
from Base import all
import Base.Test
polyglot java import java.lang.Long
spec = describe "Java FFI" <|
it "should call methods imported from Java" <|
Long.sum [1, 2] . should_equal 3

View File

@ -5,6 +5,8 @@ import Test.Import_Loop_Spec
import Test.Deep_Export_Spec
import Test.Names_Spec
import Test.Process_Spec
import Test.Java_Interop.Spec as Java_Spec
import Test.Vector.Spec as Vector_Spec
main = Test.Suite.runMain <|
List_Spec.spec
@ -13,3 +15,5 @@ main = Test.Suite.runMain <|
Names_Spec.spec
Deep_Export_Spec.spec
Process_Spec.spec
Java_Spec.spec
Vector_Spec.spec

View File

@ -1,3 +1,4 @@
from Base import all
import Base.Process
from Base.Process.Exit_Code import Exit_Success, Exit_Failure
import Base.System.Platform

View File

@ -0,0 +1,22 @@
from Base import all
import Base.Test
spec = describe "Vectors" <|
it "should allow accessing elements" <|
[1,2,3].at 2 . should_equal 3
it "should have a well-defined length" <|
[1,2,3].length . should_equal 3
it "should allow folding an operator over its elements" <|
[1,2,3].fold 0 (+) . should_equal 6
it "should allow vector creation with a programmatic constructor" <|
Vector.new 100 (ix -> ix + 1) . fold 0 (+) . should_equal 5050
it "should have a well-defined text conversion" <|
[].to_text.should_equal "[]"
[1,2,3].to_text.should_equal "[1, 2, 3]"
[Unit].to_text.should_equal "[Unit]"
it "should allow mapping an operation, returning a new vector" <|
vec = [1, 2, 3, 4]
mapped = vec.map x-> x * x
vec.to_text.should_equal "[1, 2, 3, 4]"
mapped.to_text.should_equal "[1, 4, 9, 16]"