Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Vector.from_polyglot_array to make Vectors backed by polyglot arrays #3628

Merged
merged 14 commits into from
Aug 23, 2022
Merged
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@
type from `Standard.Table`.][3601]
- [Created `Index_Sub_Range` type and updated `Text.take` and
`Text.drop`.][3617]
- [Added `Vector.from_polyglot_array` to make `Vector`s backed by polyglot
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
Arrays][3628]
- [Updated `Vector.take` and `Vector.drop` and removed their obsolete
counterparts.][3629]
- [Short-hand syntax for `order_by` added.][3643]
Expand Down Expand Up @@ -282,6 +284,7 @@
[3593]: https://github.com/enso-org/enso/pull/3593
[3601]: https://github.com/enso-org/enso/pull/3601
[3617]: https://github.com/enso-org/enso/pull/3617
[3628]: https://github.com/enso-org/enso/pull/3628
[3629]: https://github.com/enso-org/enso/pull/3629
[3643]: https://github.com/enso-org/enso/pull/3643
[3644]: https://github.com/enso-org/enso/pull/3644
Expand Down Expand Up @@ -357,7 +360,8 @@
[3531]: https://github.com/enso-org/enso/pull/3531
[3562]: https://github.com/enso-org/enso/pull/3562
[3538]: https://github.com/enso-org/enso/pull/3538
[3538]: https://github.com/enso-org/enso/pull/3569
[3569]: https://github.com/enso-org/enso/pull/3569
[3578]: https://github.com/enso-org/enso/pull/3578
[3618]: https://github.com/enso-org/enso/pull/3618
[3608]: https://github.com/enso-org/enso/pull/3608
[3608]: https://github.com/enso-org/enso/pull/3608
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ type Decimal

4.736.ceil
ceil : Integer
ceil self = @Builtin_Method "Integer.ceil"
ceil self = @Builtin_Method "Decimal.ceil"

## Compares the two operands to determine the ordering of this with
respect to that.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ calculate_correlation_statistics_matrix : [Vector] -> [CorrelationStatistics]
calculate_correlation_statistics_matrix data =
data_array = Vector.new data.length i->(data.at i).to_array . to_array
stats_array = wrap_java_call <| CorrelationStatistics.computeMatrix data_array
Vector.new stats_array.length i->(Vector.Vector (stats_array.at i))
Vector.new stats_array.length i->(Vector.from_polyglot_array (stats_array.at i))


## Compute a single statistic on the vector.
Expand Down Expand Up @@ -248,4 +248,4 @@ rank_data input method=Rank_Method.Average =

handle_classcast <| handle_nullpointer <|
java_ranks = Rank.rank input.to_array Comparator.new java_method
Vector.Vector java_ranks
Vector.from_polyglot_array java_ranks
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ polyglot java import org.enso.base.Text_Utils
all_character_sets : Vector.Vector Text
all_character_sets =
java_array = Charset.availableCharsets.keySet.toArray
Vector.Vector java_array
Vector.from_polyglot_array java_array

## Get all available Encodings.
all_encodings : Vector Encoding
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ Text.split : Text -> (Text_Matcher | Regex_Matcher) -> Vector.Vector Text
Text.split self delimiter="," matcher=Text_Matcher = if delimiter.is_empty then Error.throw (Illegal_Argument_Error "The delimiter cannot be empty.") else
case matcher of
Text_Matcher case_sensitivity ->
delimiters = Vector.Vector <| case case_sensitivity of
delimiters = Vector.from_polyglot_array <| case case_sensitivity of
True ->
Text_Utils.span_of_all self delimiter
Case_Insensitive locale ->
Expand Down Expand Up @@ -552,7 +552,7 @@ Text.words self keep_whitespace=False =
'\na\nb\n'.lines keep_endings=True == ['\n', 'a\n', 'b\n']
Text.lines : Boolean -> Vector.Vector Text
Text.lines self keep_endings=False =
Vector.Vector (Text_Utils.split_on_lines self keep_endings)
Vector.from_polyglot_array (Text_Utils.split_on_lines self keep_endings)

## Checks whether `self` is equal to `that`, ignoring the case of the texts.

Expand Down Expand Up @@ -739,7 +739,7 @@ Text.is_whitespace self =
Text.bytes : Encoding -> Problem_Behavior -> Vector.Vector Byte
Text.bytes self encoding on_problems=Report_Warning =
result = Encoding_Utils.get_bytes self (encoding . to_java_charset)
vector = Vector.Vector result.result
vector = Vector.from_polyglot_array result.result
if result.warnings.is_nothing then vector else
on_problems.attach_problems_after vector [Encoding_Error result.warnings]

