mirror of
https://github.com/enso-org/enso.git
synced 2024-12-28 10:15:07 +03:00
Check type of self
in static dispatch (#8867)
- Fixes #8805 - also btw. fixes #8706
This commit is contained in:
parent
ee381369b0
commit
d45f0fe4df
@ -1046,6 +1046,7 @@
|
||||
- [Binary operator resolution based on that value][8779]
|
||||
- [Add run_google_report method][8907]
|
||||
- [Execute and debug individual Enso files in VSCode extension][8923]
|
||||
- [Check type of `self` when calling a method using the static syntax][8867]
|
||||
|
||||
[3227]: https://github.com/enso-org/enso/pull/3227
|
||||
[3248]: https://github.com/enso-org/enso/pull/3248
|
||||
@ -1203,6 +1204,7 @@
|
||||
[8779]: https://github.com/enso-org/enso/pull/8779
|
||||
[8907]: https://github.com/enso-org/enso/pull/8907
|
||||
[8923]: https://github.com/enso-org/enso/pull/8923
|
||||
[8867]: https://github.com/enso-org/enso/pull/8867
|
||||
|
||||
# Enso 2.0.0-alpha.18 (2021-10-12)
|
||||
|
||||
|
@ -144,7 +144,7 @@ type Array
|
||||
[My_Type.Value 'hello', 1].to_array.sort == [1, My_Type.Value 'hello'].to_array
|
||||
sort : Sort_Direction -> (Any -> Any)|Nothing -> (Any -> Any -> (Ordering|Nothing))|Nothing -> Problem_Behavior -> Vector Any ! Incomparable_Values
|
||||
sort self (order = Sort_Direction.Ascending) on=Nothing by=Nothing on_incomparable=Problem_Behavior.Ignore =
|
||||
Vector.sort self order on by on_incomparable
|
||||
Array_Like_Helpers.sort self order on by on_incomparable
|
||||
|
||||
## ALIAS first, last, sample, slice
|
||||
GROUP Selections
|
||||
@ -159,7 +159,8 @@ type Array
|
||||
If a `Range`, the selection is specified by two indices, from and to.
|
||||
@range Index_Sub_Range.default_widget
|
||||
take : (Index_Sub_Range | Range | Integer) -> Vector Any
|
||||
take self range=(Index_Sub_Range.First 1) = Vector.take self range
|
||||
take self range=(Index_Sub_Range.First 1) =
|
||||
Array_Like_Helpers.take self range
|
||||
|
||||
## ALIAS skip
|
||||
GROUP Selections
|
||||
@ -173,7 +174,8 @@ type Array
|
||||
If a `Range`, the selection is specified by two indices, from and to.
|
||||
@range Index_Sub_Range.default_widget
|
||||
drop : (Index_Sub_Range | Range | Integer) -> Vector Any
|
||||
drop self range=(Index_Sub_Range.First 1) = Vector.drop self range
|
||||
drop self range=(Index_Sub_Range.First 1) =
|
||||
Array_Like_Helpers.drop self range
|
||||
|
||||
## GROUP Calculations
|
||||
Inserts the given item into the array at the given index.
|
||||
@ -192,7 +194,8 @@ type Array
|
||||
['a', 'b', 'c'].to_array.insert -1 'X' == ['a', 'b', 'X', 'c'].to_array
|
||||
['a', 'b', 'c'].to_array.insert item='X' == ['a', 'b', 'c', 'X'].to_array
|
||||
insert : Integer -> Any -> Vector ! Index_Out_Of_Bounds
|
||||
insert self at=self.length item=Nothing = Vector.insert self at item
|
||||
insert self at=self.length item=Nothing =
|
||||
Array_Like_Helpers.insert self at item
|
||||
|
||||
## GROUP Selections
|
||||
Removes the item at the given index from the array.
|
||||
@ -202,7 +205,7 @@ type Array
|
||||
If the index is less than 0, the index will be counted back from the
|
||||
end.
|
||||
remove : Integer -> Vector
|
||||
remove self at=-1 = Vector.remove self at
|
||||
remove self at=-1 = Array_Like_Helpers.remove self at
|
||||
|
||||
## GROUP Selections
|
||||
ICON select_row
|
||||
@ -262,7 +265,8 @@ type Array
|
||||
|
||||
["ab", "abab", "aba", "bbb"].to_array.index_of (s-> s == s.reverse) == 2
|
||||
index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self condition start=0 = Vector.index_of self condition start
|
||||
index_of self condition (start : Integer = 0) =
|
||||
Array_Like_Helpers.index_of self condition start
|
||||
|
||||
## GROUP Values
|
||||
Returns the last index of an element in the array.
|
||||
@ -284,7 +288,8 @@ type Array
|
||||
|
||||
["ab", "abab", "aba", "bbb"].to_array.last_index_of (s-> s == s.reverse) == 3
|
||||
last_index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self condition start=-1 = Vector.last_index_of self condition start
|
||||
last_index_of self condition (start : Integer = -1) =
|
||||
Array_Like_Helpers.last_index_of self condition start
|
||||
|
||||
## GROUP Logical
|
||||
ICON metadata
|
||||
@ -299,7 +304,7 @@ type Array
|
||||
|
||||
## Converts the array to a list with the same elements.
|
||||
to_list : List
|
||||
to_list self = Vector.to_list self
|
||||
to_list self = Array_Like_Helpers.to_list self
|
||||
|
||||
## GROUP Selections
|
||||
ICON preparation
|
||||
@ -325,7 +330,7 @@ type Array
|
||||
|
||||
[Pair 1 "a", Pair 2 "b", Pair 1 "c"].to_array . distinct (on = _.first) == [Pair 1 "a", Pair 2 "b"].to_array
|
||||
distinct : (Any -> Any) -> Vector Any
|
||||
distinct self (on = x->x) = Vector.distinct self on
|
||||
distinct self (on = x->x) = Array_Like_Helpers.distinct self on
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Applies a function to each element of the array, returning the `Vector` of
|
||||
@ -363,7 +368,8 @@ type Array
|
||||
|
||||
[1, 2, 3].to_array . map +1
|
||||
map : (Any -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
map self function on_problems=Problem_Behavior.Report_Error = Vector.map self function on_problems
|
||||
map self function on_problems=Problem_Behavior.Report_Error =
|
||||
Array_Like_Helpers.map self function on_problems
|
||||
|
||||
## Applies a function to each element of the array, returning the `Vector`
|
||||
that contains all results concatenated.
|
||||
@ -400,7 +406,8 @@ type Array
|
||||
|
||||
[0, 1, 2].to_array . flat_map (n -> Vector.fill n n)
|
||||
flat_map : (Any -> Vector Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
flat_map self function on_problems=Problem_Behavior.Report_Error = Vector.flat_map self function on_problems
|
||||
flat_map self function on_problems=Problem_Behavior.Report_Error =
|
||||
Array_Like_Helpers.flat_map self function on_problems
|
||||
|
||||
## GROUP Selections
|
||||
ICON preparation
|
||||
@ -418,7 +425,7 @@ type Array
|
||||
[1, 2, 3, 4, 5].to_array.filter (> 3)
|
||||
[1, 2, 3, 4, 5].to_array.filter (Filter_Condition.Greater than=3)
|
||||
filter : (Filter_Condition | (Any -> Boolean)) -> Vector Any
|
||||
filter self filter = Vector.filter self filter
|
||||
filter self filter = Array_Like_Helpers.filter self filter
|
||||
|
||||
## GROUP Calculations
|
||||
Transforms an array of arrays into a `Vector` of inner elements - removes
|
||||
@ -429,12 +436,13 @@ type Array
|
||||
|
||||
[[1, 2, 3].to_array, [4, 10].to_array, [].to_array, [0].to_array, [0].to_array].to_array . flatten == [1, 2, 3, 4, 10, 0, 0].to_array
|
||||
flatten : Vector Any
|
||||
flatten self = Vector.flatten self
|
||||
flatten self = Array_Like_Helpers.flatten self
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
short_display_text : Integer -> Text
|
||||
short_display_text self max_entries=10 = Vector.short_display_text self max_entries
|
||||
short_display_text self max_entries=10 =
|
||||
Array_Like_Helpers.short_display_text self max_entries
|
||||
|
||||
## Combines all the elements of the array, by iteratively applying the
|
||||
passed function with the next element of the array. After each step the
|
||||
@ -449,7 +457,8 @@ type Array
|
||||
|
||||
[1, 2, 3].to_array.running_fold 0 (+)
|
||||
running_fold : Any -> (Any -> Any -> Any) -> Vector Any
|
||||
running_fold self init function = Vector.running_fold self init function
|
||||
running_fold self init function =
|
||||
Array_Like_Helpers.running_fold self init function
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Combines all the elements of the array, by iteratively applying the
|
||||
@ -469,7 +478,8 @@ type Array
|
||||
|
||||
[0, 1, 2].to_array . fold 0 (+)
|
||||
fold : Any -> (Any -> Any -> Any) -> Any
|
||||
fold self init function = Vector.fold self init function
|
||||
fold self init function =
|
||||
Array_Like_Helpers.fold self init function
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Combines all the elements of the array, by iteratively applying the
|
||||
@ -485,7 +495,8 @@ type Array
|
||||
|
||||
[0, 1, 2].to_array . 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 = Vector.fold_with_index self init function
|
||||
fold_with_index self init function =
|
||||
Array_Like_Helpers.fold_with_index self init function
|
||||
|
||||
## GROUP Calculations
|
||||
Extend `self` array to the length of `n` appending elements `elem` to
|
||||
@ -508,7 +519,7 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array.pad 5 0 == [1, 2, 3, 4, 5].to_array
|
||||
pad : Integer -> Any -> Vector Any
|
||||
pad self n elem = Vector.pad self n elem
|
||||
pad self n elem = Array_Like_Helpers.pad self n elem
|
||||
|
||||
## GROUP Selections
|
||||
ICON split_text
|
||||
@ -536,7 +547,8 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array.partition (x -> x % 2 == 0) == (Pair [2, 4].to_array [1, 3, 5].to_array)
|
||||
partition : (Filter_Condition | (Any -> Boolean)) -> Pair (Vector Any) (Vector Any)
|
||||
partition self condition = Vector.partition self condition
|
||||
partition self condition =
|
||||
Array_Like_Helpers.partition self condition
|
||||
|
||||
## Partitions the array into `Vector`s of elements which satisfy a given
|
||||
predicate and ones that do not.
|
||||
@ -557,7 +569,8 @@ type Array
|
||||
|
||||
["a", "b", "c", "d"].to_array.partition_with_index (ix -> _ -> ix % 2 == 0) == (Pair ["a", "c"].to_array ["b", "d"].to_array)
|
||||
partition_with_index : (Integer -> Any -> Boolean) -> Pair (Vector Any) (Vector Any)
|
||||
partition_with_index self predicate = Vector.partition_with_index self predicate
|
||||
partition_with_index self predicate =
|
||||
Array_Like_Helpers.partition_with_index self predicate
|
||||
|
||||
## Applies a function to each element of the array, returning the `Vector`
|
||||
of results.
|
||||
@ -597,7 +610,8 @@ type Array
|
||||
|
||||
[1, 2, 3].to_array.map_with_index (+)
|
||||
map_with_index : (Integer -> Any -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
map_with_index self function on_problems=Problem_Behavior.Report_Error = Vector.map_with_index self function on_problems
|
||||
map_with_index self function on_problems=Problem_Behavior.Report_Error =
|
||||
Array_Like_Helpers.map_with_index self function on_problems
|
||||
|
||||
## PRIVATE
|
||||
Creates a new array with the skipping elements until `start` and then
|
||||
@ -612,7 +626,8 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5, 6, 7, 8].to_array.slice 2 5 == [3, 4, 5].to_array
|
||||
slice : Integer -> Integer -> Vector Any
|
||||
slice self start end = Vector.slice self start end
|
||||
slice self start end =
|
||||
Array_Like_Helpers.slice self start end
|
||||
|
||||
## GROUP Selections
|
||||
Returns the first element of the array that satisfies the condition or
|
||||
@ -630,7 +645,8 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array.find (> 3)
|
||||
find : (Filter_Condition | (Any -> Boolean)) -> Integer -> Any -> Any
|
||||
find self condition start=0 ~if_missing=(Error.throw Not_Found) = Vector.find self condition start if_missing
|
||||
find self condition (start : Integer = 0) ~if_missing=(Error.throw Not_Found) =
|
||||
Array_Like_Helpers.find self condition start if_missing
|
||||
|
||||
## ICON select_row
|
||||
Gets an element from the array at a specified index (0-based).
|
||||
@ -642,7 +658,8 @@ type Array
|
||||
of the array, i.e. -1 will correspond to the last element.
|
||||
- if_missing: The value to return if the index is out of bounds.
|
||||
get : Integer -> Any -> Any
|
||||
get self index ~if_missing=Nothing = Vector.get self index if_missing
|
||||
get self index ~if_missing=Nothing =
|
||||
Array_Like_Helpers.get self index if_missing
|
||||
|
||||
## GROUP Logical
|
||||
ICON metadata
|
||||
@ -669,7 +686,8 @@ type Array
|
||||
|
||||
[0, 10, 2, 2].to_array.filter (==) == [0, 2].to_array
|
||||
filter_with_index : (Integer -> Any -> Boolean) -> Vector Any
|
||||
filter_with_index self predicate = Vector.filter_with_index self predicate
|
||||
filter_with_index self predicate =
|
||||
Array_Like_Helpers.filter_with_index self predicate
|
||||
|
||||
## GROUP Calculations
|
||||
ICON join
|
||||
@ -686,7 +704,8 @@ type Array
|
||||
|
||||
["foo", "bar", "baz"].to_array.join ", "
|
||||
join : Text -> Text -> Text -> Text
|
||||
join self separator="" prefix="" suffix="" = Vector.join self separator prefix suffix
|
||||
join self separator:Text="" prefix:Text="" suffix:Text="" =
|
||||
Array_Like_Helpers.join self separator prefix suffix
|
||||
|
||||
## PRIVATE
|
||||
Generates a human-readable text representation of the array.
|
||||
@ -710,7 +729,8 @@ type Array
|
||||
|
||||
[0, 1, 2].to_array . reduce (+)
|
||||
reduce : (Any -> Any -> Any) -> Any -> Any
|
||||
reduce self function ~if_empty=(Error.throw (Empty_Error.Error Array)) = Vector.reduce self function if_empty
|
||||
reduce self function ~if_empty=(Error.throw (Empty_Error.Error Array)) =
|
||||
Array_Like_Helpers.reduce self function if_empty
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -730,7 +750,7 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array.any (x-> x%2 == 0)
|
||||
any : (Filter_Condition | (Any -> Boolean)) -> Boolean
|
||||
any self condition = Vector.any self condition
|
||||
any self condition = Array_Like_Helpers.any self condition
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -750,7 +770,7 @@ type Array
|
||||
|
||||
[-1, 1, 5, 8].to_array.all (x-> x%2 == 0)
|
||||
all : (Filter_Condition | (Any -> Boolean)) -> Boolean
|
||||
all self condition = Vector.all self condition
|
||||
all self condition = Array_Like_Helpers.all self condition
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -831,7 +851,7 @@ type Array
|
||||
|
||||
[1, 2].to_array.reverse
|
||||
reverse : Vector Any
|
||||
reverse self = Vector.reverse self
|
||||
reverse self = Array_Like_Helpers.reverse self
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
@ -848,7 +868,7 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array . each IO.println
|
||||
each : (Any -> Any) -> Nothing
|
||||
each self f = Vector.each self f
|
||||
each self f = Array_Like_Helpers.each self f
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
@ -868,7 +888,7 @@ type Array
|
||||
|
||||
[1, 2, 3, 4, 5].to_array . each_with_index (ix->elem-> IO.println Pair ix elem)
|
||||
each_with_index : (Integer -> Any -> Any) -> Nothing
|
||||
each_with_index self f = Vector.each_with_index self f
|
||||
each_with_index self f = Array_Like_Helpers.each_with_index self f
|
||||
|
||||
## ALIAS append, concatenate, union
|
||||
GROUP Operators
|
||||
@ -884,4 +904,4 @@ type Array
|
||||
|
||||
[1].to_array + [2].to_array
|
||||
+ : Vector Any -> Vector Any
|
||||
+ self that = Vector.+ self that
|
||||
+ self that = Array_Like_Helpers.plus self that
|
||||
|
@ -555,7 +555,7 @@ type List
|
||||
|
||||
example_first = Examples.list.find (> 2)
|
||||
find : (Filter_Condition | (Any -> Boolean)) -> Integer -> Any -> Any
|
||||
find self condition start=0 ~if_missing=(Error.throw Not_Found) =
|
||||
find self condition (start : Integer = 0) ~if_missing=(Error.throw Not_Found) =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
case start.signum of
|
||||
-1 ->
|
||||
@ -583,7 +583,7 @@ type List
|
||||
|
||||
[1, 2, 3, 4, 5].find (> 3)
|
||||
index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self condition start=0 = case start.signum of
|
||||
index_of self condition (start : Integer = 0) = case start.signum of
|
||||
-1 ->
|
||||
node_and_index = find_node_from_end self start
|
||||
found = node_and_index.first.index_of condition 0
|
||||
@ -611,7 +611,7 @@ type List
|
||||
|
||||
[1, 2, 3, 4, 5].find (> 3)
|
||||
last_index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self condition start=-1 = case self of
|
||||
last_index_of self condition (start : Integer = -1) = case self of
|
||||
Nil -> if start == -1 || start == 0 then Nothing else Error.throw (Index_Out_Of_Bounds.Error start 0)
|
||||
Cons _ _ ->
|
||||
length = self.length
|
||||
|
@ -147,7 +147,7 @@ type Pair
|
||||
|
||||
Pair.new 1 6 .find (> 3)
|
||||
find : (Any -> Boolean) -> Integer -> Any -> Any
|
||||
find self predicate start=0 ~if_missing=(Error.throw Not_Found) =
|
||||
find self predicate (start : Integer = 0) ~if_missing=(Error.throw Not_Found) =
|
||||
check_start_valid start used_start->
|
||||
if used_start<1 && predicate self.first then self.first else
|
||||
if used_start<2 && predicate self.second then self.second else
|
||||
@ -169,7 +169,7 @@ type Pair
|
||||
Pair.new 1 2 . index_of 2 == 1
|
||||
Pair.new 2 2 . index_of 2 == 0
|
||||
index_of : (Any | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self element start=0 = check_start_valid start used_start->
|
||||
index_of self element (start : Integer = 0) = check_start_valid start used_start->
|
||||
predicate = case element of
|
||||
_ : Function -> element
|
||||
_ -> (==element)
|
||||
@ -192,7 +192,7 @@ type Pair
|
||||
|
||||
Pair.new 2 2 . last_index_of 2 == 1
|
||||
last_index_of : (Any | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self element start=-1 = check_start_valid start max=2 used_start->
|
||||
last_index_of self element (start : Integer = -1) = check_start_valid start max=2 used_start->
|
||||
predicate = case element of
|
||||
_ : Function -> element
|
||||
_ -> (==element)
|
||||
|
@ -399,7 +399,7 @@ type Range
|
||||
1.up_to 100 . find (Filter_Condition.Greater than=10)
|
||||
@condition range_default_filter_condition_widget
|
||||
find : (Filter_Condition | (Integer -> Boolean)) -> Integer -> Any -> Any
|
||||
find self condition start=0 ~if_missing=Nothing =
|
||||
find self condition (start : Integer = 0) ~if_missing=Nothing =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
check_start_valid start self used_start->
|
||||
result = find_internal self used_start predicate
|
||||
@ -444,7 +444,7 @@ type Range
|
||||
0.up_to 100 . with_step 5 . index_of (>10) == 3
|
||||
@condition range_default_filter_condition_widget
|
||||
index_of : (Integer | Filter_Condition | (Integer -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self condition start=0 =
|
||||
index_of self condition (start : Integer = 0) =
|
||||
check_start_valid start self used_start->
|
||||
case condition of
|
||||
element : Integer -> get_index self used_start self.length-1 element
|
||||
@ -471,7 +471,7 @@ type Range
|
||||
Pair.new 2 2 . last_index_of 2 == 1
|
||||
@condition range_default_filter_condition_widget
|
||||
last_index_of : (Integer | Filter_Condition | (Integer -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self condition start=-1 =
|
||||
last_index_of self condition (start : Integer = -1) =
|
||||
if self.is_empty && (start==-1 || start==0) then Nothing else
|
||||
check_start_valid start self include_end=False used_start->
|
||||
case condition of
|
||||
|
@ -1390,7 +1390,7 @@ Text.locate_all self term="" case_sensitivity=Case_Sensitivity.Sensitive = if te
|
||||
"Hello World!".index_of "J" == Nothing
|
||||
"Hello World!".index_of "o" == 4
|
||||
Text.index_of : Text -> Integer -> Case_Sensitivity -> Integer | Nothing
|
||||
Text.index_of self term="" start=0 case_sensitivity=Case_Sensitivity.Sensitive =
|
||||
Text.index_of self term="" (start : Integer = 0) case_sensitivity=Case_Sensitivity.Sensitive =
|
||||
used_start = if start < 0 then start+self.length else start
|
||||
if used_start < 0 || used_start > self.length then Error.throw (Index_Out_Of_Bounds.Error start self.length+1) else
|
||||
used = if used_start == 0 then self else self.drop used_start
|
||||
|
@ -401,7 +401,7 @@ type Date_Range
|
||||
(Date.new 2020 10 01).up_to (Date.new 2020 10 31) . find (d-> d.day_of_week == Day_Of_Week.Monday)
|
||||
@condition date_range_default_filter_condition_widget
|
||||
find : (Filter_Condition | (Date -> Boolean)) -> Integer -> Any -> Any
|
||||
find self condition start=0 ~if_missing=Nothing =
|
||||
find self condition (start : Integer = 0) ~if_missing=Nothing =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
index = self.index_of predicate start
|
||||
case index of
|
||||
@ -435,7 +435,7 @@ type Date_Range
|
||||
(Date.new 2020 10 01).up_to (Date.new 2020 10 31) . index_of (d-> d.day_of_week == Day_Of_Week.Monday)
|
||||
@condition date_range_default_filter_condition_widget
|
||||
index_of : (Date | Filter_Condition | (Date -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self condition start=0 =
|
||||
index_of self condition (start : Integer = 0) =
|
||||
predicate = unify_condition_for_index_of condition
|
||||
(0.up_to self.length).index_of (ix-> predicate (self.internal_at ix)) start
|
||||
|
||||
@ -455,7 +455,7 @@ type Date_Range
|
||||
(Date.new 2020 10 01).up_to (Date.new 2020 10 31) . last_index_of (d-> d.day_of_week == Day_Of_Week.Monday)
|
||||
@condition date_range_default_filter_condition_widget
|
||||
last_index_of : (Date | Filter_Condition | (Date -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self condition start=-1 =
|
||||
last_index_of self condition (start : Integer = -1) =
|
||||
predicate = unify_condition_for_index_of condition
|
||||
(0.up_to self.length).last_index_of (ix-> predicate (self.internal_at ix)) start
|
||||
|
||||
|
@ -2,7 +2,6 @@ import project.Any.Any
|
||||
import project.Data.Array.Array
|
||||
import project.Data.Filter_Condition.Filter_Condition
|
||||
import project.Data.List.List
|
||||
import project.Data.Map.Map
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Pair.Pair
|
||||
import project.Data.Range.Range
|
||||
@ -27,7 +26,7 @@ import project.Panic.Panic
|
||||
import project.Random.Random
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Data.Filter_Condition import unify_condition_or_predicate, unify_condition_predicate_or_element
|
||||
from project.Data.Index_Sub_Range import drop_helper, Index_Sub_Range, take_helper
|
||||
from project.Data.Index_Sub_Range import Index_Sub_Range
|
||||
from project.Data.Ordering import all
|
||||
from project.Data.Range.Extensions import all
|
||||
|
||||
@ -233,9 +232,7 @@ type Vector a
|
||||
- if_missing: The value to return if the index is out of bounds.
|
||||
get : Integer -> Any -> Any
|
||||
get self index ~if_missing=Nothing =
|
||||
len = self.length
|
||||
if index < -len || index >= len then if_missing else
|
||||
self.at index
|
||||
Array_Like_Helpers.get self index if_missing
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Combines all the elements of the vector, by iteratively applying the
|
||||
@ -256,8 +253,7 @@ type Vector a
|
||||
[0, 1, 2] . fold 0 (+)
|
||||
fold : Any -> (Any -> Any -> Any) -> Any
|
||||
fold self init function =
|
||||
f = acc -> ix -> function acc (self.at ix)
|
||||
0.up_to self.length . fold init f
|
||||
Array_Like_Helpers.fold self init function
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Combines all the elements of the vector, by iteratively applying the
|
||||
@ -274,8 +270,7 @@ type Vector a
|
||||
[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 =
|
||||
f = acc -> ix -> function acc ix (self.at ix)
|
||||
0.up_to self.length . fold init f
|
||||
Array_Like_Helpers.fold_with_index self init function
|
||||
|
||||
## Combines all the elements of the vector, by iteratively applying the
|
||||
passed function with the next element of the vector. After each step the
|
||||
@ -291,11 +286,7 @@ type Vector a
|
||||
[1, 2, 3].running_fold 0 (+)
|
||||
running_fold : Any -> (Any -> Any -> Any) -> Vector Any
|
||||
running_fold self init function =
|
||||
wrapped builder value =
|
||||
current = if builder.length == 0 then init else builder.last
|
||||
builder.append (function current value)
|
||||
built = self.fold (Vector.new_builder self.length) wrapped
|
||||
built.to_vector
|
||||
Array_Like_Helpers.running_fold self init function
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Combines all the elements of a non-empty vector using a binary operation.
|
||||
@ -311,15 +302,7 @@ type Vector a
|
||||
[0, 1, 2] . reduce (+)
|
||||
reduce : (Any -> Any -> Any) -> Any -> Any
|
||||
reduce self function ~if_empty=(Error.throw (Empty_Error.Error Vector)) =
|
||||
len = self.length
|
||||
case len of
|
||||
0 -> if_empty
|
||||
1 -> self.at 0
|
||||
_ ->
|
||||
fold_function current idx =
|
||||
if idx == len then current else
|
||||
@Tail_Call fold_function (function current (self.at idx)) (idx + 1)
|
||||
fold_function (self.at 0) 1
|
||||
Array_Like_Helpers.reduce self function if_empty
|
||||
|
||||
## GROUP Selections
|
||||
Returns the first element of the vector that satisfies the condition or
|
||||
@ -337,12 +320,8 @@ type Vector a
|
||||
|
||||
[1, 2, 3, 4, 5].find (> 3)
|
||||
find : (Filter_Condition | (Any -> Boolean)) -> Integer -> Any -> Any
|
||||
find self condition start=0 ~if_missing=(Error.throw Not_Found) =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
self_len = self.length
|
||||
check_start_valid start self_len used_start->
|
||||
found = used_start.up_to self_len . find (idx -> (predicate (self.at idx)))
|
||||
if found.is_nothing then if_missing else self.at found
|
||||
find self condition (start : Integer = 0) ~if_missing=(Error.throw Not_Found) =
|
||||
Array_Like_Helpers.find self condition start if_missing
|
||||
|
||||
## GROUP Values
|
||||
Returns the index of an element in the vector.
|
||||
@ -364,11 +343,8 @@ type Vector a
|
||||
|
||||
["ab", "abab", "aba", "bbb"].index_of (s-> s == s.reverse) == 2
|
||||
index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
index_of self condition start=0 =
|
||||
self_len = self.length
|
||||
check_start_valid start self_len used_start->
|
||||
predicate = unify_condition_predicate_or_element condition
|
||||
used_start.up_to self.length . find if_missing=Nothing (i-> predicate (self.at i))
|
||||
index_of self condition (start : Integer = 0) =
|
||||
Array_Like_Helpers.index_of self condition start
|
||||
|
||||
## GROUP Values
|
||||
Returns the last index of an element in the vector.
|
||||
@ -390,12 +366,8 @@ type Vector a
|
||||
|
||||
["ab", "abab", "aba", "bbb"].last_index_of (s-> s == s.reverse) == 3
|
||||
last_index_of : (Any | Filter_Condition | (Any -> Boolean)) -> Integer -> Integer | Nothing
|
||||
last_index_of self condition start=-1 =
|
||||
self_len = self.length
|
||||
if self_len == 0 && (start==0 || start==-1) then Nothing else
|
||||
check_start_valid start self_len used_start->
|
||||
predicate = unify_condition_predicate_or_element condition
|
||||
used_start.down_to -1 . find if_missing=Nothing (i-> predicate (self.at i))
|
||||
last_index_of self condition (start : Integer = -1) =
|
||||
Array_Like_Helpers.last_index_of self condition start
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -416,8 +388,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5].any (x-> x%2 == 0)
|
||||
any : (Filter_Condition | (Any -> Boolean)) -> Boolean
|
||||
any self condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
0.up_to self.length . any (idx -> (predicate (self.at idx)))
|
||||
Array_Like_Helpers.any self condition
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -438,8 +409,7 @@ type Vector a
|
||||
[-1, 1, 5, 8].all (x-> x%2 == 0)
|
||||
all : (Filter_Condition | (Any -> Boolean)) -> Boolean
|
||||
all self condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
self.any (predicate >> .not) . not
|
||||
Array_Like_Helpers.all self condition
|
||||
|
||||
## GROUP Logical
|
||||
ICON preparation
|
||||
@ -494,10 +464,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5].filter (Filter_Condition.Greater than=3)
|
||||
filter : (Filter_Condition | (Any -> Boolean)) -> Vector Any
|
||||
filter self filter =
|
||||
predicate = unify_condition_or_predicate filter
|
||||
builder = self.fold Vector.new_builder builder-> elem->
|
||||
if predicate elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
Array_Like_Helpers.filter self filter
|
||||
|
||||
## GROUP Selections
|
||||
ICON preparation
|
||||
@ -514,9 +481,7 @@ type Vector a
|
||||
[0, 10, 2, 2].filter (==) == [0, 2]
|
||||
filter_with_index : (Integer -> Any -> Boolean) -> Vector Any
|
||||
filter_with_index self predicate =
|
||||
builder = self.fold_with_index Vector.new_builder builder-> ix-> elem->
|
||||
if predicate ix elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
Array_Like_Helpers.filter_with_index self predicate
|
||||
|
||||
## GROUP Selections
|
||||
ICON split_text
|
||||
@ -545,14 +510,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5].partition (x -> x % 2 == 0) == (Pair [2, 4] [1, 3, 5])
|
||||
partition : (Filter_Condition | (Any -> Boolean)) -> Pair (Vector Any) (Vector Any)
|
||||
partition self condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
pair = self.fold (Pair.new Vector.new_builder Vector.new_builder) acc-> elem->
|
||||
case predicate elem of
|
||||
True ->
|
||||
Pair.new (acc.first.append elem) acc.second
|
||||
False ->
|
||||
Pair.new acc.first (acc.second.append elem)
|
||||
pair.map .to_vector
|
||||
Array_Like_Helpers.partition self condition
|
||||
|
||||
## Partitions the vector into `Vector`s of elements which satisfy a given
|
||||
predicate and ones that do not.
|
||||
@ -574,11 +532,7 @@ type Vector a
|
||||
["a", "b", "c", "d"].partition_with_index (ix -> _ -> ix % 2 == 0) == (Pair ["a", "c"] ["b", "d"])
|
||||
partition_with_index : (Integer -> Any -> Boolean) -> Pair (Vector Any) (Vector Any)
|
||||
partition_with_index self predicate =
|
||||
pair = self.fold_with_index (Pair.new Vector.new_builder Vector.new_builder) acc-> ix-> elem->
|
||||
case predicate ix elem of
|
||||
True -> Pair.new (acc.first.append elem) acc.second
|
||||
False -> Pair.new acc.first (acc.second.append elem)
|
||||
pair.map .to_vector
|
||||
Array_Like_Helpers.partition_with_index self predicate
|
||||
|
||||
## ICON dataframe_map_column
|
||||
Applies a function to each element of the vector, returning the `Vector` of
|
||||
@ -617,7 +571,7 @@ type Vector a
|
||||
[1, 2, 3] . map +1
|
||||
map : (Any -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
map self function on_problems=Problem_Behavior.Report_Error =
|
||||
Array_Like_Helpers.vector_from_function self.length (function << self.at) on_problems
|
||||
Array_Like_Helpers.map self function on_problems
|
||||
|
||||
## Applies a function to each element of the vector, returning the `Vector`
|
||||
that contains all results concatenated.
|
||||
@ -655,7 +609,7 @@ type Vector a
|
||||
[0, 1, 2] . flat_map (n -> Vector.fill n n)
|
||||
flat_map : (Any -> Vector Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
flat_map self function on_problems=Problem_Behavior.Report_Error =
|
||||
self.map function on_problems . flatten
|
||||
Array_Like_Helpers.flat_map self function on_problems
|
||||
|
||||
## GROUP Calculations
|
||||
Transforms a vector of vectors into a `Vector` of inner elements - removes
|
||||
@ -666,7 +620,7 @@ type Vector a
|
||||
|
||||
[[1, 2, 3], [4, 10], [], [0], [0]] . flatten == [1, 2, 3, 4, 10, 0, 0]
|
||||
flatten : Vector Any
|
||||
flatten self = @Builtin_Method "Vector.flatten"
|
||||
flatten self = Array_Like_Helpers.flatten self
|
||||
|
||||
## Applies a function to each element of the vector, returning the `Vector`
|
||||
of results.
|
||||
@ -707,7 +661,7 @@ type Vector a
|
||||
[1, 2, 3].map_with_index (+)
|
||||
map_with_index : (Integer -> Any -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
|
||||
map_with_index self function on_problems=Problem_Behavior.Report_Error =
|
||||
Array_Like_Helpers.vector_from_function self.length (i-> function i (self.at i)) on_problems
|
||||
Array_Like_Helpers.map_with_index self function on_problems
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
@ -725,8 +679,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5] . each IO.println
|
||||
each : (Any -> Any) -> Nothing
|
||||
each self f =
|
||||
0.up_to self.length . each ix->
|
||||
f (self.at ix)
|
||||
Array_Like_Helpers.each self f
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
@ -747,8 +700,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5] . each_with_index (ix->elem-> IO.println Pair ix elem)
|
||||
each_with_index : (Integer -> Any -> Any) -> Nothing
|
||||
each_with_index self f =
|
||||
0.up_to self.length . each ix->
|
||||
f ix (self.at ix)
|
||||
Array_Like_Helpers.each_with_index self f
|
||||
|
||||
## GROUP Selections
|
||||
Reverses the vector, returning a `Vector` with the same elements, but in
|
||||
@ -759,7 +711,8 @@ type Vector a
|
||||
|
||||
[1, 2].reverse
|
||||
reverse : Vector Any
|
||||
reverse self = Vector.new self.length (i -> self.at (self.length - (1 + i)))
|
||||
reverse self =
|
||||
Array_Like_Helpers.reverse self
|
||||
|
||||
## PRIVATE
|
||||
Generates a human-readable text representation of the vector.
|
||||
@ -786,14 +739,8 @@ type Vector a
|
||||
|
||||
(0.up_to 100).to_vector.short_display_text max_entries=2 == "[0, 1 and 98 more elements]"
|
||||
short_display_text : Integer -> Text
|
||||
short_display_text self max_entries=10 =
|
||||
if max_entries < 1 then Error.throw <| Illegal_Argument.Error "The `max_entries` parameter must be positive." else
|
||||
prefix = self.take (Index_Sub_Range.First max_entries)
|
||||
if prefix.length == self.length then self.to_text else
|
||||
remaining_count = self.length - prefix.length
|
||||
remaining_text = if remaining_count == 1 then "and 1 more element" else
|
||||
"and " + remaining_count.to_text + " more elements"
|
||||
prefix.map .to_text . join ", " "[" " "+remaining_text+"]"
|
||||
short_display_text self (max_entries : Integer = 10) =
|
||||
Array_Like_Helpers.short_display_text self max_entries
|
||||
|
||||
## ALIAS append, concatenate, union
|
||||
GROUP Operators
|
||||
@ -809,9 +756,8 @@ type Vector a
|
||||
|
||||
[1] + [2]
|
||||
+ : Vector Any | Array -> Vector Any
|
||||
+ self that:(Vector | Array) = case that of
|
||||
_ : Vector -> Vector.insert_builtin self self.length that
|
||||
_ : Array -> self + Vector.from_polyglot_array that
|
||||
+ self that:(Vector | Array) =
|
||||
Array_Like_Helpers.plus self that
|
||||
|
||||
## GROUP Calculations
|
||||
Inserts the given item into the vector at the given index.
|
||||
@ -831,15 +777,7 @@ type Vector a
|
||||
['a', 'b', 'c'].insert item='X' == ['a', 'b', 'c', 'X']
|
||||
insert : Integer -> Any -> Vector ! Index_Out_Of_Bounds
|
||||
insert self at=self.length item=Nothing =
|
||||
self_len = self.length
|
||||
used_index = if at < 0 then self_len + at else at
|
||||
if used_index < 0 || used_index > self_len then Error.throw (Index_Out_Of_Bounds.Error at self_len+1) else
|
||||
if used_index == self_len then self + [item] else
|
||||
if used_index == 0 then [item] + self else
|
||||
Vector.insert_builtin self used_index [item]
|
||||
|
||||
## PRIVATE
|
||||
insert_builtin vec at values = @Builtin_Method("Vector.insert_builtin")
|
||||
Array_Like_Helpers.insert self at item
|
||||
|
||||
## GROUP Selections
|
||||
Removes the item at the given index from the vector.
|
||||
@ -850,13 +788,7 @@ type Vector a
|
||||
end.
|
||||
remove : Integer -> Vector
|
||||
remove self at=-1 =
|
||||
self_len = self.length
|
||||
used_index = if at < 0 then self_len + at else at
|
||||
if used_index >= self_len || used_index < 0 then Error.throw (Index_Out_Of_Bounds.Error at self_len) else
|
||||
Vector.remove_builtin self used_index
|
||||
|
||||
## PRIVATE
|
||||
remove_builtin vec at = @Builtin_Method "Vector.remove_builtin"
|
||||
Array_Like_Helpers.remove self at
|
||||
|
||||
## GROUP Calculations
|
||||
ICON join
|
||||
@ -873,10 +805,8 @@ type Vector a
|
||||
|
||||
["foo", "bar", "baz"].join ", "
|
||||
join : Text -> Text -> Text -> Text
|
||||
join self separator="" prefix="" suffix="" =
|
||||
if self.is_empty then prefix+suffix else
|
||||
if self.length == 1 then prefix + self.at 0 + suffix else
|
||||
prefix + self.at 0 + (1.up_to self.length . fold "" acc-> i-> acc + separator + self.at i) + suffix
|
||||
join self separator:Text="" prefix:Text="" suffix:Text="" =
|
||||
Array_Like_Helpers.join self separator prefix suffix
|
||||
|
||||
## PRIVATE
|
||||
Creates a new vector with the skipping elements until `start` and then
|
||||
@ -891,7 +821,7 @@ type Vector a
|
||||
|
||||
[1, 2, 3, 4, 5, 6, 7, 8].slice 2 5 == [3, 4, 5]
|
||||
slice : Integer -> Integer -> Vector Any
|
||||
slice self start end = @Builtin_Method "Vector.slice"
|
||||
slice self start end = Array_Like_Helpers.slice self start end
|
||||
|
||||
## ALIAS first, last, sample, slice
|
||||
GROUP Selections
|
||||
@ -906,16 +836,8 @@ type Vector a
|
||||
If a `Range`, the selection is specified by two indices, from and to.
|
||||
@range Index_Sub_Range.default_widget
|
||||
take : (Index_Sub_Range | Range | Integer) -> Vector Any
|
||||
take self range=(Index_Sub_Range.First 1) = case range of
|
||||
## We are using a specialized implementation for `take Sample`, because
|
||||
the default implementation (which needs to be generic for any
|
||||
collection) generates a random set of indices and then selects these
|
||||
indices, but we can sample the vector directly.
|
||||
Index_Sub_Range.Sample count seed ->
|
||||
rng = Random.new_generator seed
|
||||
rng.items self count
|
||||
_ ->
|
||||
take_helper self.length (self.at _) self.slice (slice_ranges self) range
|
||||
take self range=(Index_Sub_Range.First 1) =
|
||||
Array_Like_Helpers.take self range
|
||||
|
||||
## ALIAS skip
|
||||
GROUP Selections
|
||||
@ -930,7 +852,7 @@ type Vector a
|
||||
@range Index_Sub_Range.default_widget
|
||||
drop : (Index_Sub_Range | Range | Integer) -> Vector Any
|
||||
drop self range=(Index_Sub_Range.First 1) =
|
||||
drop_helper self.length (self.at _) self.slice (slice_ranges self) range
|
||||
Array_Like_Helpers.drop self range
|
||||
|
||||
## ALIAS combine, join by row position, merge
|
||||
GROUP Calculations
|
||||
@ -1006,8 +928,7 @@ type Vector a
|
||||
[1, 2, 3, 4, 5].pad 5 0 == [1, 2, 3, 4, 5]
|
||||
pad : Integer -> Any -> Vector Any
|
||||
pad self n elem =
|
||||
if self.length >= n then self else
|
||||
self + (Vector.fill n-self.length elem)
|
||||
Array_Like_Helpers.pad self n elem
|
||||
|
||||
## GROUP Selections
|
||||
ICON select_row
|
||||
@ -1124,11 +1045,7 @@ type Vector a
|
||||
[My_Type.Value 'hello', 1].sort == [1, My_Type.Value 'hello']
|
||||
sort : Sort_Direction -> (Any -> Any)|Nothing -> (Any -> Any -> (Ordering|Nothing))|Nothing -> Problem_Behavior -> Vector Any ! Incomparable_Values
|
||||
sort self (order = Sort_Direction.Ascending) on=Nothing by=Nothing on_incomparable=Problem_Behavior.Ignore =
|
||||
comps = case on == Nothing of
|
||||
True -> self.map it-> Comparable.from it
|
||||
False -> self.map it-> Comparable.from (on it)
|
||||
compare_funcs = comps.map (it-> it.compare)
|
||||
self.sort_builtin order.to_sign comps compare_funcs by on on_incomparable.to_number
|
||||
Array_Like_Helpers.sort self order on by on_incomparable
|
||||
|
||||
## GROUP Selections
|
||||
ICON preparation
|
||||
@ -1155,14 +1072,7 @@ type Vector a
|
||||
[Pair 1 "a", Pair 2 "b", Pair 1 "c"] . distinct (on = _.first) == [Pair 1 "a", Pair 2 "b"]
|
||||
distinct : (Any -> Any) -> Vector Any
|
||||
distinct self (on = x->x) =
|
||||
builder = Vector.new_builder
|
||||
result = self.fold Map.empty existing->
|
||||
item->
|
||||
key = on item
|
||||
if (existing.get key False) then existing else
|
||||
builder.append item
|
||||
existing.insert key True
|
||||
if result.is_error then result else builder.to_vector
|
||||
Array_Like_Helpers.distinct self on
|
||||
|
||||
## Returns the vector as a `Vector`.
|
||||
to_vector : Vector
|
||||
@ -1170,8 +1080,7 @@ type Vector a
|
||||
|
||||
## Converts the vector to a list with the same elements.
|
||||
to_list : List
|
||||
to_list self =
|
||||
self.reverse.fold List.Nil acc-> elem-> List.Cons elem acc
|
||||
to_list self = Array_Like_Helpers.to_list self
|
||||
|
||||
## PRIVATE
|
||||
type Builder
|
||||
@ -1270,7 +1179,7 @@ type Builder
|
||||
builder = Vector.new_builder
|
||||
builder . append_vector_range [20, 30, 40, 50] 1 3 . to_vector == [30, 40]
|
||||
append_vector_range : Vector Any ! Error -> Integer -> Integer -> Builder ! Error
|
||||
append_vector_range self vector start=0 end=vector.length =
|
||||
append_vector_range self vector (start : Integer = 0) end=vector.length =
|
||||
subrange = vector.slice start end
|
||||
## This workaround is needed because
|
||||
`self.java_builder.addAll subrange.to_array` fails with
|
||||
@ -1393,42 +1302,3 @@ type No_Wrap
|
||||
|
||||
## PRIVATE
|
||||
Wrapped_Error.from (that : Map_Error) = Wrapped_Error.Value that that.inner_error
|
||||
|
||||
## PRIVATE
|
||||
Creates a new vector where for each range, a corresponding section of the
|
||||
source vector is added to the result.
|
||||
|
||||
Assumes that the ranges have been already bounds-checked (for example by
|
||||
passing them through `resolve_ranges`).
|
||||
slice_ranges vector ranges =
|
||||
if ranges.length == 0 then [] else
|
||||
if ranges.length != 1 then slice_many_ranges vector ranges else
|
||||
case ranges.first of
|
||||
_ : Integer -> [vector.at ranges.first]
|
||||
Range.Between start end step -> case step == 1 of
|
||||
True -> vector.slice start end
|
||||
False -> slice_many_ranges vector ranges
|
||||
|
||||
## PRIVATE
|
||||
See `slice_ranges`.
|
||||
slice_many_ranges vector ranges =
|
||||
new_length = ranges.fold 0 acc-> descriptor-> case descriptor of
|
||||
_ : Integer -> acc+1
|
||||
_ : Range -> acc+descriptor.length
|
||||
builder = Vector.new_builder new_length
|
||||
ranges.each descriptor-> case descriptor of
|
||||
_ : Integer ->
|
||||
builder.append (vector.at descriptor)
|
||||
Range.Between start end step -> case step == 1 of
|
||||
True ->
|
||||
builder.append_vector_range vector start end
|
||||
False ->
|
||||
descriptor.each ix->
|
||||
builder.append (vector.at ix)
|
||||
builder.to_vector
|
||||
|
||||
## PRIVATE
|
||||
check_start_valid start length function =
|
||||
used_start = if start < 0 then start + length else start
|
||||
if used_start < 0 || used_start > length then Error.throw (Index_Out_Of_Bounds.Error start length+1) else
|
||||
function used_start
|
||||
|
@ -2,45 +2,62 @@ private
|
||||
|
||||
import project.Any.Any
|
||||
import project.Data.Array.Array
|
||||
import project.Data.List.List
|
||||
import project.Data.Map.Map
|
||||
import project.Data.Maybe.Maybe
|
||||
import project.Data.Numbers.Integer
|
||||
import project.Data.Pair.Pair
|
||||
import project.Data.Range.Range
|
||||
import project.Data.Vector.Map_Error
|
||||
import project.Data.Vector.No_Wrap
|
||||
import project.Data.Vector.Vector
|
||||
import project.Error.Error
|
||||
import project.Errors.Common.Additional_Warnings
|
||||
import project.Errors.Common.Index_Out_Of_Bounds
|
||||
import project.Errors.Illegal_Argument.Illegal_Argument
|
||||
import project.Errors.Problem_Behavior.Problem_Behavior
|
||||
import project.Errors.Unimplemented.Unimplemented
|
||||
import project.Nothing.Nothing
|
||||
import project.Random.Random
|
||||
import project.Runtime
|
||||
import project.Runtime.Ref.Ref
|
||||
import project.Warning.Warning
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Data.Filter_Condition import unify_condition_or_predicate, unify_condition_predicate_or_element
|
||||
from project.Data.Index_Sub_Range import Index_Sub_Range, drop_helper, take_helper
|
||||
from project.Data.Ordering import Comparable
|
||||
from project.Data.Range.Extensions import all
|
||||
|
||||
## PRIVATE
|
||||
new_array_proxy_builtin : Integer -> (Integer -> Any) -> Array
|
||||
new_array_proxy_builtin length at = @Builtin_Method "Array_Like_Helpers.new_array_proxy_builtin"
|
||||
|
||||
## PRIVATE
|
||||
new_vector_builder : Integer -> Any
|
||||
new_vector_builder capacity = @Builtin_Method "Array_Like_Helpers.new_vector_builder"
|
||||
|
||||
## PRIVATE
|
||||
length : (Array | Vector) -> Integer
|
||||
length array_like = @Builtin_Method "Array_Like_Helpers.length"
|
||||
|
||||
## PRIVATE
|
||||
at : (Array | Vector) -> Integer -> Any
|
||||
at array_like index = @Builtin_Method "Array_Like_Helpers.at"
|
||||
|
||||
## PRIVATE
|
||||
vector_to_array : (Vector | Array) -> Array
|
||||
vector_to_array array_like = @Builtin_Method "Array_Like_Helpers.vector_to_array"
|
||||
|
||||
## PRIVATE
|
||||
vector_from_function_primitive : Integer -> (Integer -> Any) -> Vector Any
|
||||
vector_from_function_primitive length constructor = @Builtin_Method "Array_Like_Helpers.vector_from_function"
|
||||
|
||||
flatten : (Vector | Array) -> Vector
|
||||
flatten array_like = @Builtin_Method "Array_Like_Helpers.flatten"
|
||||
|
||||
insert_builtin : (Vector | Array) -> Integer -> (Vector | Array) -> Vector
|
||||
insert_builtin vector at items = @Builtin_Method "Array_Like_Helpers.insert_builtin"
|
||||
|
||||
remove_builtin : (Vector | Array) -> Integer -> Vector
|
||||
remove_builtin vector at = @Builtin_Method "Array_Like_Helpers.remove_builtin"
|
||||
|
||||
slice : (Vector | Array) -> Integer -> Integer -> Vector
|
||||
slice vector start end = @Builtin_Method "Array_Like_Helpers.slice"
|
||||
|
||||
## PRIVATE
|
||||
Construct a Vector by mapping a function over 0..length-1.
|
||||
|
||||
@ -92,3 +109,217 @@ vector_from_function length function on_problems=Problem_Behavior.Report_Error =
|
||||
The maximum number of warnings attached to result values in
|
||||
`vector_from_function`.
|
||||
MAX_MAP_WARNINGS = 10
|
||||
|
||||
## PRIVATE
|
||||
Creates a new vector where for each range, a corresponding section of the
|
||||
source vector is added to the result.
|
||||
|
||||
Assumes that the ranges have been already bounds-checked (for example by
|
||||
passing them through `resolve_ranges`).
|
||||
slice_ranges vector ranges =
|
||||
if ranges.length == 0 then [] else
|
||||
if ranges.length != 1 then slice_many_ranges vector ranges else
|
||||
case ranges.first of
|
||||
_ : Integer -> [vector.at ranges.first]
|
||||
Range.Between start end step -> case step == 1 of
|
||||
True -> vector.slice start end
|
||||
False -> slice_many_ranges vector ranges
|
||||
|
||||
## PRIVATE
|
||||
See `slice_ranges`.
|
||||
slice_many_ranges vector ranges =
|
||||
new_length = ranges.fold 0 acc-> descriptor-> case descriptor of
|
||||
_ : Integer -> acc+1
|
||||
_ : Range -> acc+descriptor.length
|
||||
builder = Vector.new_builder new_length
|
||||
ranges.each descriptor-> case descriptor of
|
||||
_ : Integer ->
|
||||
builder.append (vector.at descriptor)
|
||||
Range.Between start end step -> case step == 1 of
|
||||
True ->
|
||||
builder.append_vector_range vector start end
|
||||
False ->
|
||||
descriptor.each ix->
|
||||
builder.append (vector.at ix)
|
||||
builder.to_vector
|
||||
|
||||
check_start_valid start length function =
|
||||
used_start = if start < 0 then start + length else start
|
||||
if used_start < 0 || used_start > length then Error.throw (Index_Out_Of_Bounds.Error start length+1) else
|
||||
function used_start
|
||||
|
||||
sort vector order on by on_incomparable =
|
||||
comps = case on == Nothing of
|
||||
True -> vector.map it-> Comparable.from it
|
||||
False -> vector.map it-> Comparable.from (on it)
|
||||
compare_funcs = comps.map (it-> it.compare)
|
||||
vector.sort_builtin order.to_sign comps compare_funcs by on on_incomparable.to_number
|
||||
|
||||
distinct vector on =
|
||||
builder = Vector.new_builder
|
||||
result = vector.fold Map.empty existing->
|
||||
item->
|
||||
key = on item
|
||||
if (existing.get key False) then existing else
|
||||
builder.append item
|
||||
existing.insert key True
|
||||
if result.is_error then result else builder.to_vector
|
||||
|
||||
take vector range = case range of
|
||||
## We are using a specialized implementation for `take Sample`, because
|
||||
the default implementation (which needs to be generic for any
|
||||
collection) generates a random set of indices and then selects these
|
||||
indices, but we can sample the vector directly.
|
||||
Index_Sub_Range.Sample count seed ->
|
||||
rng = Random.new_generator seed
|
||||
rng.items vector count
|
||||
_ ->
|
||||
take_helper vector.length (vector.at _) vector.slice (slice_ranges vector) range
|
||||
|
||||
drop vector range =
|
||||
drop_helper vector.length (vector.at _) vector.slice (slice_ranges vector) range
|
||||
|
||||
get vector index ~if_missing =
|
||||
len = vector.length
|
||||
if index < -len || index >= len then if_missing else
|
||||
vector.at index
|
||||
|
||||
insert vector at item =
|
||||
self_len = vector.length
|
||||
used_index = if at < 0 then self_len + at else at
|
||||
if used_index < 0 || used_index > self_len then Error.throw (Index_Out_Of_Bounds.Error at self_len+1) else
|
||||
if used_index == self_len then vector + [item] else
|
||||
if used_index == 0 then [item] + vector else
|
||||
insert_builtin vector used_index [item]
|
||||
|
||||
remove vector at =
|
||||
self_len = vector.length
|
||||
used_index = if at < 0 then self_len + at else at
|
||||
if used_index >= self_len || used_index < 0 then Error.throw (Index_Out_Of_Bounds.Error at self_len) else
|
||||
remove_builtin vector used_index
|
||||
|
||||
index_of vector condition start =
|
||||
self_len = vector.length
|
||||
check_start_valid start self_len used_start->
|
||||
predicate = unify_condition_predicate_or_element condition
|
||||
used_start.up_to vector.length . find if_missing=Nothing (i-> predicate (vector.at i))
|
||||
|
||||
last_index_of vector condition start =
|
||||
self_len = vector.length
|
||||
if self_len == 0 && (start==0 || start==-1) then Nothing else
|
||||
check_start_valid start self_len used_start->
|
||||
predicate = unify_condition_predicate_or_element condition
|
||||
used_start.down_to -1 . find if_missing=Nothing (i-> predicate (vector.at i))
|
||||
|
||||
any vector condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
0.up_to vector.length . any (idx -> (predicate (vector.at idx)))
|
||||
|
||||
all vector condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
vector.any (predicate >> .not) . not
|
||||
|
||||
plus vector that:(Vector | Array) = case that of
|
||||
_ : Vector -> insert_builtin vector vector.length that
|
||||
_ : Array -> plus vector (Vector.from_polyglot_array that)
|
||||
|
||||
find vector condition start ~if_missing =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
self_len = vector.length
|
||||
check_start_valid start self_len used_start->
|
||||
found = used_start.up_to self_len . find (idx -> (predicate (vector.at idx)))
|
||||
if found.is_nothing then if_missing else vector.at found
|
||||
|
||||
map vector function on_problems =
|
||||
vector_from_function vector.length (function << vector.at) on_problems
|
||||
|
||||
map_with_index vector function on_problems =
|
||||
vector_from_function vector.length (i-> function i (vector.at i)) on_problems
|
||||
|
||||
flat_map vector function on_problems =
|
||||
vector.map function on_problems . flatten
|
||||
|
||||
fold vector init function =
|
||||
f = acc -> ix -> function acc (vector.at ix)
|
||||
0.up_to vector.length . fold init f
|
||||
|
||||
fold_with_index vector init function =
|
||||
f = acc -> ix -> function acc ix (vector.at ix)
|
||||
0.up_to vector.length . fold init f
|
||||
|
||||
reduce vector function ~if_empty =
|
||||
len = vector.length
|
||||
case len of
|
||||
0 -> if_empty
|
||||
1 -> vector.at 0
|
||||
_ ->
|
||||
fold_function current idx =
|
||||
if idx == len then current else
|
||||
@Tail_Call fold_function (function current (vector.at idx)) (idx + 1)
|
||||
fold_function (vector.at 0) 1
|
||||
|
||||
running_fold vector init function =
|
||||
wrapped builder value =
|
||||
current = if builder.length == 0 then init else builder.last
|
||||
builder.append (function current value)
|
||||
built = vector.fold (Vector.new_builder vector.length) wrapped
|
||||
built.to_vector
|
||||
|
||||
pad vector n elem =
|
||||
if vector.length >= n then vector else
|
||||
vector + (Vector.fill n-vector.length elem)
|
||||
|
||||
each vector f =
|
||||
0.up_to vector.length . each ix->
|
||||
f (vector.at ix)
|
||||
|
||||
each_with_index vector f =
|
||||
0.up_to vector.length . each ix->
|
||||
f ix (vector.at ix)
|
||||
|
||||
reverse vector = Vector.new vector.length (i -> vector.at (vector.length - (1 + i)))
|
||||
|
||||
to_list vector =
|
||||
vector.reverse.fold List.Nil acc-> elem-> List.Cons elem acc
|
||||
|
||||
short_display_text vector max_entries =
|
||||
if max_entries < 1 then Error.throw <| Illegal_Argument.Error "The `max_entries` parameter must be positive." else
|
||||
prefix = vector.take (Index_Sub_Range.First max_entries)
|
||||
if prefix.length == vector.length then vector.to_text else
|
||||
remaining_count = vector.length - prefix.length
|
||||
remaining_text = if remaining_count == 1 then "and 1 more element" else
|
||||
"and " + remaining_count.to_text + " more elements"
|
||||
prefix.map .to_text . join ", " "[" " "+remaining_text+"]"
|
||||
|
||||
join vector separator prefix suffix =
|
||||
if vector.is_empty then prefix+suffix else
|
||||
if vector.length == 1 then prefix + vector.at 0 + suffix else
|
||||
prefix + vector.at 0 + (1.up_to vector.length . fold "" acc-> i-> acc + separator + vector.at i) + suffix
|
||||
|
||||
partition vector condition =
|
||||
predicate = unify_condition_or_predicate condition
|
||||
pair = vector.fold (Pair.new Vector.new_builder Vector.new_builder) acc-> elem->
|
||||
case predicate elem of
|
||||
True ->
|
||||
Pair.new (acc.first.append elem) acc.second
|
||||
False ->
|
||||
Pair.new acc.first (acc.second.append elem)
|
||||
pair.map .to_vector
|
||||
|
||||
partition_with_index vector predicate =
|
||||
pair = vector.fold_with_index (Pair.new Vector.new_builder Vector.new_builder) acc-> ix-> elem->
|
||||
case predicate ix elem of
|
||||
True -> Pair.new (acc.first.append elem) acc.second
|
||||
False -> Pair.new acc.first (acc.second.append elem)
|
||||
pair.map .to_vector
|
||||
|
||||
filter vector filter =
|
||||
predicate = unify_condition_or_predicate filter
|
||||
builder = vector.fold Vector.new_builder builder-> elem->
|
||||
if predicate elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
|
||||
filter_with_index vector predicate =
|
||||
builder = vector.fold_with_index Vector.new_builder builder-> ix-> elem->
|
||||
if predicate ix elem then builder.append elem else builder
|
||||
builder.to_vector
|
||||
|
@ -50,11 +50,11 @@ type Warning
|
||||
|
||||
Arguments:
|
||||
- warning_type: The type to throw if attached to the value. Defaults to all warnings.
|
||||
throw_on_warning : Any -> Any
|
||||
throw_on_warning self warning_type=Any =
|
||||
warnings = Warning.get_all self
|
||||
throw_on_warning : Any -> Any -> Any
|
||||
throw_on_warning value warning_type=Any =
|
||||
warnings = Warning.get_all value
|
||||
first = warnings.find (w-> w.value.is_a warning_type) if_missing=Nothing
|
||||
if first.is_nothing then self else Error.throw first.value
|
||||
if first.is_nothing then value else Error.throw first.value
|
||||
|
||||
## PRIVATE
|
||||
ADVANCED
|
||||
|
@ -998,6 +998,13 @@ object BindingsMap {
|
||||
s"The name `${originalName.name}` could not be found"
|
||||
}
|
||||
|
||||
/** A resolution error due to usage of Self type reference outside of a type scope.
|
||||
*/
|
||||
case object SelfTypeOutsideOfTypeDefinition extends ResolutionError {
|
||||
override def explain(originalName: ir.Name): String =
|
||||
s"The Self type is not applicable outside of a type definition"
|
||||
}
|
||||
|
||||
/** A metadata-friendly storage for resolutions */
|
||||
case class Resolution(target: ResolvedName) extends IRPass.IRMetadata {
|
||||
|
||||
|
@ -100,19 +100,24 @@ case object MethodDefinitions extends IRPass {
|
||||
case Some(Resolution(ResolvedType(_, tp)))
|
||||
if canGenerateStaticWrappers(tp) =>
|
||||
val dup = method.duplicate()
|
||||
val static = dup.copy(body =
|
||||
new Function.Lambda(
|
||||
List(
|
||||
DefinitionArgument
|
||||
.Specified(
|
||||
Name.Self(None, true),
|
||||
// This is the self argument that will receive the `SelfType.type` value upon dispatch, it is added to avoid modifying the dispatch mechanism.
|
||||
val syntheticModuleSelfArg = DefinitionArgument.Specified(
|
||||
Name.Self(None, synthetic = true),
|
||||
None,
|
||||
None,
|
||||
false,
|
||||
suspended = false,
|
||||
None
|
||||
)
|
||||
),
|
||||
dup.body,
|
||||
|
||||
// The actual `self` argument that is referenced inside of method body is the second one in the lambda.
|
||||
// This is the argument that will hold the actual instance of the object we are calling on, e.g. `My_Type.method instance`.
|
||||
// We add a type check to it to ensure only `instance` of `My_Type` can be passed to it.
|
||||
val static = dup.copy(body =
|
||||
new Function.Lambda(
|
||||
// This is the synthetic Self argument that gets the static module
|
||||
List(syntheticModuleSelfArg),
|
||||
// Here we add the type ascription ensuring that the 'proper' self argument only accepts _instances_ of the type (or triggers conversions)
|
||||
addTypeAscriptionToSelfArgument(dup.body),
|
||||
None
|
||||
)
|
||||
)
|
||||
@ -127,11 +132,43 @@ case object MethodDefinitions extends IRPass {
|
||||
ir.copy(bindings = withStaticAliases)
|
||||
}
|
||||
|
||||
private def addTypeAscriptionToSelfArgument(
|
||||
methodBody: Expression
|
||||
): Expression = methodBody match {
|
||||
case lambda: Function.Lambda =>
|
||||
val newArguments = lambda.arguments match {
|
||||
case (selfArg @ DefinitionArgument.Specified(
|
||||
Name.Self(_, _, _, _),
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_
|
||||
)) :: rest =>
|
||||
val selfType = Name.SelfType(location = selfArg.location)
|
||||
selfArg.copy(ascribedType = Some(selfType)) :: rest
|
||||
case other :: _ =>
|
||||
throw new CompilerError(
|
||||
s"MethodDefinitions pass: expected the first argument to be `self`, but got $other"
|
||||
)
|
||||
case Nil =>
|
||||
throw new CompilerError(
|
||||
s"MethodDefinitions pass: expected at least one argument (self) in the method, but got none."
|
||||
)
|
||||
}
|
||||
lambda.copy(arguments = newArguments)
|
||||
case other =>
|
||||
throw new CompilerError(
|
||||
s"Unexpected body type $other in MethodDefinitions pass."
|
||||
)
|
||||
}
|
||||
|
||||
// Generate static wrappers for
|
||||
// 1. Types having at least one type constructor
|
||||
// 2. All builtin types except for Nothing. Nothing's eigentype is Nothing and not Nothing.type,
|
||||
// would lead to overriding conflicts.
|
||||
// TODO: Remvoe the hardcoded type once Enso's annotations can define parameters.
|
||||
// TODO: Remove the hardcoded type once Enso's annotations can define parameters.
|
||||
private def canGenerateStaticWrappers(tp: Type): Boolean =
|
||||
tp.members.nonEmpty || (tp.builtinType && (tp.name != "Nothing"))
|
||||
|
||||
|
@ -2,13 +2,12 @@ package org.enso.compiler.pass.resolve
|
||||
|
||||
import org.enso.compiler.context.{InlineContext, ModuleContext}
|
||||
import org.enso.compiler.core.Implicits.AsMetadata
|
||||
import org.enso.compiler.core.IR
|
||||
import org.enso.compiler.core.ir.{Expression, Function, Module, Name}
|
||||
import org.enso.compiler.core.ir.MetadataStorage.MetadataPair
|
||||
import org.enso.compiler.core.ir.expression.errors
|
||||
import org.enso.compiler.core.ir.module.scope.Definition
|
||||
import org.enso.compiler.core.ir.module.scope.definition.Method
|
||||
import org.enso.compiler.core.ir.MetadataStorage.MetadataPair
|
||||
import org.enso.compiler.core.ir.`type`
|
||||
import org.enso.compiler.core.ir.{`type`, Expression, Function, Module, Name}
|
||||
import org.enso.compiler.core.{CompilerError, IR}
|
||||
import org.enso.compiler.data.BindingsMap
|
||||
import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedModule}
|
||||
import org.enso.compiler.pass.IRPass
|
||||
@ -47,43 +46,81 @@ case object TypeNames extends IRPass {
|
||||
val bindingsMap =
|
||||
ir.unsafeGetMetadata(BindingAnalysis, "bindings analysis did not run")
|
||||
ir.copy(bindings = ir.bindings.map { d =>
|
||||
val typeParams: List[Name] = d match {
|
||||
case t: Definition.Type => t.params.map(_.name)
|
||||
val selfTypeInfo: SelfTypeInfo = d match {
|
||||
case t: Definition.Type => SelfTypeInfo.fromTypeDefinition(t)
|
||||
case m: Method.Explicit =>
|
||||
val params: List[Name] = m.methodReference.typePointer
|
||||
.flatMap { p =>
|
||||
p.getMetadata(MethodDefinitions)
|
||||
.map(_.target match {
|
||||
case typ: BindingsMap.ResolvedType =>
|
||||
typ.tp.params.map(Name.Literal(_, false, None)).toList
|
||||
case _ => List()
|
||||
})
|
||||
}
|
||||
.getOrElse(List())
|
||||
params
|
||||
case _ => Nil
|
||||
SelfTypeInfo.fromMethodReference(m.methodReference)
|
||||
case _ => SelfTypeInfo.empty
|
||||
}
|
||||
|
||||
val mapped =
|
||||
d.mapExpressions(resolveExpression(typeParams, bindingsMap, _))
|
||||
doResolveType(
|
||||
typeParams,
|
||||
bindingsMap,
|
||||
mapped match {
|
||||
d.mapExpressions(
|
||||
resolveExpression(selfTypeInfo, bindingsMap, _)
|
||||
)
|
||||
val withResolvedArguments = mapped match {
|
||||
case typ: Definition.Type =>
|
||||
typ.members.foreach(m =>
|
||||
m.arguments.foreach(a =>
|
||||
doResolveType(typ.params.map(_.name), bindingsMap, a)
|
||||
doResolveType(
|
||||
SelfTypeInfo.fromTypeDefinition(typ),
|
||||
bindingsMap,
|
||||
a
|
||||
)
|
||||
)
|
||||
)
|
||||
typ
|
||||
case x => x
|
||||
}
|
||||
)
|
||||
doResolveType(selfTypeInfo, bindingsMap, withResolvedArguments)
|
||||
})
|
||||
}
|
||||
|
||||
private case class SelfTypeInfo(
|
||||
selfType: Option[BindingsMap.ResolvedType],
|
||||
typeParams: List[Name]
|
||||
)
|
||||
|
||||
private case object SelfTypeInfo {
|
||||
def empty: SelfTypeInfo = SelfTypeInfo(None, Nil)
|
||||
|
||||
def fromTypeDefinition(d: Definition.Type): SelfTypeInfo = {
|
||||
// TODO currently the `Self` type is only used internally as an ascription for static method bindings
|
||||
// Once we actually start supporting the `Self` syntax, we should set the self type here to the ResolvedType
|
||||
// corresponding to the current definition, so that we can correctly resolve `Self` references in constructor
|
||||
// argument types.
|
||||
val selfType = None
|
||||
val typeParams = d.params.map(_.name)
|
||||
SelfTypeInfo(selfType, typeParams)
|
||||
}
|
||||
|
||||
def fromMethodReference(m: Name.MethodReference): SelfTypeInfo =
|
||||
m.typePointer match {
|
||||
case Some(p) =>
|
||||
p.getMetadata(MethodDefinitions) match {
|
||||
case Some(resolution) =>
|
||||
resolution.target match {
|
||||
case typ: BindingsMap.ResolvedType =>
|
||||
val params =
|
||||
typ.tp.params.map(Name.Literal(_, false, None)).toList
|
||||
SelfTypeInfo(Some(typ), params)
|
||||
case _: BindingsMap.ResolvedModule =>
|
||||
SelfTypeInfo.empty
|
||||
case other =>
|
||||
throw new CompilerError(
|
||||
s"Method target not resolved as ResolvedType, but $other."
|
||||
)
|
||||
}
|
||||
case None =>
|
||||
// It is unexpected that the metadata is missing here, but we don't fail because other passes should fail
|
||||
// with more detailed info.
|
||||
SelfTypeInfo.empty
|
||||
}
|
||||
case None => SelfTypeInfo.empty
|
||||
}
|
||||
}
|
||||
|
||||
private def resolveExpression(
|
||||
typeParams: List[Name],
|
||||
selfTypeInfo: SelfTypeInfo,
|
||||
bindingsMap: BindingsMap,
|
||||
ir: Expression
|
||||
): Expression = {
|
||||
@ -91,17 +128,23 @@ case object TypeNames extends IRPass {
|
||||
val processedIr = ir match {
|
||||
case fn: Function.Lambda =>
|
||||
fn.copy(arguments =
|
||||
fn.arguments.map(doResolveType(typeParams, bindingsMap, _))
|
||||
fn.arguments.map(
|
||||
doResolveType(selfTypeInfo, bindingsMap, _)
|
||||
)
|
||||
)
|
||||
case x => x
|
||||
}
|
||||
doResolveType(typeParams, bindingsMap, processedIr.mapExpressions(go))
|
||||
doResolveType(
|
||||
selfTypeInfo,
|
||||
bindingsMap,
|
||||
processedIr.mapExpressions(go)
|
||||
)
|
||||
}
|
||||
go(ir)
|
||||
}
|
||||
|
||||
private def doResolveType[T <: IR](
|
||||
typeParams: List[Name],
|
||||
selfTypeInfo: SelfTypeInfo,
|
||||
bindingsMap: BindingsMap,
|
||||
ir: T
|
||||
): T = {
|
||||
@ -111,7 +154,7 @@ case object TypeNames extends IRPass {
|
||||
new MetadataPair(
|
||||
TypeSignatures,
|
||||
TypeSignatures.Signature(
|
||||
resolveSignature(typeParams, bindingsMap, s.signature),
|
||||
resolveSignature(selfTypeInfo, bindingsMap, s.signature),
|
||||
s.comment
|
||||
)
|
||||
)
|
||||
@ -121,14 +164,14 @@ case object TypeNames extends IRPass {
|
||||
}
|
||||
|
||||
private def resolveSignature(
|
||||
typeParams: List[Name],
|
||||
selfTypeInfo: SelfTypeInfo,
|
||||
bindingsMap: BindingsMap,
|
||||
expression: Expression
|
||||
): Expression =
|
||||
expression.transformExpressions {
|
||||
case expr if SuspendedArguments.representsSuspended(expr) => expr
|
||||
case n: Name.Literal =>
|
||||
if (typeParams.exists(_.name == n.name)) {
|
||||
if (selfTypeInfo.typeParams.exists(_.name == n.name)) {
|
||||
n
|
||||
} else {
|
||||
processResolvedName(n, bindingsMap.resolveName(n.name))
|
||||
@ -138,8 +181,13 @@ case object TypeNames extends IRPass {
|
||||
n,
|
||||
bindingsMap.resolveQualifiedName(n.parts.map(_.name))
|
||||
)
|
||||
case selfRef: Name.SelfType =>
|
||||
val resolvedSelfType = selfTypeInfo.selfType.toRight {
|
||||
BindingsMap.SelfTypeOutsideOfTypeDefinition
|
||||
}
|
||||
processResolvedName(selfRef, resolvedSelfType)
|
||||
case s: `type`.Set =>
|
||||
s.mapExpressions(resolveSignature(typeParams, bindingsMap, _))
|
||||
s.mapExpressions(resolveSignature(selfTypeInfo, bindingsMap, _))
|
||||
}
|
||||
|
||||
private def processResolvedName(
|
||||
|
@ -12,7 +12,6 @@ import org.graalvm.polyglot.Source;
|
||||
import org.graalvm.polyglot.Value;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class BinaryDispatchTest extends TestBase {
|
||||
@ -212,7 +211,6 @@ public class BinaryDispatchTest extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // PENDING: #8805
|
||||
public void staticWithRFirstArgumentIsConverted() {
|
||||
var rOperator = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "R.---");
|
||||
|
||||
@ -251,7 +249,6 @@ public class BinaryDispatchTest extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // PENDING #8805
|
||||
public void staticWithRFirstAndZSecondNoConversionHappens() {
|
||||
var zOperator = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "Z.---");
|
||||
|
||||
|
@ -398,6 +398,45 @@ public class SignatureTest extends TestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runtimeCheckOfSelfType() throws Exception {
|
||||
final URI uri = new URI("memory://self_type_check.enso");
|
||||
final Source src =
|
||||
Source.newBuilder(
|
||||
"enso",
|
||||
"""
|
||||
from Standard.Base import all
|
||||
type My_Type
|
||||
Value x
|
||||
f self y = self.x+y
|
||||
|
||||
type Other_Type
|
||||
Ctor x
|
||||
|
||||
normal_call = (My_Type.Value 42).f 10
|
||||
static_call = My_Type.f (My_Type.Value 23) 100
|
||||
invalid_static_call = My_Type.f (Other_Type.Ctor 11) 1000
|
||||
""",
|
||||
uri.getAuthority())
|
||||
.uri(uri)
|
||||
.buildLiteral();
|
||||
|
||||
var module = ctx.eval(src);
|
||||
var normal_call = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "normal_call");
|
||||
assertEquals("Normal call", 52, normal_call.asInt());
|
||||
|
||||
var static_call = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "static_call");
|
||||
assertEquals("Static call", 123, static_call.asInt());
|
||||
|
||||
try {
|
||||
var invalid_static_call =
|
||||
module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "invalid_static_call");
|
||||
fail("Expecting an exception, not: " + invalid_static_call);
|
||||
} catch (PolyglotException e) {
|
||||
assertTypeError("`self`", "My_Type", "Other_Type", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrongAscribedInConstructor() throws Exception {
|
||||
final URI uri = new URI("memory://constructor.enso");
|
||||
@ -573,6 +612,55 @@ public class SignatureTest extends TestBase {
|
||||
assertEquals(42, fourtyTwoAsV.getMember("a").asInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selfTypeConversion() throws Exception {
|
||||
final URI uri = new URI("memory://self_type_conversion.enso");
|
||||
final Source src =
|
||||
Source.newBuilder(
|
||||
"enso",
|
||||
"""
|
||||
from Standard.Base import all
|
||||
type My_Type
|
||||
Value x
|
||||
f self y = self.x+y
|
||||
|
||||
type Convertible_Type
|
||||
A x
|
||||
|
||||
type Inconvertible_Type
|
||||
B x
|
||||
|
||||
My_Type.from (that : Convertible_Type) = My_Type.Value that.x+1
|
||||
|
||||
static_my_type = My_Type.f (My_Type.Value 23) 1000
|
||||
static_convertible = My_Type.f (Convertible_Type.A 23) 1000
|
||||
static_inconvertible = My_Type.f (Inconvertible_Type.B 23) 1000
|
||||
""",
|
||||
uri.getAuthority())
|
||||
.uri(uri)
|
||||
.buildLiteral();
|
||||
|
||||
var module = ctx.eval(src);
|
||||
var static_my_type = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "static_my_type");
|
||||
assertEquals(
|
||||
"My_Type.f is executed directly on 23, yielding 1023", 1023, static_my_type.asInt());
|
||||
|
||||
var convertible = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "static_convertible");
|
||||
assertEquals(
|
||||
"My_Type.f is executed on the converted value, so 23 is incremented to 24, yielding 1024"
|
||||
+ " proving that the conversion has been applied",
|
||||
1024,
|
||||
convertible.asInt());
|
||||
|
||||
try {
|
||||
var invalid_static_call =
|
||||
module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "static_inconvertible");
|
||||
fail("Expecting an exception, not: " + invalid_static_call);
|
||||
} catch (PolyglotException e) {
|
||||
assertTypeError("`self`", "My_Type", "Inconvertible_Type", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Value exampleWithBinary() throws URISyntaxException {
|
||||
var uri = new URI("memory://binary.enso");
|
||||
var src =
|
||||
|
@ -208,5 +208,25 @@ class DataflowErrorsTest extends InterpreterTest {
|
||||
"(Syntax_Error.Error 'Unexpected expression')"
|
||||
)
|
||||
}
|
||||
|
||||
"report correct stack trace for errors thrown from a suspended default argument" in {
|
||||
val code =
|
||||
"""import Standard.Base.IO
|
||||
|import Standard.Base.Error.Error
|
||||
|
|
||||
|type My_Error
|
||||
| Value
|
||||
|
|
||||
|fn x ~y=(Error.throw My_Error.Value) =
|
||||
| if x == 0 then 0 else y
|
||||
|
|
||||
|main =
|
||||
| IO.println (fn 1).get_stack_trace_text
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
consumeOut should contain(
|
||||
" at <enso> <default::Test.fn::y>(Test:7:10-35)"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class MethodsTest extends InterpreterTest {
|
||||
): Unit = {
|
||||
"be defined in the global scope and dispatched to" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|type Foo
|
||||
|Foo.bar = number -> number + 1
|
||||
|main = Foo.bar 10
|
||||
@ -37,7 +37,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|
||||
"be callable with dot operator" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|type Foo
|
||||
|Foo.bar = number -> number + 1
|
||||
|main = Foo.bar 10
|
||||
@ -47,7 +47,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|
||||
"be chainable with dot operator" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|type Foo
|
||||
|type Bar
|
||||
|type Baz
|
||||
@ -63,7 +63,7 @@ class MethodsTest extends InterpreterTest {
|
||||
|
||||
"behave like parenthesised when called with non-spaced dot operator" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|type Foo
|
||||
|type Bar
|
||||
|
|
||||
@ -78,7 +78,8 @@ class MethodsTest extends InterpreterTest {
|
||||
|
||||
"be able to be defined without arguments" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|
|
||||
|type Foo
|
||||
|Foo.bar = 1
|
||||
|main = Foo.bar + 5
|
||||
@ -89,6 +90,7 @@ class MethodsTest extends InterpreterTest {
|
||||
"be definable as blocks without arguments" in {
|
||||
val code =
|
||||
"""import Standard.Base.Any.Any
|
||||
|import Standard.Base.Data.Numbers
|
||||
|
|
||||
|Any.method self =
|
||||
| x = self * self
|
||||
@ -169,7 +171,8 @@ class MethodsTest extends InterpreterTest {
|
||||
|
||||
"be callable on types when non-static, with additional self arg" in {
|
||||
val code =
|
||||
"""import Standard.Base.IO
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|import Standard.Base.IO
|
||||
|
|
||||
|type Foo
|
||||
| Mk_Foo a
|
||||
|
@ -11,7 +11,8 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
|
||||
"work in basic expressions" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|
|
||||
|main =
|
||||
| lazyId : Suspended -> a
|
||||
| lazyId = x -> x
|
||||
@ -38,6 +39,7 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|import Standard.Base.Any.Any
|
||||
|import Standard.Base.Data.Numbers
|
||||
|
|
||||
|main =
|
||||
| ifTest = c -> ~ifT -> ~ifF -> if c == 0 then ifT else ifF
|
||||
@ -49,7 +51,9 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
|
||||
"work in non-tail positions" in {
|
||||
val code =
|
||||
"""
|
||||
"""import Standard.Base.Data.Numbers
|
||||
|import Standard.Base.Data.Numbers.Number
|
||||
|
|
||||
|main =
|
||||
| suspInc : Suspended -> Number
|
||||
| suspInc = ~x -> 1 + x
|
||||
|
@ -16,7 +16,7 @@ import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Vector",
|
||||
type = "Array_Like_Helpers",
|
||||
name = "flatten",
|
||||
description = "Flattens a vector of vectors into a single vector.",
|
||||
autoRegister = false)
|
||||
@ -25,15 +25,15 @@ public abstract class FlattenVectorNode extends Node {
|
||||
return FlattenVectorNodeGen.create();
|
||||
}
|
||||
|
||||
abstract EnsoObject execute(Object self);
|
||||
abstract EnsoObject execute(Object vector);
|
||||
|
||||
@Specialization
|
||||
EnsoObject flattenAnything(
|
||||
Object self,
|
||||
Object vector,
|
||||
@Cached ArrayLikeCopyToArrayNode copyNode,
|
||||
@Cached ArrayLikeLengthNode lengthNode,
|
||||
@Cached ArrayLikeAtNode atNode) {
|
||||
return flatten(self, copyNode, lengthNode, atNode);
|
||||
return flatten(vector, copyNode, lengthNode, atNode);
|
||||
}
|
||||
|
||||
private EnsoObject flatten(
|
||||
|
@ -10,7 +10,7 @@ import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Vector",
|
||||
type = "Array_Like_Helpers",
|
||||
name = "insert_builtin",
|
||||
description = "Inserts a set of values into the Vector at the specified index.",
|
||||
autoRegister = false)
|
||||
|
@ -10,7 +10,7 @@ import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Vector",
|
||||
type = "Array_Like_Helpers",
|
||||
name = "remove_builtin",
|
||||
description = "Removes a value for the vector at the specified index.",
|
||||
autoRegister = false)
|
||||
|
@ -5,7 +5,10 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeHelpers;
|
||||
import org.enso.interpreter.runtime.data.vector.ArrayLikeLengthNode;
|
||||
|
||||
@BuiltinMethod(type = "Vector", name = "slice", description = "Returns a slice of this Vector.")
|
||||
@BuiltinMethod(
|
||||
type = "Array_Like_Helpers",
|
||||
name = "slice",
|
||||
description = "Returns a slice of this Vector.")
|
||||
public final class SliceArrayVectorNode extends Node {
|
||||
private @Child ArrayLikeLengthNode lengthNode = ArrayLikeLengthNode.create();
|
||||
|
||||
@ -15,8 +18,8 @@ public final class SliceArrayVectorNode extends Node {
|
||||
return new SliceArrayVectorNode();
|
||||
}
|
||||
|
||||
Object execute(Object self, long start, long end) {
|
||||
var len = lengthNode.executeLength(self);
|
||||
return ArrayLikeHelpers.slice(self, start, end, len);
|
||||
Object execute(Object vector, long start, long end) {
|
||||
var len = lengthNode.executeLength(vector);
|
||||
return ArrayLikeHelpers.slice(vector, start, end, len);
|
||||
}
|
||||
}
|
||||
|
@ -2256,7 +2256,7 @@ class IrToTruffle(
|
||||
*
|
||||
* @param inputArg the argument to generate code for
|
||||
* @param position the position of `arg` at the function definition site
|
||||
* @param checkNode null or node to check the argument type for
|
||||
* @param types null or node to check the argument type for
|
||||
* @return a truffle entity corresponding to the definition of `arg` for a
|
||||
* given function
|
||||
*/
|
||||
@ -2273,13 +2273,14 @@ class IrToTruffle(
|
||||
|
||||
// Note [Handling Suspended Defaults]
|
||||
val defaultedValue = if (arg.suspended && defaultExpression != null) {
|
||||
assert(arg.defaultValue.isDefined)
|
||||
val defaultRootNode = ClosureRootNode.build(
|
||||
language,
|
||||
scope,
|
||||
moduleScope,
|
||||
defaultExpression,
|
||||
null,
|
||||
s"<default::$scopeName::${arg.name}>",
|
||||
makeSection(moduleScope, arg.defaultValue.get.location()),
|
||||
s"<default::$scopeName::${arg.name.showCode()}>",
|
||||
false,
|
||||
false
|
||||
)
|
||||
|
@ -539,7 +539,7 @@ type_spec suite_builder name alter = suite_builder.group name group_builder->
|
||||
vec.slice 1 3 . should_equal [2, 3]
|
||||
vec.slice 1 1 . should_equal []
|
||||
vec.slice 0 100 . should_equal [1, 2, 3, 4, 5, 6]
|
||||
Meta.is_same_object vec (vec.slice 0 100) . should_be_true
|
||||
|
||||
Meta.get_qualified_type_name (vec.slice 1 1) . should_equal (Meta.meta Vector . qualified_name)
|
||||
Meta.get_simple_type_name (vec.slice 1 1) . should_equal "Vector"
|
||||
|
||||
@ -1086,4 +1086,3 @@ main =
|
||||
suite = Test.build suite_builder->
|
||||
add_specs suite_builder
|
||||
suite.run_with_filter
|
||||
|
||||
|
@ -5,7 +5,9 @@ import project.Semantic.Definitions.Names
|
||||
|
||||
from Standard.Test import all
|
||||
|
||||
|
||||
## This test is important as it also ensures that we can define extension
|
||||
methods on modules that are not directly imported, but accessed through
|
||||
a (not-fully) qualified name.
|
||||
Names.Foo.my_method self = case self of
|
||||
Names.Foo.Value x y z -> x * y * z
|
||||
|
||||
|
@ -266,7 +266,7 @@ add_specs suite_builder = suite_builder.group "Dataflow Warnings" group_builder-
|
||||
no_error = warned.remove_warnings Unimplemented
|
||||
Warning.get_all no_error . map .value . should_equal [1, "Alpha", Nothing]
|
||||
|
||||
group_builder.specify "should allow to throwing warnings, by type" <|
|
||||
group_builder.specify "should allow raising warnings as errors, by type" <|
|
||||
warned = Warning.attach 1 <| Warning.attach "Alpha" <| Warning.attach Nothing <| Warning.attach (Unimplemented.Error "An Error Here") "foo"
|
||||
|
||||
warned.throw_on_warning . should_fail_with Integer
|
||||
|
@ -1,6 +1,6 @@
|
||||
import project.Data.Vector.Vector
|
||||
from project.Data.Vector import array_like_at, array_like_length
|
||||
|
||||
@Builtin_Type
|
||||
type Array
|
||||
at self index = Vector.at self index
|
||||
length self = Vector.length self
|
||||
at self index = array_like_at self index
|
||||
length self = array_like_length self
|
||||
|
Loading…
Reference in New Issue
Block a user