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 -> reverse_list = list ->
go = list -> acc -> case list of go = list -> acc -> case list of
Cons h t -> go t (Cons h acc) Cons h t -> go t (Cons h acc)
@ -24,6 +26,11 @@ Number.times = act ->
res = here.reverse_list (go Nil this) res = here.reverse_list (go Nil this)
res 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 -> measure = ~act -> label -> iter_size -> num_iters ->
single_call = _ -> single_call = _ ->
x1 = System.nano_time x1 = System.nano_time
@ -34,5 +41,6 @@ measure = ~act -> label -> iter_size -> num_iters ->
act_it_num = num_iters - it_num act_it_num = num_iters - it_num
res = iter_size.times single_call res = iter_size.times single_call
avg = here.avg_list res 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 num_iters.times iteration

View File

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

View File

@ -1,6 +1,46 @@
import Base.List import Base.List
import Builtins import Base.Vector
from Builtins import Number, Unit
from Builtins export all from Builtins export all
from Base.List export Nil, Cons 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 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. ## The builder object that is used to create operating system processes.
type Process_Builder command arguments stdin type Process_Builder command arguments stdin
@ -16,7 +17,7 @@ type Process_Result exit_code stdout stderr
8 8
Process.execute : String -> Exit_Code Process.execute : String -> Exit_Code
Process.execute command = 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 Exit_Code.from_number result.exit_code
## Call a command with a list of arguments. ## Call a command with a list of arguments.
@ -28,7 +29,7 @@ Process.execute command =
Hello! Hello!
Process.run_command : String -> Vector -> Exit_Code Process.run_command : String -> Vector -> Exit_Code
Process.run_command command arguments = 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 Exit_Code.from_number result.exit_code
## Create a process using a builder returning the result of execution. ## 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_Result Exit_Success "test" ""
Process.create : Process_Builder -> Process_Result Process.create : Process_Builder -> Process_Result
Process.create b = 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 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.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function; 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.MethodDoesNotExistException;
import org.enso.interpreter.runtime.error.RuntimeError; import org.enso.interpreter.runtime.error.RuntimeError;
@ -157,6 +158,16 @@ public abstract class MethodResolverNode extends Node {
return function; 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)"}) @Specialization(guards = {"cachedSymbol == symbol", "ctx.getEnvironment().isHostObject(target)"})
Function resolveHost( Function resolveHost(
UnresolvedSymbol symbol, UnresolvedSymbol symbol,
@ -220,11 +231,18 @@ public abstract class MethodResolverNode extends Node {
return ensureMethodExists(symbol.resolveFor(getBuiltins().any()), "Error", symbol); 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) { Function buildHostResolver(UnresolvedSymbol symbol, Context context) {
if (symbol.getName().equals("new")) { if (symbol.getName().equals("new")) {
return context.getBuiltins().getConstructorDispatch(); return context.getBuiltins().getConstructorDispatch();
} else { } 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.ExplodeLoop;
import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.nodes.NodeInfo;
import org.enso.interpreter.node.ExpressionNode; 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.") @NodeInfo(shortName = "[]", description = "Creates a vector from given expressions.")
public class SequenceLiteralNode extends ExpressionNode { public class SequenceLiteralNode extends ExpressionNode {
@ -28,7 +28,7 @@ public class SequenceLiteralNode extends ExpressionNode {
* Executes the node. * Executes the node.
* *
* @param frame the stack frame for execution. * @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 @Override
@ExplodeLoop @ExplodeLoop
@ -37,6 +37,6 @@ public class SequenceLiteralNode extends ExpressionNode {
for (int i = 0; i < items.length; i++) { for (int i = 0; i < items.length; i++) {
itemValues[i] = items[i].executeGeneric(frame); 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; 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.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.nodes.Node; 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 com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants; import org.enso.interpreter.Constants;
import org.enso.interpreter.Language;
import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode; import org.enso.interpreter.runtime.data.Array;
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.error.PanicException; import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.state.Stateful;
import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod( @BuiltinMethod(
type = "Polyglot", type = "Polyglot",
@ -30,7 +20,7 @@ public class ExecuteNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create(); private final BranchProfile err = BranchProfile.create();
Object execute(Object _this, Object callable, Vector arguments) { Object execute(Object _this, Object callable, Array arguments) {
try { try {
return library.execute(callable, arguments.getItems()); return library.execute(callable, arguments.getItems());
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) { } 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 com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants; import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod; 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; import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod( @BuiltinMethod(
@ -21,7 +21,7 @@ public class InstantiateNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create(); private final BranchProfile err = BranchProfile.create();
Object execute(Object _this, Object constructor, Vector arguments) { Object execute(Object _this, Object constructor, Array arguments) {
try { try {
return library.instantiate(constructor, arguments.getItems()); return library.instantiate(constructor, arguments.getItems());
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) { } 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 com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants; import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod; 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; import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod( @BuiltinMethod(
@ -17,7 +17,7 @@ public class InvokeNode extends Node {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create(); 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 { try {
return library.invokeMember(target, name, arguments.getItems()); return library.invokeMember(target, name, arguments.getItems());
} catch (UnsupportedMessageException } catch (UnsupportedMessageException

View File

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

View File

@ -1,5 +1,9 @@
package org.enso.interpreter.node.expression.builtin.interop.syntax; 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.frame.VirtualFrame;
import com.oracle.truffle.api.interop.*; import com.oracle.truffle.api.interop.*;
import com.oracle.truffle.api.nodes.NodeInfo; 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 com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.Constants; import org.enso.interpreter.Constants;
import org.enso.interpreter.Language; import org.enso.interpreter.Language;
import org.enso.interpreter.node.callable.InvokeCallableNode;
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode; 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.callable.function.Function;
import org.enso.interpreter.runtime.error.PanicException; import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.state.Stateful; import org.enso.interpreter.runtime.state.Stateful;
import org.enso.interpreter.runtime.type.TypesGen; import org.enso.interpreter.runtime.type.TypesGen;
@NodeInfo(shortName = "<polyglot_dispatch>", description = "Invokes a polyglot method by name.") @NodeInfo(shortName = "<polyglot_dispatch>", description = "Invokes a polyglot method by name.")
public class MethodDispatchNode extends BuiltinRootNode { @ReportPolymorphism
private MethodDispatchNode(Language language) { public abstract class MethodDispatchNode extends BuiltinRootNode {
MethodDispatchNode(Language language) {
super(language); super(language);
} }
@ -23,6 +31,12 @@ public class MethodDispatchNode extends BuiltinRootNode {
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
private final BranchProfile err = BranchProfile.create(); 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. * Creates an instance of this node.
* *
@ -30,7 +44,7 @@ public class MethodDispatchNode extends BuiltinRootNode {
* @return a function wrapping this node * @return a function wrapping this node
*/ */
public static MethodDispatchNode build(Language language) { 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. * @param frame current execution frame.
* @return the result of converting input into a string. * @return the result of converting input into a string.
*/ */
@Override @Specialization(guards = "symbol == cachedSymbol")
public Stateful execute(VirtualFrame frame) { 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[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
Object callable = args[0]; Object callable = args[0];
Object state = Function.ArgumentsHelper.getState(frame.getArguments()); Object state = Function.ArgumentsHelper.getState(frame.getArguments());
Object arguments = args[2];
Stateful casted = invokeCallableNode.execute(toArray, frame, state, new Object[] {arguments});
try { try {
String method = TypesGen.expectString(args[1]); Object[] castedArgs = TypesGen.expectArray(casted.getValue()).getItems();
Object[] arguments = TypesGen.expectVector(args[2]).getItems(); Object res = library.invokeMember(callable, symbol.getName(), castedArgs);
Object res = library.invokeMember(callable, method, arguments); return new Stateful(casted.getState(), res);
return new Stateful(state, res);
} catch (UnsupportedMessageException } catch (UnsupportedMessageException
| ArityException | ArityException
| UnsupportedTypeException | 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. * 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.Language;
import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.Context; 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 org.enso.interpreter.runtime.error.PanicException;
import java.io.*; import java.io.*;
@ -26,7 +26,7 @@ public abstract class CreateProcessNode extends Node {
abstract Object execute( abstract Object execute(
Object _this, Object _this,
String command, String command,
Vector arguments, Array arguments,
String input, String input,
boolean redirectIn, boolean redirectIn,
boolean redirectOut, boolean redirectOut,
@ -37,15 +37,15 @@ public abstract class CreateProcessNode extends Node {
Object doCreate( Object doCreate(
Object _this, Object _this,
String command, String command,
Vector arguments, Array arguments,
String input, String input,
boolean redirectIn, boolean redirectIn,
boolean redirectOut, boolean redirectOut,
boolean redirectErr, boolean redirectErr,
@CachedContext(Language.class) Context ctx) { @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; 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); TruffleProcessBuilder pb = ctx.getEnvironment().newProcessBuilder(cmd);
try { 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.CallerInfo;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function; 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.LocalScope;
import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.interpreter.runtime.scope.ModuleScope;
import org.enso.interpreter.runtime.type.Types; import org.enso.interpreter.runtime.type.Types;
@ -454,7 +454,7 @@ public class Module implements TruffleObject {
*/ */
@ExportMessage @ExportMessage
Object getMembers(boolean includeInternal) { Object getMembers(boolean includeInternal) {
return new Vector( return new Array(
MethodNames.Module.GET_METHOD, MethodNames.Module.GET_METHOD,
MethodNames.Module.GET_CONSTRUCTOR, MethodNames.Module.GET_CONSTRUCTOR,
MethodNames.Module.REPARSE, 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.node.expression.builtin.unsafe.SetAtomFieldMethodGen;
import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.Module; 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.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
@ -52,6 +53,7 @@ public class Builtins {
private final Error error; private final Error error;
private final Bool bool; private final Bool bool;
private final System system; private final System system;
private final Array array;
private final RootCallTarget interopDispatchRoot; private final RootCallTarget interopDispatchRoot;
private final FunctionSchema interopDispatchSchema; private final FunctionSchema interopDispatchSchema;
@ -72,6 +74,7 @@ public class Builtins {
number = new AtomConstructor("Number", scope).initializeFields(); number = new AtomConstructor("Number", scope).initializeFields();
bool = new Bool(language, scope); bool = new Bool(language, scope);
error = new Error(language, scope); error = new Error(language, scope);
array = new Array(language, scope);
function = new AtomConstructor("Function", scope).initializeFields(); function = new AtomConstructor("Function", scope).initializeFields();
text = new AtomConstructor("Text", scope).initializeFields(); text = new AtomConstructor("Text", scope).initializeFields();
debug = new AtomConstructor("Debug", scope).initializeFields(); debug = new AtomConstructor("Debug", scope).initializeFields();
@ -258,6 +261,10 @@ public class Builtins {
return system; return system;
} }
/** @return the container for array-related builtins. */
public Array array() {
return array;
}
/** /**
* Returns the builtin module scope. * Returns the builtin module scope.
@ -275,10 +282,10 @@ public class Builtins {
/** /**
* Builds a function dispatching to a polyglot method call. * 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. * @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}; Object[] preAppliedArr = new Object[] {null, method, null};
return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null); return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null);
} }

View File

@ -33,15 +33,17 @@ public class UnresolvedSymbol implements TruffleObject {
/** /**
* Gets the symbol name. * 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 * @return the name of this symbol
*/ */
public String getName() { public String getName() {
return name; return name;
} }
/** @return the scope this symbol was used in. */
public ModuleScope getScope() {
return scope;
}
/** /**
* Resolves the symbol for a given hierarchy of constructors. * 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.ArgumentDefinition;
import org.enso.interpreter.runtime.callable.argument.Thunk; import org.enso.interpreter.runtime.callable.argument.Thunk;
import org.enso.interpreter.runtime.state.data.EmptyMap; 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.interpreter.runtime.type.Types;
import org.enso.polyglot.MethodNames; import org.enso.polyglot.MethodNames;
@ -272,7 +272,7 @@ public final class Function implements TruffleObject {
*/ */
@ExportMessage @ExportMessage
Object getMembers(boolean includeInternal) { 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; 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.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException; import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage; 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) @ExportLibrary(InteropLibrary.class)
public class Vector implements TruffleObject { public class Array implements TruffleObject {
private final @CompilerDirectives.CompilationFinal(dimensions = 1) Object[] items; private final Object[] items;
/** /**
* Creates a new Vector * Creates a new array
* *
* @param items the element values * @param items the element values
*/ */
public Vector(Object... items) { public Array(Object... items) {
this.items = 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() { public Object[] getItems() {
return items; return items;
} }
@ -57,7 +65,7 @@ public class Vector implements TruffleObject {
* @return * @return
*/ */
@ExportMessage @ExportMessage
public long getArraySize() { long getArraySize() {
return items.length; return items.length;
} }
@ -68,7 +76,22 @@ public class Vector implements TruffleObject {
* @return {@code true} if the index is valid, {@code false} otherwise. * @return {@code true} if the index is valid, {@code false} otherwise.
*/ */
@ExportMessage @ExportMessage
public boolean isArrayElementReadable(long index) { boolean isArrayElementReadable(long index) {
return index < getArraySize() && index >= 0; 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.Context;
import org.enso.interpreter.runtime.Module; import org.enso.interpreter.runtime.Module;
import org.enso.interpreter.runtime.builtin.Builtins; 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.interpreter.runtime.type.Types;
import org.enso.pkg.QualifiedName; import org.enso.pkg.QualifiedName;
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. * @return a collection of all the exported members.
*/ */
@ExportMessage @ExportMessage
Vector getMembers(boolean includeInternal) { Array getMembers(boolean includeInternal) {
return new Vector( return new Array(
MethodNames.TopScope.GET_MODULE, MethodNames.TopScope.GET_MODULE,
MethodNames.TopScope.CREATE_MODULE, MethodNames.TopScope.CREATE_MODULE,
MethodNames.TopScope.REGISTER_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.dsl.TypeSystem;
import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.UnsupportedTypeException; 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.argument.Thunk;
import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.callable.function.Function; 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 org.enso.interpreter.runtime.error.RuntimeError;
import java.util.Optional;
/** /**
* This class defines the interpreter-level type system for Enso. * This class defines the interpreter-level type system for Enso.
* *
@ -33,7 +32,8 @@ import java.util.Optional;
AtomConstructor.class, AtomConstructor.class,
Thunk.class, Thunk.class,
RuntimeError.class, RuntimeError.class,
Vector.class UnresolvedSymbol.class,
Array.class
}) })
public class Types { public class Types {
@ -118,8 +118,8 @@ public class Types {
return "Thunk"; return "Thunk";
} else if (TypesGen.isRuntimeError(value)) { } else if (TypesGen.isRuntimeError(value)) {
return "Error " + TypesGen.asRuntimeError(value).getPayload().toString(); return "Error " + TypesGen.asRuntimeError(value).getPayload().toString();
} else if (TypesGen.isVector(value)) { } else if (TypesGen.isArray(value)) {
return "Vector"; return "Array";
} else { } else {
return null; return null;
} }

View File

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

View File

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

View File

@ -5302,6 +5302,12 @@ object IR {
def explain(originalName: IR.Name): String 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. * An error coming from an unexpected occurence of a polyglot symbol.
* *

View File

@ -57,14 +57,13 @@ case class BindingsMap(
} }
private def findLocalCandidates(name: String): List[ResolvedName] = { private def findLocalCandidates(name: String): List[ResolvedName] = {
if (currentModule.getName.item == name) {
List(ResolvedModule(currentModule))
} else {
val conses = findConstructorCandidates(name) val conses = findConstructorCandidates(name)
val polyglot = findPolyglotCandidates(name) val polyglot = findPolyglotCandidates(name)
val methods = findMethodCandidates(name) val methods = findMethodCandidates(name)
conses ++ polyglot ++ methods val all = conses ++ polyglot ++ methods
} if (all.isEmpty && currentModule.getName.item == name) {
List(ResolvedModule(currentModule))
} else { all }
} }
private def findQualifiedImportCandidates( 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 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 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 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 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 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 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 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 import Test_Rename_Error.Atom as Def
Main.main = (Atom.X 1).method main = (Atom.X 1).method

View File

@ -856,7 +856,10 @@ class DataflowAnalysisTest extends CompilerTest {
val depInfo = ir.getMetadata(DataflowAnalysis).get 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] .asInstanceOf[IR.Application.Literal.Sequence]
val xDefId = mkStaticDep(ir.arguments(0).getId) val xDefId = mkStaticDep(ir.arguments(0).getId)
@ -864,13 +867,17 @@ class DataflowAnalysisTest extends CompilerTest {
val yId = mkStaticDep(vector.items(1).getId) val yId = mkStaticDep(vector.items(1).getId)
val litId = mkStaticDep(vector.items(2).getId) val litId = mkStaticDep(vector.items(2).getId)
val vecId = mkStaticDep(vector.getId) val vecId = mkStaticDep(vector.getId)
val callArgId = mkStaticDep(callArg.getId)
val appId = mkStaticDep(ir.body.getId)
val lamId = mkStaticDep(ir.getId) val lamId = mkStaticDep(ir.getId)
depInfo.getDirect(xDefId) shouldEqual Some(Set(xUseId)) depInfo.getDirect(xDefId) shouldEqual Some(Set(xUseId))
depInfo.getDirect(xUseId) shouldEqual Some(Set(vecId)) depInfo.getDirect(xUseId) shouldEqual Some(Set(vecId))
depInfo.getDirect(yId) shouldEqual Some(Set(vecId)) depInfo.getDirect(yId) shouldEqual Some(Set(vecId))
depInfo.getDirect(litId) 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 { "work properly for typeset literals" in {

View File

@ -150,6 +150,9 @@ class DemandAnalysisTest extends CompilerTest {
val vec = ir val vec = ir
.asInstanceOf[IR.Function.Lambda] .asInstanceOf[IR.Function.Lambda]
.body .body
.asInstanceOf[IR.Application.Prefix]
.arguments(0)
.value
.asInstanceOf[IR.Application.Literal.Sequence] .asInstanceOf[IR.Application.Literal.Sequence]
vec.items(0) shouldBe an[IR.Application.Force] 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 idMain = metadata.addItem(32, 35)
val idMainA = metadata.addItem(41, 8) val idMainA = metadata.addItem(41, 8)
val idMainP = metadata.addItem(54, 12) val idMainP = metadata.addItem(54, 12)
val idPie = metadata.addItem(71 + 8, 1) val idPie = metadata.addItem(66 + 8, 1)
val idUwu = metadata.addItem(84 + 8, 1) val idUwu = metadata.addItem(74 + 8, 1)
val idHie = metadata.addItem(97 + 8, 6) val idHie = metadata.addItem(82 + 8, 6)
val idXxx = metadata.addItem(117 + 8, 1) val idXxx = metadata.addItem(102 + 8, 1)
val code = val code =
"""from Builtins import all """from Builtins import all
| |
@ -1208,9 +1208,9 @@ class RuntimeServerTest
| a = 123 + 21 | a = 123 + 21
| IO.println a | IO.println a
| |
|Main.pie = 3 |pie = 3
|Main.uwu = 7 |uwu = 7
|Main.hie = "hie!" |hie = "hie!"
|Number.x y = y |Number.x y = y
|""".stripMargin.linesIterator.mkString("\n") |""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code) val contents = metadata.appendToCode(code)
@ -1399,7 +1399,7 @@ class RuntimeServerTest
Seq( Seq(
TextEdit( TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)), model.Range(model.Position(3, 8), model.Position(3, 16)),
"Main.pie" "here.pie"
) )
) )
) )
@ -1430,7 +1430,7 @@ class RuntimeServerTest
Seq( Seq(
TextEdit( TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)), model.Range(model.Position(3, 8), model.Position(3, 16)),
"Main.uwu" "here.uwu"
) )
) )
) )
@ -1461,7 +1461,7 @@ class RuntimeServerTest
Seq( Seq(
TextEdit( TextEdit(
model.Range(model.Position(3, 8), model.Position(3, 16)), 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 package org.enso.interpreter.test.semantic
import org.enso.interpreter.node.callable.function.CreateFunctionNode import org.enso.interpreter.node.callable.function.CreateFunctionNode
import org.enso.interpreter.node.callable.thunk.ForceNode 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.controlflow.CaseNode
import org.enso.interpreter.node.expression.literal.IntegerLiteralNode import org.enso.interpreter.node.expression.literal.IntegerLiteralNode
import org.enso.interpreter.node.scope.{AssignmentNode, ReadLocalVariableNode} 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 "be correct for negated literals" in
withLocationsInstrumenter { instrumenter => withLocationsInstrumenter { instrumenter =>
val code = "main = (-1)" val code = "main = (-1)"

View File

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

View File

@ -139,23 +139,6 @@ class LambdaShorthandArgsTest extends InterpreterTest {
eval(code) shouldEqual 15 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 { "work properly when used with dot notation" in {
val code = val code =
""" """

View File

@ -257,16 +257,5 @@ class NamedArgumentsTest extends InterpreterTest {
eval(code) shouldEqual 10 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 = |main =
| class = Java.lookup_class "org.enso.example.TestClass" | class = Java.lookup_class "org.enso.example.TestClass"
| method = Polyglot.get_member class "add" | method = Polyglot.get_member class "add"
| Polyglot.execute method [1, 2] | Polyglot.execute method (Array.new_2 1 2)
|""".stripMargin |""".stripMargin
eval(code) shouldEqual 3 eval(code) shouldEqual 3
@ -28,8 +28,8 @@ class PolyglotTest extends InterpreterTest {
| |
|main = |main =
| class = Java.lookup_class "org.enso.example.TestClass" | class = Java.lookup_class "org.enso.example.TestClass"
| instance = Polyglot.new class [x -> x * 2] | instance = Polyglot.new class (Array.new_1 (x -> x * 2))
| Polyglot.invoke instance "callFunctionAndIncrement" [10] | Polyglot.invoke instance "callFunctionAndIncrement" (Array.new_1 10)
|""".stripMargin |""".stripMargin
eval(code) shouldEqual 21 eval(code) shouldEqual 21
} }
@ -40,7 +40,7 @@ class PolyglotTest extends InterpreterTest {
| |
|main = |main =
| class = Java.lookup_class "org.enso.example.TestClass" | class = Java.lookup_class "org.enso.example.TestClass"
| instance = Polyglot.new class [] | instance = Polyglot.new class Array.empty
| members = Polyglot.get_members instance | members = Polyglot.get_members instance
| IO.println (Polyglot.get_array_size members) | IO.println (Polyglot.get_array_size members)
| IO.println (Polyglot.get_array_element members 0) | 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 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 """from Builtins import all
| |
|main = |main =
| result = System.create_process "echo" [] "" False False False | result = System.create_process "echo" Array.empty "" False False False
| result.exit_code | result.exit_code
|""".stripMargin |""".stripMargin
eval(code) shouldEqual 0 eval(code) shouldEqual 0
@ -32,7 +32,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"return error when creating nonexistent command" in { "return error when creating nonexistent command" in {
val code = val code =
"""from Builtins import all """from Builtins import all
|main = System.create_process "nonexistentcommandxyz" [] "" False False False |main = System.create_process "nonexistentcommandxyz" Array.empty "" False False False
|""".stripMargin |""".stripMargin
val error = the[InterpreterException] thrownBy eval(code) val error = the[InterpreterException] thrownBy eval(code)
@ -46,7 +46,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -60,7 +60,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -75,7 +75,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -91,7 +91,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -106,7 +106,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -121,7 +121,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -135,7 +135,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.stdout
|""".stripMargin |""".stripMargin
@ -149,7 +149,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.stdout
|""".stripMargin |""".stripMargin
@ -163,7 +163,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -177,7 +177,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -191,7 +191,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |main =
| result = System.create_process "echo" ["foobar"] "" False False False | result = System.create_process "echo" (Array.new_1 "foobar") "" False False False
| result.stdout | result.stdout
|""".stripMargin |""".stripMargin
@ -205,7 +205,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -219,7 +219,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -233,7 +233,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.exit_code
|""".stripMargin |""".stripMargin
@ -247,7 +247,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.stderr
|""".stripMargin |""".stripMargin
@ -261,7 +261,7 @@ class SystemProcessTest extends InterpreterTest with OsSpec {
"""from Builtins import all """from Builtins import all
| |
|main = |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 | result.stderr
|""".stripMargin |""".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.Bench_Utils
import Base.List from Base import all
polyglot java import java.lang.Long
type Counter type Counter
type Sum type Sum
@ -10,6 +12,12 @@ sum_tco = sum_to ->
res = summator 0 sum_to res = summator 0 sum_to
res 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 = sum_co_state_body =
n = State.get Counter n = State.get Counter
acc = State.get Sum acc = State.get Sum
@ -34,6 +42,8 @@ main =
hundred_mil = 100000000 hundred_mil = 100000000
IO.println "Measuring SumTCO" IO.println "Measuring SumTCO"
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10 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" IO.println "Measuring State"
Bench_Utils.measure (here.sum_state hundred_mil) "sum_state" 100 10 Bench_Utils.measure (here.sum_state hundred_mil) "sum_state" 100 10
IO.println "Measuring Co-State" 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.Deep_Export_Spec
import Test.Names_Spec import Test.Names_Spec
import Test.Process_Spec import Test.Process_Spec
import Test.Java_Interop.Spec as Java_Spec
import Test.Vector.Spec as Vector_Spec
main = Test.Suite.runMain <| main = Test.Suite.runMain <|
List_Spec.spec List_Spec.spec
@ -13,3 +15,5 @@ main = Test.Suite.runMain <|
Names_Spec.spec Names_Spec.spec
Deep_Export_Spec.spec Deep_Export_Spec.spec
Process_Spec.spec Process_Spec.spec
Java_Spec.spec
Vector_Spec.spec

View File

@ -1,3 +1,4 @@
from Base import all
import Base.Process import Base.Process
from Base.Process.Exit_Code import Exit_Success, Exit_Failure from Base.Process.Exit_Code import Exit_Success, Exit_Failure
import Base.System.Platform 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]"