Expand Down Expand Up @@ -817,7 +817,7 @@ Text.from_utf_8 bytes on_problems=Report_Warning =

"Hello".char_vector
Text.char_vector : Vector.Vector Integer
Text.char_vector self = Vector.Vector (Text_Utils.get_chars self)
Text.char_vector self = Vector.from_polyglot_array (Text_Utils.get_chars self)

## Takes a vector of characters and returns the text that results from it.

Expand All @@ -840,7 +840,7 @@ Text.from_char_vector chars = Text_Utils.from_chars chars.to_array

"Hello".codepoints
Text.codepoints : Vector.Vector Integer
Text.codepoints self = Vector.Vector (Text_Utils.get_codepoints self)
Text.codepoints self = Vector.from_polyglot_array (Text_Utils.get_codepoints self)

## Takes an array of numbers and returns the text resulting from interpreting it
as a sequence of Unicode codepoints.
Expand Down Expand Up @@ -1481,8 +1481,8 @@ Text.location_of_all : Text -> Matcher -> [Span]
Text.location_of_all self term="" matcher=Text_Matcher = case matcher of
Text_Matcher case_sensitive -> if term.is_empty then Vector.new (self.length + 1) (ix -> Span (Range ix ix) self) else case case_sensitive of
True ->
codepoint_spans = Vector.Vector <| Text_Utils.span_of_all self term
grahpeme_ixes = Vector.Vector <| Text_Utils.utf16_indices_to_grapheme_indices self (codepoint_spans.map .codeunit_start).to_array
codepoint_spans = Vector.from_polyglot_array <| Text_Utils.span_of_all self term
grahpeme_ixes = Vector.from_polyglot_array <| Text_Utils.utf16_indices_to_grapheme_indices self (codepoint_spans.map .codeunit_start).to_array
## While the codepoint_spans may have different code unit lengths
from our term, the `length` counted in grapheme clusters is
guaranteed to be the same.
Expand All @@ -1491,7 +1491,7 @@ Text.location_of_all self term="" matcher=Text_Matcher = case matcher of
end = start+offset
Span (Range start end) self
Case_Insensitive locale ->
grapheme_spans = Vector.Vector <| Text_Utils.span_of_all_case_insensitive self term locale.java_locale
grapheme_spans = Vector.from_polyglot_array <| Text_Utils.span_of_all_case_insensitive self term locale.java_locale
grapheme_spans.map grapheme_span->
Span (Range grapheme_span.grapheme_start grapheme_span.grapheme_end) self
Regex_Matcher _ _ _ _ _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ type Pattern
Mode_Error "Splitting on a bounded region is not well-defined."

splits = self.internal_pattern.split input limit
Vector.Vector splits
Vector.from_polyglot_array splits

## ADVANCED

Expand Down Expand Up @@ -683,7 +683,7 @@ type Match
matcg.named_groups default="UNMATCHED"
named_groups : (a : Any) -> Map Text (Text | a)
named_groups self default=Nothing =
group_names = Vector.Vector <|
group_names = Vector.from_polyglot_array <|
Regex_Utils.get_group_names self.internal_match.pattern
pairs = group_names.map name->
value = case self.group name of
Expand Down
43 changes: 23 additions & 20 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ from Standard.Base import all
import Standard.Base.Runtime.Ref
import Standard.Base.Runtime.Unsafe
from Standard.Base.Data.Index_Sub_Range import While, By_Index, Sample, Every
import Standard.Base.Polyglot.Proxy_Polyglot_Array
import Standard.Base.Random

## Creates a new vector of the given length, initializing elements using
Expand Down Expand Up @@ -86,15 +87,8 @@ new_builder (capacity=1) = Builder.new capacity

A vector allows to store an arbitrary number of elements in linear memory. It
is the recommended data structure for most applications.

! Value Copying
As Enso vectors implement immutable semantics, this constructor function
makes a copy of each value in the argument array.

If this didn't happen then it would be possible for the underlying array to
be mutated under the hood, and sneak mutability into our immutable data.
from_array : Any -> Vector Any
from_array arr = new (Polyglot.get_array_size arr) (arr.at _)
from_polyglot_array : Any -> Vector Any
from_polyglot_array arr = Vector (Proxy_Polyglot_Array.Proxy_Polyglot_Array arr)
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved

## The basic, immutable, vector type.
type Vector
Expand All @@ -104,7 +98,7 @@ type Vector
The basic, immutable, vector type.

