diff --git a/CHANGELOG.md b/CHANGELOG.md index 886b8f86fc0d..916f0f9c5264 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso index 838db6eba721..dd3f64bacecc 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/List.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/List.enso index 7bb0631d44a2..6fe810bd3996 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/List.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/List.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso index 2610530b47c0..f13e84de2a39 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Pair.enso @@ -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) diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso index 59fd9ae2fa6b..d63f7b516176 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Range.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso index 786c88574287..64e0f25dd3f1 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Text/Extensions.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Range.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Range.enso index 92da73574609..f9312d409dc7 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Range.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date_Range.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso index a6c06c172af6..24f7c648671a 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso index 3a7abc0a1cf0..8ab06d903094 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso @@ -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 diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso index c5819c69b68c..b4f2e7222007 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Warning.enso @@ -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 diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/data/BindingsMap.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/data/BindingsMap.scala index ba18b6c98d73..ac708439bd7c 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/data/BindingsMap.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/data/BindingsMap.scala @@ -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 { diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala index 43c02e16a960..c6614db7d8d0 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala @@ -100,19 +100,24 @@ case object MethodDefinitions extends IRPass { case Some(Resolution(ResolvedType(_, tp))) if canGenerateStaticWrappers(tp) => val dup = method.duplicate() + // 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, + suspended = false, + None + ) + + // 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( - List( - DefinitionArgument - .Specified( - Name.Self(None, true), - None, - None, - false, - None - ) - ), - dup.body, + // 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")) diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala index 8272b7c1982d..24f5db9ee2f5 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala @@ -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 { - case typ: Definition.Type => - typ.members.foreach(m => - m.arguments.foreach(a => - doResolveType(typ.params.map(_.name), bindingsMap, a) + d.mapExpressions( + resolveExpression(selfTypeInfo, bindingsMap, _) + ) + val withResolvedArguments = mapped match { + case typ: Definition.Type => + typ.members.foreach(m => + m.arguments.foreach(a => + doResolveType( + SelfTypeInfo.fromTypeDefinition(typ), + bindingsMap, + a ) ) - typ - case x => x - } - ) + ) + 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( diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/BinaryDispatchTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/BinaryDispatchTest.java index f0a0be891060..5443f061e296 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/BinaryDispatchTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/BinaryDispatchTest.java @@ -12,7 +12,6 @@ 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 void staticVerifyR() { } @Test - @Ignore // PENDING: #8805 public void staticWithRFirstArgumentIsConverted() { var rOperator = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "R.---"); @@ -251,7 +249,6 @@ public void staticWithZFirstAndRSecondNoConversionHappens() { } @Test - @Ignore // PENDING #8805 public void staticWithRFirstAndZSecondNoConversionHappens() { var zOperator = module.invokeMember(MethodNames.Module.EVAL_EXPRESSION, "Z.---"); diff --git a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/SignatureTest.java b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/SignatureTest.java index 9cf7c20070cc..536c3f470e54 100644 --- a/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/SignatureTest.java +++ b/engine/runtime-integration-tests/src/test/java/org/enso/interpreter/test/SignatureTest.java @@ -398,6 +398,45 @@ public void runtimeCheckOfAscribedLocalMethodSignature() throws Exception { } } + @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 @@ mul self (other : V) = V.Val self.a*other.a 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 = diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DataflowErrorsTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DataflowErrorsTest.scala index 37df233f2b3c..f9a6043b4d3c 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DataflowErrorsTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/DataflowErrorsTest.scala @@ -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 (Test:7:10-35)" + ) + } } } diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala index c2dba122c6dc..b797a756f6f2 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/MethodsTest.scala @@ -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 diff --git a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/SuspendedArgumentsTest.scala b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/SuspendedArgumentsTest.scala index aaef667c24e5..d71acd5b2c34 100644 --- a/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/SuspendedArgumentsTest.scala +++ b/engine/runtime-integration-tests/src/test/scala/org/enso/interpreter/test/semantic/SuspendedArgumentsTest.scala @@ -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 diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java index be1ca6ae8a21..e9714d6c523c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/FlattenVectorNode.java @@ -16,7 +16,7 @@ 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 @@ static FlattenVectorNode build() { 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( diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java index 80a74d9e49e6..d83c6a6975b1 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/InsertBuiltinVectorNode.java @@ -10,7 +10,7 @@ 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) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java index b13185133201..ff05b8a1ab59 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/RemoveAtVectorNode.java @@ -10,7 +10,7 @@ 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) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java index adfb29e73c14..fe6a78558bb0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/immutable/SliceArrayVectorNode.java @@ -5,7 +5,10 @@ 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 static SliceArrayVectorNode build() { 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); } } diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala index 0b58b21c2003..10652b3a6892 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala @@ -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"", + makeSection(moduleScope, arg.defaultValue.get.location()), + s"", false, false ) diff --git a/test/Base_Tests/src/Data/Vector_Spec.enso b/test/Base_Tests/src/Data/Vector_Spec.enso index c3e980df2eee..67eaa9759757 100644 --- a/test/Base_Tests/src/Data/Vector_Spec.enso +++ b/test/Base_Tests/src/Data/Vector_Spec.enso @@ -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 - diff --git a/test/Base_Tests/src/Semantic/Names_Spec.enso b/test/Base_Tests/src/Semantic/Names_Spec.enso index 9268b9988b30..10d2eec652a6 100644 --- a/test/Base_Tests/src/Semantic/Names_Spec.enso +++ b/test/Base_Tests/src/Semantic/Names_Spec.enso @@ -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 diff --git a/test/Base_Tests/src/Semantic/Warnings_Spec.enso b/test/Base_Tests/src/Semantic/Warnings_Spec.enso index 8de8c0e76484..33bbc7748374 100644 --- a/test/Base_Tests/src/Semantic/Warnings_Spec.enso +++ b/test/Base_Tests/src/Semantic/Warnings_Spec.enso @@ -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 diff --git a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso index 3c609b860d8f..4f0cc3b58e5f 100644 --- a/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso +++ b/test/micro-distribution/lib/Standard/Base/0.0.0-dev/src/Data/Array.enso @@ -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