Arguments:
- to_array: The underlying array.
- storage: The underlying storage.

A vector allows to store an arbitrary number of elements, in linear memory.
It is the recommended data structure for most applications.
Expand All @@ -117,7 +111,18 @@ type Vector
A vector containing 50 elements, each being the number `42`, can be
created by:
Vector.fill length=50 item=42
type Vector to_array
type Vector storage

to_array self =
arr = self.storage.to_array
case arr of
Array ->
arr
_ ->
len = self.storage.length
a = Array.new len
Array.copy arr 0 a 0 len
a
Comment on lines +117 to +125
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this code?

My experience tells me that polyglot arrays also used to match the Array case in pattern matching, so I'm not really sure if it will do what you want - it will most likely always enter the Array branch. Any array-object that is compatible with Array.copy will also match the Array branch, so the second branch is essentially dead code, unless I'm missing something.

See the following code:

from Standard.Base import all

polyglot java import java.util.List

main =
    listarr = List.of 1 2 3
    IO.println listarr
    m = Meta.meta listarr
    IO.println m
    IO.println m.get_language
    IO.println (Meta.get_simple_type_name listarr)
    IO.println (Meta.get_qualified_type_name listarr)
    case listarr of
        Array -> IO.println "Matches Array!"
        _ -> IO.println "nope"

it actually prints

[1, 2, 3]
(Polyglot [1, 2, 3])
Java
java.util.ImmutableCollections$ListN
null
Matches Array!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think the to_array method should have some doc comment, if at least ## PRIVATE.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Sorry for commenting after merge, but I did not notice these earlier)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was affecting my Array.set_at removal tests, so I fixed it in 29c4abc (part of #3634).


## Returns the number of elements stored in this vector.

Expand All @@ -126,7 +131,8 @@ type Vector

[1, 2, 3, 4].length
length : Number
length self = Polyglot.get_array_size self.to_array
length self =
self.storage.length

## Gets an element from the vector at a specified index (0-based).

Expand Down Expand Up @@ -159,7 +165,7 @@ type Vector
bounds or with additional error handling.
unsafe_at : Integer -> Any
unsafe_at self index =
self.to_array.at index
self.storage.at index

## Combines all the elements of the vector, by iteratively applying the
passed function with next elements of the vector.
Expand All @@ -179,8 +185,7 @@ type Vector
[0, 1, 2] . fold 0 (+)
fold : Any -> (Any -> Any -> Any) -> Any
fold self init function =
arr = self.to_array
f = acc -> ix -> function acc (arr.at ix)
f = acc -> ix -> function acc (self.storage.at ix)
0.up_to self.length . fold init f

## Combines all the elements of the vector, by iteratively applying the
Expand All @@ -194,11 +199,10 @@ type Vector
> Example
Compute the sum of all of the elements and indexes in a vector.

[0, 1, 2] . fold 0 (s->i->e->s+i+e)
[0, 1, 2] . fold_with_index 0 (s->i->e->s+i+e)
fold_with_index : Any -> (Any -> Integer -> Any -> Any) -> Any
fold_with_index self init function =
arr = self.to_array
f = acc -> ix -> function acc ix (arr.at ix)
f = acc -> ix -> function acc ix (self.storage.at ix)
0.up_to self.length . fold init f

## Combines all the elements of a non-empty vector using a binary operation.
Expand All @@ -216,8 +220,7 @@ type Vector
reduce self function =
case self.not_empty of
True -> if self.length == 1 then self.unsafe_at 0 else
arr = self.to_array
f = acc -> ix -> function acc (arr.at ix)
f = acc -> ix -> function acc (self.storage.at ix)
1.up_to self.length . fold (self.unsafe_at 0) f
False -> Error.throw Empty_Error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Response
example_headers = Examples.get_response.headers
headers : Vector.Vector
headers self =
header_entries = Vector.Vector (Http_Utils.get_headers self.internal_http_response.headers)
header_entries = Vector.from_polyglot_array (Http_Utils.get_headers self.internal_http_response.headers)
header_entries.map e-> Header.new e.getKey e.getValue

## Get the response body.
Expand All @@ -41,7 +41,7 @@ type Response

example_body = Examples.get_response.body
body : Response_Body
body self = Response_Body.Body (Vector.Vector self.internal_http_response.body)
body self = Response_Body.Body (Vector.from_polyglot_array self.internal_http_response.body)

## Get the response status code.

Expand Down
7 changes: 7 additions & 0 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Polyglot.enso
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ type Polyglot
get_array_size : Any -> Integer
get_array_size array = @Builtin_Method "Polyglot.get_array_size"

## Reads the element in a given polyglot array object.

Arguments:
- index: The index to get the element from.
read_array_element : Any -> Integer -> Any
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
read_array_element array index = @Builtin_Method "Polyglot.read_array_element"

## Executes a polyglot function object (e.g. a lambda).

Arguments:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from Standard.Base import Polyglot, Array

## Advanced

Wrapper for Polyglot Arrays
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
type Proxy_Polyglot_Array
hubertp marked this conversation as resolved.
Show resolved Hide resolved

type Proxy_Polyglot_Array arr

## Returns the number of elements stored in this Polyglot Array.

length : Number
length self =
Polyglot.get_array_size self.arr

## Gets an element from this Polyglot Array at a specified index (0-based).

at : Number -> Any
at self index =
Polyglot.read_array_element self.arr index

to_array : Array Any
to_array self =
self.arr
4 changes: 2 additions & 2 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Random.enso
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ type Random_Number_Generator
sample : Vector Any -> Integer -> Random_Number_Generator -> Vector Any
sample vector k rng =
new_array = Random_Utils.sample vector.to_array k rng.java_random
Vector.Vector new_array
Vector.from_polyglot_array new_array

## Returns `k` indices sampled from the range [0, n-1] without replacement.

If `k >= n`, it will return a random permutation of the indices.
random_indices : Integer -> Integer -> Random_Number_Generator -> Vector Integer
random_indices n k rng =
array = Random_Utils.random_indices n k rng.java_random
Vector.Vector array
Vector.from_polyglot_array array
4 changes: 0 additions & 4 deletions distribution/lib/Standard/Base/0.0.0-dev/src/System.enso
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ nano_time = @Builtin_Method "System.nano_time"
os : Text
os = @Builtin_Method "System.os"

## Check if the operating system is UNIX.
is_unix : Boolean
is_unix = @Builtin_Method "System.is_unix"

## PRIVATE
Returns the default line separator for the platform that the program is
currently running on.
Expand Down
10 changes: 5 additions & 5 deletions distribution/lib/Standard/Base/0.0.0-dev/src/System/File.enso
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ type File
Builtin method that deletes the file.
Recommended to use `File.delete` instead which handles potential exceptions.
delete_builtin : Nothing
delete_builtin self = @Builtin_Method "File.delete"
delete_builtin self = @Builtin_Method "File.delete_builtin"

## Moves the file to the specified destination.

Expand Down Expand Up @@ -646,7 +646,7 @@ type File
read_last_bytes : Integer -> Vector ! File_Error
read_last_bytes self n =
handle_java_exceptions self <|
Vector.Vector (self.read_last_bytes_builtin n)
Vector.from_polyglot_array (self.read_last_bytes_builtin n)

## PRIVATE
read_last_bytes_builtin : Integer -> Array
Expand Down Expand Up @@ -837,7 +837,7 @@ type Output_Stream
replacement_sequence = Encoding_Utils.INVALID_CHARACTER.bytes encoding on_problems=Problem_Behavior.Ignore
java_charset = encoding.to_java_charset
results = Encoding_Utils.with_stream_encoder java_stream java_charset replacement_sequence.to_array action
problems = Vector.Vector results.problems . map Encoding_Error
problems = Vector.from_polyglot_array results.problems . map Encoding_Error
on_problems.attach_problems_after results.result problems

## An input stream, allowing for interactive reading of contents from an open
Expand Down Expand Up @@ -874,7 +874,7 @@ type Input_Stream
read_all_bytes : Vector.Vector ! File_Error
read_all_bytes self = self.stream_resource . with java_stream->
handle_java_exceptions self.file <|
Vector.Vector java_stream.readAllBytes
Vector.from_polyglot_array java_stream.readAllBytes

## ADVANCED

Expand Down Expand Up @@ -1122,4 +1122,4 @@ Vector.Vector.write_bytes self path on_existing_file=Existing_File_Behavior.Back

file = new path
on_existing_file.write file stream->
stream.write_bytes (Vector.Vector byte_array)
stream.write_bytes (Vector.from_polyglot_array byte_array)
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ type Os
os : Os
os = from_text System.os

## Check if the currently running platform is a UNIX platform.
## Check if the operating system is UNIX.
is_unix : Boolean
is_unix = System.is_unix
is_unix = @Builtin_Method "System.is_unix"

## PRIVATE

Expand Down
Loading