diff --git a/distribution/std-lib/Base/src/Data/Any/Extensions.enso b/distribution/std-lib/Base/src/Data/Any/Extensions.enso index c08d0206ecd7..f5091a8e6146 100644 --- a/distribution/std-lib/Base/src/Data/Any/Extensions.enso +++ b/distribution/std-lib/Base/src/Data/Any/Extensions.enso @@ -19,7 +19,7 @@ Any.== that = if Meta.is_same_object this that then True else Cons (Meta.Error _) (Meta.Error _) -> this_meta.payload == that_meta.payload Cons (Meta.Polyglot o_1) (Meta.Polyglot o_2) -> langs_match = this_meta.language == Meta.Java && that_meta.language == Meta.Java - if langs_match.not then False else o_1.equals [o_2] + if langs_match.not then False else o_1.equals o_2 ## Constructor comparison is covered by the identity equality. Primitive objects should define their own equality. Therefore, there is no more cases to handle in this method. diff --git a/distribution/std-lib/Base/src/Data/Json.enso b/distribution/std-lib/Base/src/Data/Json.enso index 44f6a75c1cb5..3662dea293c9 100644 --- a/distribution/std-lib/Base/src/Data/Json.enso +++ b/distribution/std-lib/Base/src/Data/Json.enso @@ -91,7 +91,7 @@ parse : Text -> Json ! Parse_Error parse json_text = r = Panic.recover (Internal.parse_helper json_text) r.catch <| case _ of - Polyglot_Error err -> Error.throw (Parse_Error (err.getMessage [])) + Polyglot_Error err -> Error.throw (Parse_Error err.getMessage) p -> Panic.throw p ## A failure indicating the inability to marshall a `Json` object into the diff --git a/distribution/std-lib/Base/src/Data/Json/Internal.enso b/distribution/std-lib/Base/src/Data/Json/Internal.enso index f5e109e7bcb5..ce13fdd914a8 100644 --- a/distribution/std-lib/Base/src/Data/Json/Internal.enso +++ b/distribution/std-lib/Base/src/Data/Json/Internal.enso @@ -120,7 +120,7 @@ render_helper builder json = case json of separator = Ref.get r Ref.put r "," val = here.render_helper "" value - acc + separator + (Printer.json_escape [key]) + ":" + val + acc + separator + (Printer.json_escape key) + ":" + val arr = fields.fold_with_key "" render_key_value builder + "{" + arr + "}" Array items -> @@ -133,7 +133,7 @@ render_helper builder json = case json of arr = items.fold "" render_array_element builder + "[" + arr + "]" String value -> - builder + (Printer.json_escape [value]) + builder + (Printer.json_escape value) Number value -> builder + value.to_text Boolean value -> @@ -178,5 +178,5 @@ into_helper fmt json = case fmt of parse_helper : Text -> Json ! Polyglot_Error parse_helper json_text = consumer = here.mk_consumer - Parser.parse [json_text, consumer] + Parser.parse json_text consumer Ref.get consumer.value diff --git a/distribution/std-lib/Base/src/Data/Noise/Generator.enso b/distribution/std-lib/Base/src/Data/Noise/Generator.enso index 1090ee4d0a41..3ec51cfceed6 100644 --- a/distribution/std-lib/Base/src/Data/Noise/Generator.enso +++ b/distribution/std-lib/Base/src/Data/Noise/Generator.enso @@ -36,11 +36,11 @@ type Deterministic_Random ## Step the generator to produce the next value. step : Number -> Interval -> Number step input interval = - max_long = Polyglot.get_member Long "MAX_VALUE" + max_long = Long.MAX_VALUE seed = input.floor % max_long - gen = Random.new [seed].to_array + gen = Random.new seed value_range = (interval.end.n - interval.start.n).abs offset = (interval.start.n) - gen.nextDouble [] - val = gen.nextDouble [] + gen.nextDouble + val = gen.nextDouble (val * value_range) + offset diff --git a/distribution/std-lib/Base/src/Data/Number/Extensions.enso b/distribution/std-lib/Base/src/Data/Number/Extensions.enso index 6b1b49a3c9b3..98a3c47e4ea7 100644 --- a/distribution/std-lib/Base/src/Data/Number/Extensions.enso +++ b/distribution/std-lib/Base/src/Data/Number/Extensions.enso @@ -7,62 +7,62 @@ polyglot java import java.lang.String Selects a value in the -pi/2 through pi/2 range. Number.asin : Decimal -Number.asin = Math.asin [this.to_decimal] +Number.asin = Math.asin this.to_decimal ## Computes the inverse of the cosine function. Selects a value in the -pi/2 through pi/2 range. Number.acos : Decimal -Number.acos = Math.acos [this.to_decimal] +Number.acos = Math.acos this.to_decimal ## Computes the inverse of the tangent function. Selects a value in the -pi/2 through pi/2 range. Number.atan : Decimal -Number.atan = Math.atan [this.to_decimal] +Number.atan = Math.atan this.to_decimal ## Computes the argument (angle) in the conversion from cartesian to polar coordinates. The returned angle is in the -pi through pi range. Number.atan_2 : Number -> Decimal -Number.atan_2 y = Math.atan2 [this.to_decimal, y.to_decimal] +Number.atan_2 y = Math.atan2 this.to_decimal y.to_decimal ## Computes the sine function. Number.sin : Decimal -Number.sin = Math.sin [this.to_decimal] +Number.sin = Math.sin this.to_decimal ## Computes the cosine function. Number.cos : Decimal -Number.cos = Math.cos [this.to_decimal] +Number.cos = Math.cos this.to_decimal ## Computes the tangent function. Number.tan : Decimal -Number.tan = Math.tan [this.to_decimal] +Number.tan = Math.tan this.to_decimal ## Computes the hyperbolic sine function. Number.sinh : Decimal -Number.sinh = Math.sinh [this.to_decimal] +Number.sinh = Math.sinh this.to_decimal ## Computes the hyperbolic cosine function. Number.cosh : Decimal -Number.cosh = Math.cosh [this.to_decimal] +Number.cosh = Math.cosh this.to_decimal ## Computes the hyperbolic tangent function. Number.tanh : Decimal -Number.tanh = Math.tanh [this.to_decimal] +Number.tanh = Math.tanh this.to_decimal ## Computes the exponential function. Number.exp : Decimal -Number.exp = Math.exp [this.to_decimal] +Number.exp = Math.exp this.to_decimal ## Computes the natural logarithm function. Number.ln : Decimal -Number.ln = Math.log [this.to_decimal] +Number.ln = Math.log this.to_decimal ## Computes the square root of `this`. Number.sqrt : Decimal -Number.sqrt = Math.sqrt [this.to_decimal] +Number.sqrt = Math.sqrt this.to_decimal ## Computes the `base`-log of `this`. Number.log : Number -> Decimal @@ -72,7 +72,7 @@ Number.log base = this.ln / base.ln ## Converts a decimal value to a string, using the Java string formatting syntax. Decimal.format : Text -> Text -Decimal.format fmt = String.format [fmt, this] +Decimal.format fmt = String.format fmt this ## Creates a new right-exclusive range of integers from `this` to `n`. Integer.up_to : Integer -> Range @@ -100,5 +100,5 @@ Number.to_json = Json.Number this Returns `Nothing` if the text does not represent a valid decimal. Decimal.parse : Text -> Decimal | Nothing Decimal.parse text = - Panic.recover (Double.parseDouble [text]) . catch (_ -> Nothing) + Panic.recover (Double.parseDouble text) . catch (_ -> Nothing) diff --git a/distribution/std-lib/Base/src/Data/Text/Extensions.enso b/distribution/std-lib/Base/src/Data/Text/Extensions.enso index 605c95e3b38e..928ce50802c9 100644 --- a/distribution/std-lib/Base/src/Data/Text/Extensions.enso +++ b/distribution/std-lib/Base/src/Data/Text/Extensions.enso @@ -18,13 +18,13 @@ polyglot java import org.enso.base.Text_Utils text-processing applications. Text.length : Integer Text.length = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] - nxt = iterator.next [] + iterator = BreakIterator.getCharacterInstance + iterator.setText this + nxt = iterator.next count accum iter = if iter == -1 then accum else counter = accum + 1 - next_nxt = iterator.next [] + next_nxt = iterator.next @Tail_Call count counter next_nxt count 0 nxt @@ -37,15 +37,15 @@ Text.length = text-processing applications. Text.each : (Text -> Any) -> Nothing Text.each function = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] + iterator = BreakIterator.getCharacterInstance + iterator.setText this - fst = iterator.first [] - nxt = iterator.next [] + fst = iterator.first + nxt = iterator.next iterate prev nxt = if nxt == -1 then Nothing else - function (Text_Utils.substring [this, prev, nxt]) - next_nxt = iterator.next [] + function (Text_Utils.substring this prev nxt) + next_nxt = iterator.next @Tail_Call iterate nxt next_nxt iterate fst nxt Nothing @@ -75,10 +75,10 @@ Text.characters = Text.split : Split_Kind -> Vector.Vector Text.split (separator = Split_Kind.Whitespace) = result = case separator of - Split_Kind.Whitespace -> Text_Utils.split_on_whitespace [this] - Split_Kind.Lines -> Text_Utils.split_on_lines [this] + Split_Kind.Whitespace -> Text_Utils.split_on_whitespace this + Split_Kind.Lines -> Text_Utils.split_on_lines this Split_Kind.Words -> this.words - Text -> Text_Utils.split_by_literal [this, separator] + Text -> Text_Utils.split_by_literal this separator Vector.from_polyglot_array result ## Returns a vector containing all words in the given text. @@ -95,20 +95,20 @@ Text.split (separator = Split_Kind.Whitespace) = "I have not one, but two cats.".words Text.words : Boolean -> Vector.Vector Text.words keep_whitespace=False = - iterator = BreakIterator.getWordInstance [] - iterator.setText [this] + iterator = BreakIterator.getWordInstance + iterator.setText this bldr = Vector.new_builder - fst = iterator.first [] - nxt = iterator.next [] + fst = iterator.first + nxt = iterator.next build prev nxt = if nxt == -1 then Nothing else - word = Text_Utils.substring [this, prev, nxt] - word_not_whitespace = (Text_Utils.is_whitespace [word]).not + word = Text_Utils.substring this prev nxt + word_not_whitespace = (Text_Utils.is_whitespace word).not if word_not_whitespace then bldr.append word else if keep_whitespace then bldr.append word - next_nxt = iterator.next [] + next_nxt = iterator.next @Tail_Call build nxt next_nxt build fst nxt @@ -129,7 +129,7 @@ Text.words keep_whitespace=False = ('é' == 'e\u0301') == True Text.== : Any -> Boolean Text.== that = if Meta.is_same_object this Text then Meta.is_same_object that Text else - Text_Utils.equals [this, that] + Text_Utils.equals this that ## Checks whether `this` is equal to `that`, ignoring case considerations. @@ -151,7 +151,7 @@ Text.== that = if Meta.is_same_object this Text then Meta.is_same_object that Te (('É' . equals_ignore_case 'é') && ('é' == 'e\u0301')) == True Text.equals_ignore_case : Text -> Boolean -Text.equals_ignore_case that = Text_Utils.equals_ignore_case [this, that] +Text.equals_ignore_case that = Text_Utils.equals_ignore_case this that ## Compare two texts to discover their ordering. @@ -160,7 +160,7 @@ Text.equals_ignore_case that = Text_Utils.equals_ignore_case [this, that] "a".compare_to "b" Text.compare_to : Text -> Ordering Text.compare_to that = if this == that then Ordering.Equal else - if Text_Utils.lt [this, that] then Ordering.Less else Ordering.Greater + if Text_Utils.lt this that then Ordering.Less else Ordering.Greater ## Check if `this` is empty. Text.is_empty : Boolean @@ -176,7 +176,7 @@ Text.not_empty = this.is_empty.not This is useful for low-level operations, such as binary data encoding and decoding. Text.utf_8 : Vector.Vector -Text.utf_8 = Vector.from_polyglot_array (Text_Utils.get_bytes [this]) +Text.utf_8 = Vector.from_polyglot_array (Text_Utils.get_bytes this) ## Takes an array of bytes and returns Text resulting from decoding it as UTF-8. @@ -184,7 +184,7 @@ Text.utf_8 = Vector.from_polyglot_array (Text_Utils.get_bytes [this]) This is useful for low-level operations, such as binary data encoding and decoding. Text.from_utf_8 : Vector.Vector -> Text -Text.from_utf_8 bytes = Text_Utils.from_utf_8 [bytes.to_array] +Text.from_utf_8 bytes = Text_Utils.from_utf_8 bytes.to_array ## Returns a vector containing integers representing the Unicode codepoints of the input text. @@ -193,7 +193,7 @@ Text.from_utf_8 bytes = Text_Utils.from_utf_8 [bytes.to_array] decoding. Text.codepoints : Vector.Vector Text.codepoints = - Vector.from_polyglot_array (Text_Utils.get_codepoints [this]) + Vector.from_polyglot_array (Text_Utils.get_codepoints this) ## Takes an array of numbers and returns the text resulting from interpreting it as a sequence of Unicode codepoints. @@ -201,19 +201,19 @@ Text.codepoints = This is useful for low-level operations, such as binary data encoding and decoding. Text.from_codepoints : Vector.Vector -> Text -Text.from_codepoints codepoints = Text_Utils.from_codepoints [codepoints.to_array] +Text.from_codepoints codepoints = Text_Utils.from_codepoints codepoints.to_array ## Checks whether `this` starts with `prefix`. Text.starts_with : Text -> Boolean -Text.starts_with prefix = Text_Utils.starts_with [this, prefix] +Text.starts_with prefix = Text_Utils.starts_with this prefix ## Checks whether `this` ends with `suffix`. Text.ends_with : Text -> Boolean -Text.ends_with suffix = Text_Utils.ends_with [this, suffix] +Text.ends_with suffix = Text_Utils.ends_with this suffix ## Checks whether `this` contains `sequence` as its substring. Text.contains : Text -> Boolean -Text.contains sequence = Text_Utils.contains [this, sequence] +Text.contains sequence = Text_Utils.contains this sequence ## Text to JSON conversion. Text.to_json : Json.String @@ -230,41 +230,41 @@ Text.repeat count = is returned. Text.drop_first : Integer -> Text Text.drop_first count = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] - iterator.first [] - boundary = iterator.next [count] - if boundary == -1 then '' else Text_Utils.drop_first [this, boundary] + iterator = BreakIterator.getCharacterInstance + iterator.setText this + iterator.first + boundary = iterator.next count + if boundary == -1 then '' else Text_Utils.drop_first this boundary ## Creates a new text by removing the last `count` characters of `this`. If `count` is greater than the number of characters in `this`, an empty text is returned. Text.drop_last : Integer -> Text Text.drop_last count = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] - iterator.last [] - boundary = iterator.next [-count] - if boundary == -1 then '' else Text_Utils.substring [this, 0, boundary] + iterator = BreakIterator.getCharacterInstance + iterator.setText this + iterator.last + boundary = iterator.next -count + if boundary == -1 then '' else Text_Utils.substring this 0 boundary ## Creates a new text by selecting the first `count` characters of `this`. If `count` is greater than the number of characters in `this`, the whole `this` is returned. Text.take_first : Integer -> Text Text.take_first count = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] - iterator.first [] - boundary = iterator.next [count] - if boundary == -1 then this else Text_Utils.substring [this, 0, boundary] + iterator = BreakIterator.getCharacterInstance + iterator.setText this + iterator.first + boundary = iterator.next count + if boundary == -1 then this else Text_Utils.substring this 0 boundary ## Creates a new text by selecting the last `count` characters of `this`. If `count` is greater than the number of characters in `this`, the whole `this` is returned. Text.take_last : Integer -> Text Text.take_last count = - iterator = BreakIterator.getCharacterInstance [] - iterator.setText [this] - iterator.last [] - boundary = iterator.next [-count] - if boundary == -1 then this else Text_Utils.drop_first [this, boundary] + iterator = BreakIterator.getCharacterInstance + iterator.setText this + iterator.last + boundary = iterator.next -count + if boundary == -1 then this else Text_Utils.drop_first this boundary diff --git a/distribution/std-lib/Base/src/Data/Time/Date.enso b/distribution/std-lib/Base/src/Data/Time/Date.enso index b476777accee..a440cdabd477 100644 --- a/distribution/std-lib/Base/src/Data/Time/Date.enso +++ b/distribution/std-lib/Base/src/Data/Time/Date.enso @@ -22,15 +22,15 @@ type Date ## Get the year field. year : Integer - year = this . internal_local_date . getYear [] + year = this . internal_local_date . getYear ## Get the month of year field, as a number from 1 to 12. month : Integer - month = this . internal_local_date . getMonthValue [] + month = this . internal_local_date . getMonthValue ## Get the day of month field. day : Integer - day = this . internal_local_date . getDayOfMonth [] + day = this . internal_local_date . getDayOfMonth ## Combine this date with time of day to create a point in time. @@ -38,7 +38,7 @@ type Date Convert this date to midnight UTC time. Day.new 2020 2 3 . to_time Time_Of_Day.new Zone.utc to_time : Time_Of_Day -> Zone -> Time - to_time daytime (zone = Zone.system) = Time.time (this . internal_local_date . atTime [daytime.internal_local_time] . atZone [zone.internal_zone_id]) + to_time daytime (zone = Zone.system) = Time.time (this . internal_local_date . atTime daytime.internal_local_time . atZone zone.internal_zone_id) ## Add specified amount of time to this instant. @@ -46,7 +46,7 @@ type Date Add 6 months to a local date. Date.new 2020 + 6.months + : Duration -> Date - + amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . plus [amount.internal_period]) + + amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . plus amount.internal_period) ## Subtract specified amount of time to this instant. @@ -54,11 +54,11 @@ type Date Subtract 7 days from a local date. Date.new 2020 - 7.days - : Duration -> Date - - amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . minus [amount.internal_period]) + - amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else Date (this . internal_local_date . minus amount.internal_period) ## Format this date using the default formatter. to_text : Text - to_text = Time_Utils.default_date_formatter [] . format [this.internal_local_date] + to_text = Time_Utils.default_date_formatter . format this.internal_local_date ## A Date to Json conversion. to_json : Json.Object @@ -92,7 +92,7 @@ type Date Format "2020-06-02" as "2020AD" Date.new 2020 6 2 . format "yyyyGG" format : Text -> Text - format pattern = DateTimeFormatter.ofPattern [pattern] . format [this.internal_local_date] + format pattern = DateTimeFormatter.ofPattern pattern . format this.internal_local_date ## Obtains an instance of `Date` from a text, such as "2007-12-03". @@ -119,8 +119,8 @@ type Date Time.Error _ -> Date.new 2000 1 1 parse : Text -> Date parse text = - Panic.recover (Date (LocalDate.parse [text])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + Panic.recover (Date (LocalDate.parse text)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x ## Obtains an instance of `Date` from a text using custom format. @@ -139,14 +139,14 @@ parse text = Time.Error msg -> Date.new 2000 1 1 parse_format : Text -> Text -> Date parse_format text pattern = - format = DateTimeFormatter.ofPattern [pattern] - Panic.recover (Date (LocalDate.parse [text, format])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + format = DateTimeFormatter.ofPattern pattern + Panic.recover (Date (LocalDate.parse text format)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x ## Obtains the current date from the system clock in the system timezone. now : Date -now = Date (LocalDate.now []) +now = Date LocalDate.now ## Alias for `now`. today : Date @@ -167,6 +167,6 @@ today = here.now Date.new 1986 8 5 new : Integer -> Integer -> Integer -> Date new year (month = 1) (day = 1) = - Panic.recover (Date (LocalDate.of [year, month, day])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + Panic.recover (Date (LocalDate.of year month day)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x diff --git a/distribution/std-lib/Base/src/Data/Time/Duration.enso b/distribution/std-lib/Base/src/Data/Time/Duration.enso index 916029840946..e2e2447ed06c 100644 --- a/distribution/std-lib/Base/src/Data/Time/Duration.enso +++ b/distribution/std-lib/Base/src/Data/Time/Duration.enso @@ -20,7 +20,7 @@ type Duration Add 12 hours to a duration of a month. 1.month + 12.hours + : Duration -> Duration - + other = Duration (this.internal_period . plus [other.internal_period] . normalized []) (this.internal_duration . plus [other.internal_duration]) + + other = Duration (this.internal_period . plus other.internal_period . normalized) (this.internal_duration . plus other.internal_duration) ## Subtract specified amount of time from this duration. > Example @@ -31,39 +31,39 @@ type Duration Substract 30 minutes from a duration of 7 months. 7.months - 30.minutes - : Duration -> Duration - - other = Duration (this.internal_period . minus [other.internal_period] . normalized []) (this.internal_duration . minus [other.internal_duration]) + - other = Duration (this.internal_period . minus other.internal_period . normalized) (this.internal_duration . minus other.internal_duration) ## Get the amount of nanoseconds of this duration. nanoseconds : Integer - nanoseconds = this.internal_duration . toNanosPart [] + nanoseconds = this.internal_duration . toNanosPart ## Get the amount of milliseconds of this duration. milliseconds : Integer - milliseconds = this.internal_duration . toMillisPart [] + milliseconds = this.internal_duration . toMillisPart ## Get the amount of minutes of this duration. seconds : Integer - seconds = this.internal_duration . toSecondsPart [] + seconds = this.internal_duration . toSecondsPart ## Get the amount of minutes of this duration. minutes : Integer - minutes = this.internal_duration . toMinutesPart [] + minutes = this.internal_duration . toMinutesPart ## Get the amount of hours of this duration. hours : Integer - hours = this.internal_duration . toHours [] + hours = this.internal_duration . toHours ## Get the amount of days of this duration. days : Integer - days = this.internal_period . getDays [] + days = this.internal_period . getDays ## Get the amount of months of this duration. months : Integer - months = this.internal_period . getMonths [] + months = this.internal_period . getMonths ## Get the amount of days of this duration. years : Integer - years = this.internal_period . getYears [] + years = this.internal_period . getYears ## Convert this duration to a Vector of years, months, days, hours, minutes, seconds and nanosecnods. @@ -110,7 +110,7 @@ type Duration ## Duration in nanoseconds. Integer.nanosecond : Duration -Integer.nanosecond = Duration (Java_Period.ofDays [0]) (Java_Duration.ofNanos [this]) +Integer.nanosecond = Duration (Java_Period.ofDays 0) (Java_Duration.ofNanos this) ## Duration in nanoseconds. Integer.nanoseconds : Duration @@ -118,7 +118,7 @@ Integer.nanoseconds = this.nanosecond ## Duration in milliseconds. Integer.millisecond : Duration -Integer.millisecond = Duration (Java_Period.ofDays [0]) (Java_Duration.ofMillis [this]) +Integer.millisecond = Duration (Java_Period.ofDays 0) (Java_Duration.ofMillis this) ## Duration in milliseconds. Integer.milliseconds : Duration @@ -126,7 +126,7 @@ Integer.milliseconds = this.millisecond ## Duration in seconds. Integer.second : Duration -Integer.second = Duration (Java_Period.ofDays [0]) (Java_Duration.ofSeconds [this]) +Integer.second = Duration (Java_Period.ofDays 0) (Java_Duration.ofSeconds this) ## Duration in seconds. Integer.seconds : Duration @@ -134,7 +134,7 @@ Integer.seconds = this.second ## Duration in minutes. Integer.minute : Duration -Integer.minute = Duration (Java_Period.ofDays [0]) (Java_Duration.ofMinutes [this]) +Integer.minute = Duration (Java_Period.ofDays 0) (Java_Duration.ofMinutes this) ## Duration in minutes. Integer.minutes : Duration @@ -142,7 +142,7 @@ Integer.minutes = this.minute ## Duration in hours. Integer.hour : Duration -Integer.hour = Duration (Java_Period.ofDays [0]) (Java_Duration.ofHours [this]) +Integer.hour = Duration (Java_Period.ofDays 0) (Java_Duration.ofHours this) ## Duration in hours. Integer.hours : Duration @@ -150,7 +150,7 @@ Integer.hours = this.hour ## Duration in days. Integer.day : Duration -Integer.day = Duration (Java_Period.ofDays [this] . normalized []) (Java_Duration.ofSeconds [0]) +Integer.day = Duration (Java_Period.ofDays this . normalized) (Java_Duration.ofSeconds 0) ## Duration in days. Integer.days : Duration @@ -158,7 +158,7 @@ Integer.days = this.day ## Duration in months. Integer.month : Duration -Integer.month = Duration (Java_Period.ofMonths [this] . normalized []) (Java_Duration.ofSeconds [0]) +Integer.month = Duration (Java_Period.ofMonths this . normalized) (Java_Duration.ofSeconds 0) ## Duration in months. Integer.months : Duration @@ -166,7 +166,7 @@ Integer.months = this.month ## Duration in years. Integer.year : Duration -Integer.year = Duration (Java_Period.ofYears [this] . normalized []) (Java_Duration.ofSeconds [0]) +Integer.year = Duration (Java_Period.ofYears this . normalized) (Java_Duration.ofSeconds 0) ## Duration in years. Integer.years : Duration @@ -179,4 +179,4 @@ Integer.years = this.year Duration.between Time.now (Time.new 2010 10 20) between : Time -> Time -> Duration between start_inclusive end_exclusive = - Duration (Java_Period.ofDays [0] . normalized []) (Java_Duration.between [start_inclusive.internal_zoned_date_time, end_exclusive.internal_zoned_date_time]) + Duration (Java_Period.ofDays 0 . normalized) (Java_Duration.between start_inclusive.internal_zoned_date_time end_exclusive.internal_zoned_date_time) diff --git a/distribution/std-lib/Base/src/Data/Time/Locale.enso b/distribution/std-lib/Base/src/Data/Time/Locale.enso index 568b3198bc17..0dc63e91085a 100644 --- a/distribution/std-lib/Base/src/Data/Time/Locale.enso +++ b/distribution/std-lib/Base/src/Data/Time/Locale.enso @@ -8,7 +8,7 @@ polyglot java import java.util.Locale as JavaLocale ## The default locale. default : Locale -default = here.from_java (Polyglot.get_member JavaLocale "ROOT") +default = here.from_java JavaLocale.ROOT ## A locale representing Bangladesh. bangladesh : Locale @@ -101,7 +101,7 @@ new : Text -> Text | Nothing -> Text | Nothing -> Locale new language country=Nothing variant=Nothing = country_text = if country.is_nothing then "" else country variant_text = if variant.is_nothing then "" else variant - java_locale = JavaLocale.new [language, country_text, variant_text].to_array + java_locale = JavaLocale.new language country_text variant_text here.from_java java_locale ## Returns the locale specified by the provided IETF BCP47 language tag string. @@ -133,7 +133,7 @@ new language country=Nothing variant=Nothing = Locale.from_language_tag "en_US" from_language_tag : Text -> Locale | Nothing from_language_tag tag = - java_locale = JavaLocale.forLanguageTag [tag] + java_locale = JavaLocale.forLanguageTag tag here.from_java java_locale ## A type representing a locale. @@ -148,45 +148,45 @@ type Locale ## Gets the language from the locale. language : Text | Nothing language = - lang = this.java_locale.getLanguage [] + lang = this.java_locale.getLanguage if lang.is_empty then Nothing else lang ## Gets the country from the locale. country : Text | Nothing country = - place = this.java_locale.getCountry [] + place = this.java_locale.getCountry if place.is_empty then Nothing else place ## Gets the country from the locale. variant : Text | Nothing variant = - var = this.java_locale.getVariant [] + var = this.java_locale.getVariant if var.is_empty then Nothing else var ## Gets a representation of the language in the locale that can be shown to the user. display_language : Text | Nothing display_language = - disp = this.java_locale.getDisplayLanguage [] + disp = this.java_locale.getDisplayLanguage if disp.is_empty then Nothing else disp ## Gets a representation of the country in the locale that can be shown to the user. display_country : Text | Nothing display_country = - disp = this.java_locale.getDisplayCountry [] + disp = this.java_locale.getDisplayCountry if disp.is_empty then Nothing else disp ## Gets a representation of the variant in the locale that can be shown to the user. display_variant : Text | Nothing display_variant = - disp = this.java_locale.getDisplayVariant [] + disp = this.java_locale.getDisplayVariant if disp.is_empty then Nothing else disp ## Converts the locale to text. to_text : Text | Nothing - to_text = this.java_locale.toLanguageTag [] + to_text = this.java_locale.toLanguageTag ## A Locale to Json conversion to_json : Json.Object @@ -203,4 +203,4 @@ from_java : JavaLocale -> Locale from_java java = Locale java ## PRIVATE -javaLocaleBuilder = Polyglot.get_member JavaLocale "Builder" +javaLocaleBuilder = JavaLocale.Builder diff --git a/distribution/std-lib/Base/src/Data/Time/Time.enso b/distribution/std-lib/Base/src/Data/Time/Time.enso index 8daa3347c90a..8d033e03a4d5 100644 --- a/distribution/std-lib/Base/src/Data/Time/Time.enso +++ b/distribution/std-lib/Base/src/Data/Time/Time.enso @@ -30,51 +30,51 @@ type Time ## Get the year field. year : Integer - year = this . internal_zoned_date_time . getYear [] + year = this . internal_zoned_date_time . getYear ## Get the month of year field from 1 to 12. month : Integer - month = this . internal_zoned_date_time . getMonthValue [] + month = this . internal_zoned_date_time . getMonthValue ## Get the day of month field. day : Integer - day = this . internal_zoned_date_time . getDayOfMonth [] + day = this . internal_zoned_date_time . getDayOfMonth ## Get the hour of day field. hour : Integer - hour = this . internal_zoned_date_time . getHour [] + hour = this . internal_zoned_date_time . getHour ## Get the minute of hour field. minute : Integer - minute = this . internal_zoned_date_time . getMinute [] + minute = this . internal_zoned_date_time . getMinute ## Get the second of minute field second : Integer - second = this . internal_zoned_date_time . getSecond [] + second = this . internal_zoned_date_time . getSecond ## Get the nano-of-second field. nanosecond : Integer - nanosecond = this . internal_zoned_date_time . getNano [] + nanosecond = this . internal_zoned_date_time . getNano ## Get the timezone. zone : Zone - zone = Zone.zone (this . internal_zoned_date_time . getZone []) + zone = Zone.zone (this . internal_zoned_date_time . getZone) ## Return the number of seconds from the Unix epoch. to_epoch_seconds : Integer - to_epoch_seconds = this . internal_zoned_date_time . toEpochSecond [] + to_epoch_seconds = this . internal_zoned_date_time . toEpochSecond ## Return the number of milliseconds from the Unix epoch. to_epoch_milliseconds : Integer - to_epoch_milliseconds = this . internal_zoned_date_time . toInstant [] . toEpochMilli [] + to_epoch_milliseconds = this . internal_zoned_date_time . toInstant . toEpochMilli ## Convert this point in time to time of day. time_of_day : Time_Of_Day - time_of_day = Time_Of_Day.time_of_day (this . internal_zoned_date_time . toLocalTime []) + time_of_day = Time_Of_Day.time_of_day this.internal_zoned_date_time.toLocalTime ## Convert this point in time to date. date : Date - date = Date.date (this . internal_zoned_date_time . toLocalDate []) + date = Date.date this.internal_zoned_date_time.toLocalDate ## Convert the time instant to a provided timezone. @@ -82,7 +82,7 @@ type Time Convert time instance to -04:00 timezone. Time.new 2020 . at_zone (Zone.new -4) at_zone : Zone -> Time - at_zone zone = Time (this.internal_zoned_date_time . withZoneSameInstant [zone.internal_zone_id]) + at_zone zone = Time (this.internal_zoned_date_time . withZoneSameInstant zone.internal_zone_id) ## Add specified amount of time to this instant. @@ -94,7 +94,7 @@ type Time Add 15 years and 3 hours to a zoned date time. Time.new 2020 + 15.years + 3.hours + : Duration -> Time - + amount = Time (this . internal_zoned_date_time . plus [amount.internal_period] . plus [amount.internal_duration]) + + amount = Time (this . internal_zoned_date_time . plus amount.internal_period . plus amount.internal_duration) ## Subtract specified amount of time to this instant. @@ -106,11 +106,11 @@ type Time Subtract 1 year and 9 months from a zoned date time. Time.new 2020 - 1.year - 9.months - : Duration -> Time - - amount = Time (this . internal_zoned_date_time . minus [amount.internal_period] . minus [amount.internal_duration]) + - amount = Time (this . internal_zoned_date_time . minus amount.internal_period . minus amount.internal_duration) ## Format this time using the default formatter. to_text : Text - to_text = Time_Utils.default_time_formatter [] . format [this.internal_zoned_date_time] + to_text = Time_Utils.default_time_formatter . format this.internal_zoned_date_time ## A Time to Json conversion. to_json : Json.Object @@ -175,7 +175,7 @@ type Time Format "2020-10-08T16:41:13+03:00[Europe/Moscow]" as "Thu Oct 8 (16:41)" Time.parse "2020-10-08T16:41:13+03:00[Europe/Moscow]" . format "EEE MMM d (HH:mm)" format : Text -> Text - format pattern = DateTimeFormatter.ofPattern [pattern] . format [this.internal_zoned_date_time] + format pattern = DateTimeFormatter.ofPattern pattern . format this.internal_zoned_date_time ## Obtains an instance of `Time` from a text such as "2007-12-03T10:15:30+01:00 Europe/Paris". @@ -214,8 +214,8 @@ type Time Time.Error _ -> Time.now parse : Text -> Time parse text = - Panic.recover (Time (Time_Utils.parse_time [text])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time_Error (err.getMessage [])) + Panic.recover (Time (Time_Utils.parse_time text)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time_Error err.getMessage) x -> x ## Obtains an instance of Time from a text using custom format. @@ -231,13 +231,13 @@ parse text = Date.parse_format "06 of May 2020 at 04:30AM" "dd 'of' MMMM yyyy 'at' hh:mma" parse_format : Text -> Text -> Locale -> Time_Of_Day parse_format text pattern locale=Locale.default = - Panic.recover (Time (Time_Utils.parse_time_format [text, pattern, locale.java_locale])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time_Error (err.getMessage [])) + Panic.recover (Time (Time_Utils.parse_time_format text pattern locale.java_locale)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time_Error err.getMessage) x -> x ## Obtains the current date-time from the system clock in the system timezone. now : Time -now = Time (ZonedDateTime.now []) +now = Time ZonedDateTime.now ## Obtains an instance of `Time` from a year, month, day, hour, minute, second, nanosecond and timezone. @@ -260,6 +260,6 @@ now = Time (ZonedDateTime.now []) Time.new 1986 8 5 new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Zone -> Time new year (month = 1) (day = 1) (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) (zone = Zone.system) = - Panic.recover (Time (ZonedDateTime.of [year, month, day, hour, minute, second, nanosecond, zone.internal_zone_id])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time_Error (err.getMessage [])) + Panic.recover (Time (ZonedDateTime.of year month day hour minute second nanosecond zone.internal_zone_id)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time_Error err.getMessage) x -> x diff --git a/distribution/std-lib/Base/src/Data/Time/Time_Of_Day.enso b/distribution/std-lib/Base/src/Data/Time/Time_Of_Day.enso index 0303b7189dbb..47ad911ca363 100644 --- a/distribution/std-lib/Base/src/Data/Time/Time_Of_Day.enso +++ b/distribution/std-lib/Base/src/Data/Time/Time_Of_Day.enso @@ -19,23 +19,23 @@ type Time_Of_Day ## Get the hour of day field. hour : Integer - hour = this . internal_local_time . getHour [] + hour = this . internal_local_time . getHour ## Get the minute of hour field. minute : Integer - minute = this . internal_local_time . getMinute [] + minute = this . internal_local_time . getMinute ## Get the second of minute field. second : Integer - second = this . internal_local_time . getSecond [] + second = this . internal_local_time . getSecond ## Get the nanosecond of second field. nanosecond : Integer - nanosecond = this . internal_local_time . getNano [] + nanosecond = this . internal_local_time . getNano ## Extracts the time as the number of seconds, from 0 to 24 * 60 * 60 - 1. to_seconds : Integer - to_seconds = this . internal_local_time . toSecondOfDay [] + to_seconds = this . internal_local_time . toSecondOfDay ## Combine this time of day with a date to create a point in time. @@ -43,7 +43,7 @@ type Time_Of_Day Convert local time to 1st January 2020 12:30 at system timezone. Time_Of_Day.new 12 30 . to_time (Date.new 2020) to_time : Date -> Zone -> Time - to_time date (zone = Zone.system) = Time.time (this . internal_local_time . atDate [date.internal_local_date] . atZone [zone.internal_zone_id]) + to_time date (zone = Zone.system) = Time.time (this . internal_local_time . atDate date.internal_local_date . atZone zone.internal_zone_id) ## Add specified amount of time to this instant. @@ -51,7 +51,7 @@ type Time_Of_Day Add 3 seconds to a local time. Time_Of_Day.new + 3.seconds + : Duration -> Time_Of_Day - + amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . plus [amount.internal_duration]) + + amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . plus amount.internal_duration) ## Subtract specified amount of time to this instant. @@ -59,11 +59,11 @@ type Time_Of_Day Subtract 12 hours from a local time. Time_Of_Day.new - 12.hours - : Duration -> Time_Of_Day - - amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . minus [amount.internal_duration]) + - amount = if amount.is_date then Error.throw (Time.Time_Error "Time_Of_Day does not support date intervals") else Time_Of_Day (this . internal_local_time . minus amount.internal_duration) ## Format this time of day using the default formatter. to_text : Text - to_text = Time_Utils.default_time_of_day_formatter [] . format [this.internal_local_time] + to_text = Time_Utils.default_time_of_day_formatter . format this.internal_local_time ## A Time_Of_Day to Json conversion. to_json : Json.Object @@ -97,7 +97,7 @@ type Time_Of_Day Format "16:21:10" as "hour:4" Time_Of_Day.new 16 21 10 . format "'hour:'h" format : Text -> Text - format pattern = DateTimeFormatter.ofPattern [pattern] . format [this.internal_local_time] + format pattern = DateTimeFormatter.ofPattern pattern . format this.internal_local_time ## Obtains an instance of `Time_Of_Day` from a text such as "10:15". @@ -128,8 +128,8 @@ type Time_Of_Day Time.Error _ -> Time_Of_Day.new parse : Text -> Time_Of_Day parse text = - Panic.recover (Time_Of_Day (LocalTime.parse [text])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + Panic.recover (Time_Of_Day (LocalTime.parse text)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x ## Obtains an instance of Time_Of_Day from a text using custom format. @@ -146,14 +146,14 @@ parse text = Date.parse_format "4:30AM" "h:mma" parse_format : Text -> Text -> Locale -> Time_Of_Day parse_format text pattern locale=Locale.default = - format = (DateTimeFormatter.ofPattern [pattern]).withLocale [locale.java_locale] - Panic.recover (Time_Of_Day (LocalTime.parse [text, format])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + format = (DateTimeFormatter.ofPattern pattern).withLocale locale.java_locale + Panic.recover (Time_Of_Day (LocalTime.parse text format)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x ## Obtains the current time from the system clock in the default time-zone. now : Time_Of_Day -now = Time_Of_Day (LocalTime.now []) +now = Time_Of_Day LocalTime.now ## Obtains an instance of `Time_Of_Day` from an hour, minute, second and nanosecond. @@ -172,6 +172,6 @@ now = Time_Of_Day (LocalTime.now []) Time_Of_Day.new 9 30 new : Integer -> Integer -> Integer -> Integer -> Time_Of_Day new (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) = - Panic.recover (Time_Of_Day (LocalTime.of [hour, minute, second, nanosecond])) . catch <| case _ of - Polyglot_Error err -> Error.throw (Time.Time_Error (err.getMessage [])) + Panic.recover (Time_Of_Day (LocalTime.of hour minute second nanosecond)) . catch <| case _ of + Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage) x -> x diff --git a/distribution/std-lib/Base/src/Data/Time/Zone.enso b/distribution/std-lib/Base/src/Data/Time/Zone.enso index 6bf0877bbade..b62e14acc98d 100644 --- a/distribution/std-lib/Base/src/Data/Time/Zone.enso +++ b/distribution/std-lib/Base/src/Data/Time/Zone.enso @@ -13,7 +13,7 @@ type Zone ## Get the unique timezone ID. zone_id : Text - zone_id = this.internal_zone_id . getId [] + zone_id = this.internal_zone_id . getId ## A Zone to Json conversion to_json : Json.Object @@ -37,11 +37,11 @@ type Zone Get custom offset +03:02:01 of 3 hours 2 minutes an 1 second. Zone.parse "+03:02:01" parse : Text -> Zone -parse text = Zone (ZoneId.of [text]) +parse text = Zone (ZoneId.of text) ## The system default timezone. system : Zone -system = Zone (ZoneId.systemDefault []) +system = Zone ZoneId.systemDefault ## The system default timezone. local : Zone @@ -64,4 +64,4 @@ utc = here.parse "UTC" Zone.new 1 1 50 new : Integer -> Integer -> Integer -> Zone new (hours = 0) (minutes = 0) (seconds = 0) = - Zone (ZoneOffset.ofHoursMinutesSeconds [hours, minutes, seconds] . normalized []) + Zone (ZoneOffset.ofHoursMinutesSeconds hours minutes seconds . normalized) diff --git a/distribution/std-lib/Base/src/Data/Vector.enso b/distribution/std-lib/Base/src/Data/Vector.enso index aa6aacaefc33..6c065afa3225 100644 --- a/distribution/std-lib/Base/src/Data/Vector.enso +++ b/distribution/std-lib/Base/src/Data/Vector.enso @@ -61,7 +61,7 @@ new_builder = Builder.new ## Converts a polyglot value representing an array into a vector. This is useful when wrapping polyglot APIs for further use in Enso. from_polyglot_array : Any -> Vector.Vector -from_polyglot_array arr = here.new arr.length arr.at +from_polyglot_array arr = here.new arr.length (arr.at _) ## The basic, immutable, vector type. diff --git a/distribution/std-lib/Base/src/Network/Http.enso b/distribution/std-lib/Base/src/Network/Http.enso index f578a434fa58..ec54cd5e61b2 100644 --- a/distribution/std-lib/Base/src/Network/Http.enso +++ b/distribution/std-lib/Base/src/Network/Http.enso @@ -186,34 +186,34 @@ type Http http.request req request : Request -> Response request req = - body_publishers = Polyglot.get_member HttpRequest "BodyPublishers" - builder = HttpRequest.newBuilder [] + body_publishers = HttpRequest.BodyPublishers + builder = HttpRequest.newBuilder # set uri - builder.uri [req.uri.internal_uri] + builder.uri req.uri.internal_uri # prepare headers and body req_with_body = case req.body of Request_Body.Empty -> - Pair req (body_publishers.noBody []) + Pair req body_publishers.noBody Request_Body.Text text -> - builder.header [Header.text_plain.name, Header.text_plain.value] - Pair req (body_publishers.ofString [text]) + builder.header Header.text_plain.name Header.text_plain.value + Pair req (body_publishers.ofString text) Request_Body.Json json -> - builder.header [Header.application_json.name, Header.application_json.value] - Pair req (body_publishers.ofString [json.to_text]) + builder.header Header.application_json.name Header.application_json.value + Pair req (body_publishers.ofString json.to_text) Request_Body.Form form -> add_multipart form = - body_builder = Http_Utils.multipart_body_builder [] + body_builder = Http_Utils.multipart_body_builder form.parts.map part-> case part.value of - Form.Part_Text text -> body_builder.add_part_text [part.key, text] - Form.Part_File file -> body_builder.add_part_file [part.key, file.path] - boundary = body_builder.get_boundary [] - Pair (req.with_headers [Header.multipart_form_data boundary]) (body_builder.build []) + Form.Part_Text text -> body_builder.add_part_text part.key text + Form.Part_File file -> body_builder.add_part_file part.key file.path + boundary = body_builder.get_boundary + Pair (req.with_headers [Header.multipart_form_data boundary]) body_builder.build add_urlencoded form = - body_builder = Http_Utils.urlencoded_body_builder [] + body_builder = Http_Utils.urlencoded_body_builder form.parts.map part-> case part.value of - Form.Part_Text text -> body_builder.add_part_text [part.key, text] - Form.Part_File file -> body_builder.add_part_file [part.key, file.path] - Pair req (body_builder.build []) + Form.Part_Text text -> body_builder.add_part_text part.key text + Form.Part_File file -> body_builder.add_part_file part.key file.path + Pair req body_builder.build if req.headers.contains Header.multipart_form_data then add_multipart form else add_urlencoded form # method @@ -228,46 +228,46 @@ type Http case req_with_body of Pair req body -> # set method and body - builder.method [req_http_method, body] + builder.method req_http_method body # set headers - req.headers.map h-> builder.header [h.name, h.value] - http_request = builder.build [] - body_handler = Polyglot.get_member HttpResponse "BodyHandlers" . ofByteArray [] - Response.response (this.internal_http_client.send [http_request, body_handler]) + req.headers.map h-> builder.header h.name h.value + http_request = builder.build + body_handler = HttpResponse.BodyHandlers . ofByteArray + Response.response (this.internal_http_client.send http_request body_handler) ## PRIVATE Build an HTTP client. internal_http_client : HttpClient internal_http_client = - builder = HttpClient.newBuilder [] + builder = HttpClient.newBuilder # timeout - if this.timeout.is_date then Panic.throw (Time.time_error "Connection timeout does not support date intervals") else builder.connectTimeout [this.timeout.internal_duration] + if this.timeout.is_date then Panic.throw (Time.time_error "Connection timeout does not support date intervals") else + builder.connectTimeout this.timeout.internal_duration # redirect - redirect = Polyglot.get_member HttpClient "Redirect" + redirect = HttpClient.Redirect redirect_policy = case this.follow_redirects of - True -> Polyglot.get_member redirect "ALWAYS" - False -> Polyglot.get_member redirect "NEVER" - builder.followRedirects [redirect_policy] + True -> redirect.ALWAYS + False -> redirect.NEVER + builder.followRedirects redirect_policy # proxy case this.proxy of Proxy.Proxy_Addr proxy_host proxy_port -> - proxy_selector = ProxySelector.of [InetSocketAddress.new [proxy_host, proxy_port].to_array] - Polyglot.invoke builder "proxy" [proxy_selector].to_array + proxy_selector = ProxySelector.of (InetSocketAddress.new proxy_host proxy_port) + builder.proxy proxy_selector Proxy.System -> - proxy_selector = ProxySelector.getDefault [] - Polyglot.invoke builder "proxy" [proxy_selector].to_array + proxy_selector = ProxySelector.getDefault + builder.proxy proxy_selector Proxy.None -> Nothing # version - http_client_version = Polyglot.get_member HttpClient "Version" case this.version of Version.Http_1_1 -> - Polyglot.invoke builder "version" [http_client_version.valueOf ["HTTP_1_1"]].to_array + builder.version HttpClient.Version.HTTP_1_1 Version.Http_2 -> - Polyglot.invoke builder "version" [http_client_version.valueOf ["HTTP_2"]].to_array + builder.version HttpClient.Version.HTTP_2 # build http client - builder.build [] + builder.build ## Create a new instance of HTTP client. diff --git a/distribution/std-lib/Base/src/Network/Http/Header.enso b/distribution/std-lib/Base/src/Network/Http/Header.enso index 5d448380d35e..6b80d7a04b84 100644 --- a/distribution/std-lib/Base/src/Network/Http/Header.enso +++ b/distribution/std-lib/Base/src/Network/Http/Header.enso @@ -37,7 +37,7 @@ authorization value = Header "Authorization" value Header.authorization_basic "user" "pass" authorization_basic : Text -> Text -> Header authorization_basic user pass = - here.authorization (Http_Utils.header_basic_auth [user, pass]) + here.authorization (Http_Utils.header_basic_auth user pass) # Content-Type diff --git a/distribution/std-lib/Base/src/Network/Http/Request.enso b/distribution/std-lib/Base/src/Network/Http/Request.enso index 919e2ff5554f..a7f5b861251e 100644 --- a/distribution/std-lib/Base/src/Network/Http/Request.enso +++ b/distribution/std-lib/Base/src/Network/Http/Request.enso @@ -19,7 +19,7 @@ type Request update_header p h = case p of Pair acc True -> Pair (acc + [h]) True Pair acc False -> - if Text_Utils.equals_ignore_case [h.name, key] then Pair (acc + [new_header]) True else Pair (acc + [h]) False + if Text_Utils.equals_ignore_case h.name key then Pair (acc + [new_header]) True else Pair (acc + [h]) False new_headers = case this.headers.fold (Pair [] False) update_header of Pair acc True -> acc Pair acc False -> acc + [new_header] diff --git a/distribution/std-lib/Base/src/Network/Http/Response.enso b/distribution/std-lib/Base/src/Network/Http/Response.enso index 2f41327299b0..1bb14436f0d9 100644 --- a/distribution/std-lib/Base/src/Network/Http/Response.enso +++ b/distribution/std-lib/Base/src/Network/Http/Response.enso @@ -14,16 +14,16 @@ type Response ## Get the response headers. headers : Vector.Vector headers = - header_entries = Vector.vector (Http_Utils.get_headers [this.internal_http_response.headers []]) - header_entries.map e-> Header.new (e.getKey []) (e.getValue []) + header_entries = Vector.vector (Http_Utils.get_headers this.internal_http_response.headers) + header_entries.map e-> Header.new e.getKey e.getValue ## Get the response body. body : Response_Body - body = Response_Body.body (Vector.vector (this.internal_http_response.body [])) + body = Response_Body.body (Vector.vector this.internal_http_response.body) ## Get the response status code. code : Status_Code - code = Status_Code.status_code (this.internal_http_response.statusCode []) + code = Status_Code.status_code this.internal_http_response.statusCode ## A Response to Json conversion. to_json : Json.Object diff --git a/distribution/std-lib/Base/src/Network/Uri.enso b/distribution/std-lib/Base/src/Network/Uri.enso index 5d5a2d7b21ce..54467fd915b8 100644 --- a/distribution/std-lib/Base/src/Network/Uri.enso +++ b/distribution/std-lib/Base/src/Network/Uri.enso @@ -19,6 +19,12 @@ panic_on_error ~action = action . catch <| case _ of Syntax_Error msg -> Panic.throw (Syntax_Error msg) +## PRIVATE +empty_if_null : Text | Nothing -> Text +empty_if_null value = case value of + Nothing -> "" + x -> x + type Uri ## Represents a Uniform Resource Identifier (URI) reference. @@ -35,7 +41,7 @@ type Uri addr = "http://user:pass@example.com/foo/bar?key=val" Uri.parse addr . scheme scheme : Text - scheme = Optional.ofNullable [this.internal_uri.getScheme []] . orElse [""] + scheme = here.empty_if_null this.internal_uri.getScheme ## Get user info part of this Uri. @@ -44,7 +50,7 @@ type Uri addr = "http://user:pass@example.com/foo/bar?key=val" Uri.parse addr . user_info user_info : Text - user_info = Optional.ofNullable [this.internal_uri.getUserInfo []] . orElse [""] + user_info = here.empty_if_null this.internal_uri.getUserInfo ## Get host part of this Uri. @@ -53,7 +59,7 @@ type Uri addr = "http://user:pass@example.com/foo/bar?key=val" Uri.parse addr . host host : Text - host = Optional.ofNullable [this.internal_uri.getHost []] . orElse [""] + host = here.empty_if_null this.internal_uri.getHost ## Get authority (user info and host) part of this Uri. @@ -62,7 +68,7 @@ type Uri addr = "http://user:pass@example.com/foo/bar?key=val" Uri.parse addr . authority authority : Text - authority = Optional.ofNullable [this.internal_uri.getAuthority []] . orElse [""] + authority = here.empty_if_null this.internal_uri.getAuthority ## Get port part of this Uri. @@ -77,7 +83,7 @@ type Uri Uri.parse addr . port port : Text port = - port_number = this.internal_uri.getPort [] + port_number = this.internal_uri.getPort if port_number == -1 then "" else port_number.to_text ## Get path part of this Uri. @@ -87,7 +93,7 @@ type Uri addr = "http://user:pass@example.com:80/foo/bar?key=val" Uri.parse addr . path path : Text - path = Optional.ofNullable [this.internal_uri.getPath []] . orElse [""] + path = here.empty_if_null this.internal_uri.getPath ## Get query part of this Uri. @@ -96,7 +102,7 @@ type Uri addr = "http://user:pass@example.com:80/foo/bar?key=val" Uri.parse addr . query query : Text - query = Optional.ofNullable [this.internal_uri.getQuery []] . orElse [""] + query = here.empty_if_null this.internal_uri.getQuery ## Get fragment part of this Uri. @@ -105,31 +111,31 @@ type Uri addr = "http://user:pass@example.com:80/foo/bar?key=val" Uri.parse addr . fragment fragment : Text - fragment = Optional.ofNullable [this.internal_uri.getFragment []] . orElse [""] + fragment = here.empty_if_null this.internal_uri.getFragment ## Get unescaped user info part of this Uri. raw_user_info : Text - raw_user_info = Optional.ofNullable [this.internal_uri.getRawUserInfo []] . orElse [""] + raw_user_info = here.empty_if_null this.internal_uri.getRawUserInfo ## Get unescaped authority part of this Uri. raw_authority : Text - raw_authority = Optional.ofNullable [this.internal_uri.getRawAuthority []] . orElse [""] + raw_authority = here.empty_if_null this.internal_uri.getRawAuthority ## Get unescaped path part of this Uri. raw_path : Text - raw_path = Optional.ofNullable [this.internal_uri.getRawPath []] . orElse [""] + raw_path = here.empty_if_null this.internal_uri.getRawPath ## Get unescaped query part of this Uri. raw_query : Text - raw_query = Optional.ofNullable [this.internal_uri.getRawQuery []] . orElse [""] + raw_query = here.empty_if_null this.internal_uri.getRawQuery ## Get unescaped fragment part of this Uri. raw_fragment : Text - raw_fragment = Optional.ofNullable [this.internal_uri.getRawFragment []] . orElse [""] + raw_fragment = here.empty_if_null this.internal_uri.getRawFragment ## Convert this Uri to text. to_text : Text - to_text = this.internal_uri.toString [] + to_text = this.internal_uri.toString ## An Uri to JSON conversion. to_json : Json.String @@ -137,7 +143,7 @@ type Uri ## Check Uri equality. == : Uri -> Boolean - == that = this.internal_uri.equals [that.internal_uri] + == that = this.internal_uri.equals that.internal_uri ## Parse Uri from text. Return Syntax_Error when the text cannot be parsed as Uri. @@ -147,6 +153,6 @@ type Uri Uri.parse "http://example.com" parse : Text -> Uri parse text = - Panic.recover (Uri (Java_URI.create [text])) . catch <| case _ of - Polyglot_Error ex -> Error.throw (Syntax_Error (ex.getMessage [])) + Panic.recover (Uri (Java_URI.create text)) . catch <| case _ of + Polyglot_Error ex -> Error.throw (Syntax_Error ex.getMessage) other -> Panic.throw other diff --git a/distribution/std-lib/Base/src/Polyglot/Java.enso b/distribution/std-lib/Base/src/Polyglot/Java.enso index cdf89a42d02e..10b339ec0113 100644 --- a/distribution/std-lib/Base/src/Polyglot/Java.enso +++ b/distribution/std-lib/Base/src/Polyglot/Java.enso @@ -4,5 +4,5 @@ import Builtins ## Checks whether an object is an instance of a given class. Builtins.Java.is_instance : Any -> Any -> Boolean Builtins.Java.is_instance object class = - class_object = Polyglot.get_member class "class" - class_object.isInstance [object] + class_object = class.class + class_object.isInstance object diff --git a/distribution/std-lib/Base/src/System/File.enso b/distribution/std-lib/Base/src/System/File.enso index 7ad9de54610c..501d7cdf92bf 100644 --- a/distribution/std-lib/Base/src/System/File.enso +++ b/distribution/std-lib/Base/src/System/File.enso @@ -24,7 +24,7 @@ rethrow_java file exception = if Java.is_instance exc AccessDeniedException then Panic.throw (Access_Denied_Error file) if Java.is_instance exc IOException then - Panic.throw (Io_Error (exc.getMessage [])) + Panic.throw (Io_Error exc.getMessage) Panic.throw exception _ -> Panic.throw exception @@ -42,7 +42,7 @@ handle_java_exceptions file ~action = accidental scope capture with `Managed_Resource` finalizers. close_stream : Any -> Nothing close_stream stream = - stream.close [] + stream.close Nothing ## An output stream, allowing for interactive writing of contents into an @@ -54,8 +54,8 @@ type Output_Stream write_bytes : Vector.Vector -> Nothing ! File_Error write_bytes contents = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| - java_stream.write [contents.to_array] - java_stream.flush [] + java_stream.write contents.to_array + java_stream.flush Nothing ## Closes this stream. @@ -75,7 +75,7 @@ type Input_Stream read_all_bytes : Vector.Vector ! File_Error read_all_bytes = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| - Vector.from_polyglot_array (java_stream.readAllBytes []) + Vector.from_polyglot_array java_stream.readAllBytes ## Reads _up to_ the provided number of bytes from the stream. @@ -87,7 +87,7 @@ type Input_Stream read_n_bytes : Integer -> Vector.Vector ! File_Error read_n_bytes n = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| - bytes = java_stream.readNBytes [n] + bytes = java_stream.readNBytes n Vector.from_polyglot_array bytes ## Reads the next byte from the stream. @@ -97,7 +97,7 @@ type Input_Stream read_byte : Integer ! File_Error read_byte = Managed_Resource.with this.stream_resource java_stream-> here.handle_java_exceptions this.file <| - java_stream.read [] + java_stream.read ## Closes this stream. @@ -128,7 +128,7 @@ type File new_input_stream open_options = opts = open_options . map (_.to_java) . to_array stream = here.handle_java_exceptions this <| - (this.prim_file.newInputStream [opts]) + (this.prim_file.newInputStream opts) resource = Managed_Resource.register stream here.close_stream Input_Stream this resource @@ -143,7 +143,7 @@ type File new_output_stream open_options = opts = open_options . map (_.to_java) . to_array stream = here.handle_java_exceptions this <| - this.prim_file.newOutputStream [opts] + this.prim_file.newOutputStream opts resource = Managed_Resource.register stream here.close_stream Output_Stream this resource @@ -212,8 +212,8 @@ type File ## Resolve a child file of the given file. / : (Text | File) -> File / subpath = case subpath of - File prim -> File (this.prim_file.resolve [prim]) - _ -> File (this.prim_file.resolve [subpath]) + File prim -> File (this.prim_file.resolve prim) + _ -> File (this.prim_file.resolve subpath) ## A text representation of this file. to_text : Text @@ -225,44 +225,44 @@ type File ## Checks whether the file exists. exists : Boolean - exists = this.prim_file.exists [] + exists = this.prim_file.exists ## Checks whether the file exists and is a directory. is_directory : Boolean - is_directory = this.prim_file.isDirectory [] + is_directory = this.prim_file.isDirectory ## Checks whether the file exists and is a regular file. is_regular_file : Boolean - is_regular_file = this.prim_file.isRegularFile [] + is_regular_file = this.prim_file.isRegularFile ## Resolves the parent filesystem node of this file. parent : File - parent = File (this.prim_file.getParent []) + parent = File this.prim_file.getParent ## Returns the path of this file. path : Text - path = this.prim_file.getPath [] + path = this.prim_file.getPath ## Returns the name of this file. name : Text - name = this.prim_file.getName [] + name = this.prim_file.getName ## Converts this file to an equivalent file represented with an absolute path. absolute : File - absolute = File (this.prim_file.getAbsoluteFile []) + absolute = File this.prim_file.getAbsoluteFile ## Checks is this file's path is absolute. is_absolute : Boolean - is_absolute = this.prim_file.isAbsolute [] + is_absolute = this.prim_file.isAbsolute ## Normalizes the filepath. normalize : File - normalize = File (this.prim_file.normalize []) + normalize = File this.prim_file.normalize ## Checks if this file has the same `path` as `that`. == : File -> Boolean - == that = this.prim_file.isEqual [that.prim_file] + == that = this.prim_file.isEqual that.prim_file ## Deletes the file. @@ -271,7 +271,7 @@ type File delete : Nothing ! File_Error delete = here.handle_java_exceptions this <| - this.prim_file.delete [] + this.prim_file.delete Nothing ## Deletes the file if it exists on disk. diff --git a/distribution/std-lib/Base/src/System/File/Option.enso b/distribution/std-lib/Base/src/System/File/Option.enso index 8abc2d71892b..e962ff5fb4a0 100644 --- a/distribution/std-lib/Base/src/System/File/Option.enso +++ b/distribution/std-lib/Base/src/System/File/Option.enso @@ -37,13 +37,13 @@ type Option Convert this object into a representation understandable by the JVM. to_java = case this of - Append -> Polyglot.get_member StandardOpenOption "APPEND" - Create -> Polyglot.get_member StandardOpenOption "CREATE" - Create_New -> Polyglot.get_member StandardOpenOption "CREATE_NEW" - Delete_On_Close -> Polyglot.get_member StandardOpenOption "DELETE_ON_CLOSE" - Dsync -> Polyglot.get_member StandardOpenOption "DSYNC" - Read -> Polyglot.get_member StandardOpenOption "READ" - Sparse -> Polyglot.get_member StandardOpenOption "SPARSE" - Sync -> Polyglot.get_member StandardOpenOption "SYNC" - Truncate_Existing -> Polyglot.get_member StandardOpenOption "TRUNCATE_EXISTING" - Write -> Polyglot.get_member StandardOpenOption "WRITE" + Append -> StandardOpenOption.APPEND + Create -> StandardOpenOption.CREATE + Create_New -> StandardOpenOption.CREATE_NEW + Delete_On_Close -> StandardOpenOption.DELETE_ON_CLOSE + Dsync -> StandardOpenOption.DSYNC + Read -> StandardOpenOption.READ + Sparse -> StandardOpenOption.SPARSE + Sync -> StandardOpenOption.SYNC + Truncate_Existing -> StandardOpenOption.TRUNCATE_EXISTING + Write -> StandardOpenOption.WRITE diff --git a/distribution/std-lib/Table/src/Data/Column.enso b/distribution/std-lib/Table/src/Data/Column.enso index 64904e0e9c88..b75d36c195f1 100644 --- a/distribution/std-lib/Table/src/Data/Column.enso +++ b/distribution/std-lib/Table/src/Data/Column.enso @@ -15,16 +15,16 @@ type Column display : Integer -> Boolean -> Text display show_rows=10 format_terminal=False = java_col = this.java_column - index = java_col.getIndex [] - col_name = java_col.getName [] - storage = java_col.getStorage [] - num_rows = java_col.getSize [] + index = java_col.getIndex + col_name = java_col.getName + storage = java_col.getStorage + num_rows = java_col.getSize display_rows = Math.min num_rows show_rows items = Vector.new display_rows num-> - row = if storage.isNa [num] then "Nothing" else + row = if storage.isNa num then "Nothing" else here.get_item_string storage num - [index.ilocString [num], row] - table = Table.print_table [index.getName [], col_name] items format_terminal + [index.ilocString num, row] + table = Table.print_table [index.getName, col_name] items format_terminal if num_rows - display_rows <= 0 then table else missing = '\n\u2026 and ' + (num_rows - display_rows).to_text + ' hidden rows.' table + missing @@ -141,11 +141,11 @@ type Column provided default. fill_missing : Any -> Column fill_missing default = - storage = this.java_column.getStorage [] - index = this.java_column.getIndex [] - name = this.java_column.getName [] - new_st = storage.fillMissing [default] - col = Java_Column.new [name, index, new_st].to_array + storage = this.java_column.getStorage + index = this.java_column.getIndex + name = this.java_column.getName + new_st = storage.fillMissing default + col = Java_Column.new name index new_st Column col ## Returns a new column without rows that had missing values. @@ -178,37 +178,37 @@ type Column of results. map : (Any -> Any) -> Column map function = - storage = this.java_column.getStorage [] - index = this.java_column.getIndex [] - new_st = storage.map [Nothing, function] - col = Java_Column.new ["Result", index, new_st].to_array + storage = this.java_column.getStorage + index = this.java_column.getIndex + new_st = storage.map Nothing function + col = Java_Column.new "Result" index new_st Column col ## Applies `function` to consecutive pairs of elements of `this` and `that` and returns a column of results. zip : Column -> (Any -> Any -> Any) -> Column zip that function = - s1 = this.java_column.getStorage [] - ix = this.java_column.getIndex [] - s2 = that.java_column.getStorage [] - rs = s1.zip [Nothing, function, s2] - Column (Java_Column.new ["Result", ix, rs].to_array) + s1 = this.java_column.getStorage + ix = this.java_column.getIndex + s2 = that.java_column.getStorage + rs = s1.zip Nothing function s2 + Column (Java_Column.new "Result" ix rs) ## Returns a new column, containing the same elements as `this`, but with the given name. - rename name = Column (this.java_column.rename [name]) + rename name = Column (this.java_column.rename name) ## Returns the name of this column. name : Text - name = this.java_column.getName [] + name = this.java_column.getName ## Returns the length of this column. length : Integer - length = this.java_column . getSize [] + length = this.java_column . getSize ## Returns the number of missing items in this column. count_missing : Integer - count_missing = this.java_column.getStorage [] . countMissing [] + count_missing = this.java_column.getStorage.countMissing ## Returns the number of non-null items in this column. count : Integer @@ -217,9 +217,9 @@ type Column ## Returns the item contained in this column at the given index. at : Integer -> Any at index = - storage = this.java_column.getStorage [] - if storage.isNa [index] then Nothing else - storage.getItem [index] + storage = this.java_column.getStorage + if storage.isNa index then Nothing else + storage.getItem index ## Selects only the rows of this column that correspond to `True` values in `indexes`. @@ -230,7 +230,7 @@ type Column my_column.where (status_column == "Valid") where : Column -> Column where indexes = - Column (this.java_column.mask [indexes.java_column]) + Column (this.java_column.mask indexes.java_column) ## Returns a vector containing all the elements in this column. to_vector : Vector @@ -239,7 +239,7 @@ type Column ## Returns the underlying storage type of this column. storage_type : Storage.Type storage_type = - tp = this.java_column.getStorage [] . getType [] + tp = this.java_column.getStorage.getType if tp == Storage_Type_String then Storage.Text else if tp == Storage_Type_Long then Storage.Integer else if tp == Storage_Type_Double then Storage.Decimal else @@ -250,8 +250,8 @@ type Column to_json : Json to_json = col = this.java_column - name = col.getName [] - storage = col.getStorage [] + name = col.getName + storage = col.getStorage json_factory = case this.storage_type of Storage.Text -> Json.String Storage.Integer -> Json.Number @@ -286,11 +286,11 @@ type Column ## Converts this column into a single-column table. to_table : Table.Table - to_table = Table.Table (this.java_column.toTable []) + to_table = Table.Table this.java_column.toTable ## Creates a new column given a name and a vector of elements. from_vector : Text -> Vector -> Column -from_vector name items = Column (Java_Column.fromItems [name, items.to_array]) +from_vector name items = Column (Java_Column.fromItems name items.to_array) ## Wraps a column grouped by its index. Allows performing aggregation operations on the contained values. @@ -310,7 +310,7 @@ type Aggregate_Column reduce : (Vector.Vector -> Any) -> Boolean -> Text -> Column reduce function skip_missing=True name_suffix="_result" = f arr = function (Vector.Vector arr) - r = this.java_column.aggregate [Nothing, name_suffix, f, skip_missing] + r = this.java_column.aggregate Nothing name_suffix f skip_missing Column r ## Sums the values in each group. @@ -320,7 +320,7 @@ type Aggregate_Column name to generate the resulting column name. sum : Text -> Column sum name_suffix='_sum' = - r = this.java_column.aggregate ['sum', name_suffix, (x-> Vector.Vector x . reduce (+)), True] + r = this.java_column.aggregate 'sum' name_suffix (x-> Vector.Vector x . reduce (+)) True Column r ## Computes the maximum element of each group. @@ -330,7 +330,7 @@ type Aggregate_Column name to generate the resulting column name. max : Text -> Column max name_suffix='_max' = - r = this.java_column.aggregate ['max', name_suffix, (x-> Vector.Vector x . reduce Math.max), True] + r = this.java_column.aggregate 'max' name_suffix (x-> Vector.Vector x . reduce Math.max) True Column r ## Computes the minimum element of each group. @@ -340,7 +340,7 @@ type Aggregate_Column name to generate the resulting column name. min : Text -> Column min name_suffix='_min' = - r = this.java_column.aggregate ['min', name_suffix, (x-> Vector.Vector x . reduce Math.min), True] + r = this.java_column.aggregate 'min' name_suffix (x-> Vector.Vector x . reduce Math.min) True Column r ## Computes the number of non-missing elements in each group. @@ -350,7 +350,7 @@ type Aggregate_Column name to generate the resulting column name. count : Text -> Column count name_suffix='_count' = - r = this.java_column.aggregate ['count', name_suffix, (x-> x.length), True] + r = this.java_column.aggregate 'count' name_suffix (x-> x.length) True Column r ## Computes the mean of non-missing elements in each group. @@ -362,7 +362,7 @@ type Aggregate_Column mean name_suffix='_mean' = vec_mean v = if v.length == 0 then Nothing else (Vector.Vector v).reduce (+) / v.length - r = this.java_column.aggregate ['mean', name_suffix, vec_mean, True] + r = this.java_column.aggregate 'mean' name_suffix vec_mean True Column r ## Gathers all elements in a group into a vector and returns a column of @@ -373,29 +373,29 @@ type Aggregate_Column name to generate the resulting column name. values : Text -> Column values name_suffix='_values' = - r = this.java_column.aggregate [Nothing, name_suffix, Vector.Vector, False] + r = this.java_column.aggregate Nothing name_suffix Vector.Vector False Column r ## PRIVATE run_vectorized_binary_op column name fallback_fn operand = case operand of Column col2 -> - s1 = column.java_column.getStorage [] - ix = column.java_column.getIndex [] - s2 = col2.getStorage [] - rs = s1.zip [name, fallback_fn, s2] - Column (Java_Column.new ["Result", ix, rs].to_array) + s1 = column.java_column.getStorage + ix = column.java_column.getIndex + s2 = col2.getStorage + rs = s1.zip name fallback_fn s2 + Column (Java_Column.new "Result" ix rs) _ -> - s1 = column.java_column.getStorage [] - ix = column.java_column.getIndex [] - rs = s1.bimap [name, fallback_fn, operand] - Column (Java_Column.new ["Result", ix, rs].to_array) + s1 = column.java_column.getStorage + ix = column.java_column.getIndex + rs = s1.bimap name fallback_fn operand + Column (Java_Column.new "Result" ix rs) ## PRIVATE run_vectorized_unary_op column name fallback_fn = - s = column.java_column.getStorage [] - ix = column.java_column.getIndex [] - rs = s.map [name, fallback_fn] - Column (Java_Column.new ["Result", ix, rs].to_array) + s = column.java_column.getStorage + ix = column.java_column.getIndex + rs = s.map name fallback_fn + Column (Java_Column.new "Result" ix rs) ## PRIVATE @@ -420,13 +420,13 @@ storage_type_bool = 4 ## PRIVATE storage_to_json storage factory = - Vector.new (storage.size []) ix-> - if storage.isNa [ix] then Json.Null else - factory (storage.getItem [ix]) + Vector.new storage.size ix-> + if storage.isNa ix then Json.Null else + factory (storage.getItem ix) ## PRIVATE get_item_string column ix = - tp = column.getType [] - if tp == Storage_Type_String then column.getItem [ix] else - column.getItem [ix] . to_text + tp = column.getType + if tp == Storage_Type_String then column.getItem ix else + column.getItem ix . to_text diff --git a/distribution/std-lib/Table/src/Data/Table.enso b/distribution/std-lib/Table/src/Data/Table.enso index ce01f4eb2c55..1e30abb7badc 100644 --- a/distribution/std-lib/Table/src/Data/Table.enso +++ b/distribution/std-lib/Table/src/Data/Table.enso @@ -16,16 +16,16 @@ type Table - format_terminal: whether ANSI-terminal formatting should be used display : Integer -> Boolean -> Text display show_rows=10 format_terminal=False = - cols = Vector.Vector (this.java_table.getColumns []) - index = this.java_table.getIndex [] - col_names = [index.getName[]] + cols.map (_.getName []) - col_vals = cols.map (_.getStorage []) - num_rows = this.java_table.nrows [] + cols = Vector.Vector this.java_table.getColumns + index = this.java_table.getIndex + col_names = [index.getName] + cols.map .getName + col_vals = cols.map .getStorage + num_rows = this.java_table.nrows display_rows = Math.min num_rows show_rows rows = Vector.new display_rows row_num-> cols = col_vals.map col-> - if col.isNa [row_num] then "Nothing" else Column.get_item_string col row_num - [index.ilocString [row_num]] + cols + if col.isNa row_num then "Nothing" else Column.get_item_string col row_num + [index.ilocString row_num] + cols table = here.print_table col_names rows format_terminal if num_rows - display_rows <= 0 then table else missing = '\n\u2026 and ' + (num_rows - display_rows).to_text + ' hidden rows.' @@ -49,7 +49,7 @@ type Table ## Returns the column with the given name. at : Text -> Column | Nothing - at name = case this.java_table.getColumnByName [name] of + at name = case this.java_table.getColumnByName name of Nothing -> Nothing c -> Column.Column c @@ -62,27 +62,27 @@ type Table my_table.where (my_table.at "Status" == "Valid") where : Column -> Table where indexes = - Table (this.java_table.mask [indexes.java_column]) + Table (this.java_table.mask indexes.java_column) ## Sets the column value at the given name. If a column with the given name already exists, it will be replaced. Otherwise a new column is added. set : Text -> Column -> Table set name column = - Table (this.java_table.addOrReplaceColumn [column.rename name . java_column]) + Table (this.java_table.addOrReplaceColumn (column.rename name . java_column)) ## Returns the vector of columns contained in this table. columns : Vector columns = - Vector.Vector (this.java_table.getColumns []) . map Column.Column + Vector.Vector this.java_table.getColumns . map Column.Column ## Sets the index of this table, using the column with the provided name. set_index : Text -> Table set_index index = - Table (this.java_table.indexFromColumn [index]) + Table (this.java_table.indexFromColumn index) ## Selects a subset of columns from this table by name. select : Vector -> Table - select columns = Table (this.java_table.selectColumns [columns.to_array]) + select columns = Table (this.java_table.selectColumns columns.to_array) ## Efficiently joins two tables based on either the index or the specified key column. @@ -107,7 +107,7 @@ type Table case other of Column.Column _ -> this.join other.to_table on drop_unmatched left_suffix right_suffix Table t -> - Table (this.java_table.join [t, drop_unmatched, on, left_suffix, right_suffix]) + Table (this.java_table.join t drop_unmatched on left_suffix right_suffix) ## Returns a new Table without rows that contained missing values in any of the columns. @@ -125,12 +125,12 @@ type Table drop_missing_columns : Table drop_missing_columns = non_missing = this.columns . filter (col -> col.count_missing == 0) - index = this.java_table.getIndex [] - Table (Java_Table.new [non_missing.map .java_column . to_array, index].to_array) + index = this.java_table.getIndex + Table (Java_Table.new (non_missing.map .java_column . to_array) index) ## Returns the amount of rows in this table. nrows : Integer - nrows = this.java_table.nrows [] + nrows = this.java_table.nrows ## Returns a Table describing this table's contents. @@ -162,7 +162,7 @@ type Table Table.join [records_num, total_quantity, mean_price] group : Text | Nothing -> Aggregate_Table group by=Nothing = - Aggregate_Table (this.java_table.group [by]) + Aggregate_Table (this.java_table.group by) ## Represents a table with grouped rows. type Aggregate_Table @@ -170,7 +170,7 @@ type Aggregate_Table ## Returns a vector of aggregate columns in this table. columns : Vector.Vector - columns = Vector.Vector (this.java_table.getColumns []) . map Column.Aggregate_Column + columns = Vector.Vector this.java_table.getColumns . map Column.Aggregate_Column ## Returns a table containing columns resulting from calling `values` on each column in `this`. @@ -179,11 +179,11 @@ type Aggregate_Table ## Returns a column containing the number of elements in each group. count : Column - count = Column.Column (this.java_table.count []) + count = Column.Column this.java_table.count ## Returns an aggregate column with the given name, contained in this table. at : Text -> Column | Nothing - at name = case this.java_table.getColumnByName [name] of + at name = case this.java_table.getColumnByName name of Nothing -> Nothing c -> Column.Aggregate_Column c @@ -195,7 +195,7 @@ type Aggregate_Table print show_rows=10 = this.values.print show_rows ## PRIVATE -from_columns cols = Table (Java_Table.new [cols.to_array].to_array) +from_columns cols = Table (Java_Table.new cols.to_array) ## Creates a new table from a vector of `[name, items]` pairs. diff --git a/distribution/std-lib/Table/src/Io/Csv.enso b/distribution/std-lib/Table/src/Io/Csv.enso index 4a3fc1c7e50e..dca1aec4e264 100644 --- a/distribution/std-lib/Table/src/Io/Csv.enso +++ b/distribution/std-lib/Table/src/Io/Csv.enso @@ -15,7 +15,7 @@ polyglot java import org.enso.table.format.csv.Parser inferred from the CSV header row or set manually. File.File.read_csv : Boolean -> Text -> Table File.File.read_csv has_header=True prefix='C' = - parser_inst = Parser.create [has_header, prefix] + parser_inst = Parser.create has_header prefix this.with_input_stream [File.Option.Read] stream-> stream.with_java_stream java_stream-> - Table.Table (parser_inst.parse [java_stream]) + Table.Table (parser_inst.parse java_stream) diff --git a/docs/polyglot/java.md b/docs/polyglot/java.md index ddf3d7d35222..96dedccbc06d 100644 --- a/docs/polyglot/java.md +++ b/docs/polyglot/java.md @@ -75,9 +75,12 @@ the following: sure that they are available. - Create java-compatible object entities that dynamically look up and dispatch both static methods on classes (by name), and methods on objects (by name). - This includes the constructor. + This includes the constructor and field reads. - This invocation syntax is integrated into Enso as variadic methods, allowing us to deal with the inter-language impedance mismatch. +- Due to different semantics of Java calls, currying and over-applying functions + are necessarily disabled for such calls, instead expecting the exact arguments + list to be passed. An example can be found below: @@ -85,9 +88,9 @@ An example can be found below: polyglot java import com.example.MyClass as MyClassJava main = - x = MyClassJava.foo [1, 2, 3] - inst = MyClassJava.new [a, b, c] - bar = inst.methodName [x, y] + x = MyClassJava.foo 1 2 3 + inst = MyClassJava.new a b c + bar = inst.methodName x y ``` > The actionables for this section are: diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/IndirectInvokeMethodNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/IndirectInvokeMethodNode.java index 587bfb702c69..c831b8f6f1ea 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/IndirectInvokeMethodNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/IndirectInvokeMethodNode.java @@ -1,26 +1,26 @@ package org.enso.interpreter.node.callable; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.ReportPolymorphism; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; +import org.enso.interpreter.Language; import org.enso.interpreter.node.BaseNode; import org.enso.interpreter.node.callable.dispatch.IndirectInvokeFunctionNode; -import org.enso.interpreter.node.callable.resolver.ArrayResolverNode; -import org.enso.interpreter.node.callable.resolver.AtomResolverNode; -import org.enso.interpreter.node.callable.resolver.BigIntegerResolverNode; -import org.enso.interpreter.node.callable.resolver.BooleanResolverNode; -import org.enso.interpreter.node.callable.resolver.ConstructorResolverNode; -import org.enso.interpreter.node.callable.resolver.DataflowErrorResolverNode; -import org.enso.interpreter.node.callable.resolver.DoubleResolverNode; -import org.enso.interpreter.node.callable.resolver.FunctionResolverNode; -import org.enso.interpreter.node.callable.resolver.LongResolverNode; -import org.enso.interpreter.node.callable.resolver.OtherResolverNode; -import org.enso.interpreter.node.callable.resolver.TextResolverNode; +import org.enso.interpreter.node.callable.resolver.*; +import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode; +import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; import org.enso.interpreter.runtime.callable.atom.Atom; @@ -30,11 +30,14 @@ import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.error.DataflowError; import org.enso.interpreter.runtime.error.PanicSentinel; +import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import org.enso.interpreter.runtime.number.EnsoBigInteger; import org.enso.interpreter.runtime.state.Stateful; @GenerateUncached @ReportPolymorphism +@ImportStatic({HostMethodCallNode.PolyglotCallType.class, HostMethodCallNode.class}) public abstract class IndirectInvokeMethodNode extends Node { /** @return a new indirect method invocation node */ @@ -53,204 +56,35 @@ public abstract Stateful execute( InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, BaseNode.TailStatus isTail); - @Specialization - Stateful doAtom( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - Atom _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached AtomResolverNode atomResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = atomResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doConstructor( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - AtomConstructor _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached ConstructorResolverNode constructorResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = constructorResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doBigInteger( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - EnsoBigInteger _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached BigIntegerResolverNode bigIntegerResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = bigIntegerResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doLong( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - long _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached LongResolverNode longResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = longResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doDouble( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - double _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached DoubleResolverNode doubleResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = doubleResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doBoolean( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - boolean _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached BooleanResolverNode booleanResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = booleanResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doText( + @Specialization(guards = "dispatch.hasFunctionalDispatch(_this)") + Stateful doFunctionalDispatch( MaterializedFrame frame, Object state, UnresolvedSymbol symbol, - Text _this, - Object[] arguments, - CallArgumentInfo[] schema, - InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, - InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, - BaseNode.TailStatus isTail, - @Cached TextResolverNode textResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = textResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); - } - - @Specialization - Stateful doFunction( - MaterializedFrame frame, - Object state, - UnresolvedSymbol symbol, - Function _this, + Object _this, Object[] arguments, CallArgumentInfo[] schema, InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, BaseNode.TailStatus isTail, - @Cached FunctionResolverNode functionResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = functionResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); + @CachedLibrary(limit = "10") MethodDispatchLibrary dispatch, + @Cached IndirectInvokeFunctionNode invokeFunctionNode, + @CachedContext(Language.class) TruffleLanguage.ContextReference ctx) { + try { + Function function = dispatch.getFunctionalDispatch(_this, symbol); + return invokeFunctionNode.execute( + function, + frame, + state, + arguments, + schema, + defaultsExecutionMode, + argumentsExecutionMode, + isTail); + } catch (MethodDispatchLibrary.NoSuchMethodException e) { + throw new PanicException( + ctx.get().getBuiltins().error().makeNoSuchMethodError(_this, symbol), this); + } } @Specialization @@ -297,38 +131,49 @@ Stateful doPanicSentinel( throw _this; } - @Specialization - Stateful doArray( + @Specialization( + guards = { + "!methods.hasFunctionalDispatch(_this)", + "!methods.hasSpecialDispatch(_this)", + "polyglotCallType != NOT_SUPPORTED" + }) + Stateful doPolyglot( MaterializedFrame frame, Object state, UnresolvedSymbol symbol, - Array _this, + Object _this, Object[] arguments, CallArgumentInfo[] schema, InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, BaseNode.TailStatus isTail, - @Cached ArrayResolverNode arrayResolverNode, - @Cached IndirectInvokeFunctionNode invokeFunctionNode, - @Cached ConditionProfile profile) { - Function function = arrayResolverNode.execute(symbol, _this); - if (profile.profile(function == null)) { - return new Stateful(state, _this); - } else { - return invokeFunctionNode.execute( - function, - frame, - state, - arguments, - schema, - defaultsExecutionMode, - argumentsExecutionMode, - isTail); + @CachedLibrary(limit = "10") MethodDispatchLibrary methods, + @CachedLibrary(limit = "10") InteropLibrary interop, + @Bind("getPolyglotCallType(_this, symbol.getName(), interop)") + HostMethodCallNode.PolyglotCallType polyglotCallType, + @Cached ThunkExecutorNode argExecutor, + @Cached AnyResolverNode anyResolverNode, + @Cached HostMethodCallNode hostMethodCallNode, + @Cached IndirectInvokeFunctionNode invokeFunctionNode) { + + Object[] args = new Object[arguments.length - 1]; + for (int i = 0; i < arguments.length - 1; i++) { + Stateful r = argExecutor.executeThunk(arguments[i + 1], state, BaseNode.TailStatus.NOT_TAIL); + state = r.getState(); + args[i] = r.getValue(); } + return new Stateful( + state, hostMethodCallNode.execute(polyglotCallType, symbol.getName(), _this, args)); } - @Specialization(guards = "isFallback(_this)") - Stateful doOther( + @ExplodeLoop + @Specialization( + guards = { + "!methods.hasFunctionalDispatch(_this)", + "!methods.hasSpecialDispatch(_this)", + "getPolyglotCallType(_this, symbol.getName(), interop) == NOT_SUPPORTED" + }) + Stateful doFallback( MaterializedFrame frame, Object state, UnresolvedSymbol symbol, @@ -338,9 +183,15 @@ Stateful doOther( InvokeCallableNode.DefaultsExecutionMode defaultsExecutionMode, InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode, BaseNode.TailStatus isTail, - @Cached OtherResolverNode otherResolverNode, + @CachedLibrary(limit = "10") MethodDispatchLibrary methods, + @CachedLibrary(limit = "10") InteropLibrary interop, + @Bind("getPolyglotCallType(_this, symbol.getName(), interop)") + HostMethodCallNode.PolyglotCallType polyglotCallType, + @Cached ThunkExecutorNode argExecutor, + @Cached AnyResolverNode anyResolverNode, + @Cached HostMethodCallNode hostMethodCallNode, @Cached IndirectInvokeFunctionNode invokeFunctionNode) { - Function function = otherResolverNode.execute(symbol, _this); + Function function = anyResolverNode.execute(symbol, _this); return invokeFunctionNode.execute( function, frame, @@ -351,8 +202,4 @@ Stateful doOther( argumentsExecutionMode, isTail); } - - static boolean isFallback(Object _this) { - return InvokeMethodNode.isFallback(_this); - } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java index e59d1221bd31..9b822a523094 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/InvokeMethodNode.java @@ -1,40 +1,36 @@ package org.enso.interpreter.node.callable; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.source.SourceSection; import java.util.UUID; +import org.enso.interpreter.Language; import org.enso.interpreter.node.BaseNode; import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode; -import org.enso.interpreter.node.callable.resolver.ArrayResolverNode; -import org.enso.interpreter.node.callable.resolver.AtomResolverNode; -import org.enso.interpreter.node.callable.resolver.BigIntegerResolverNode; -import org.enso.interpreter.node.callable.resolver.BooleanResolverNode; -import org.enso.interpreter.node.callable.resolver.ConstructorResolverNode; -import org.enso.interpreter.node.callable.resolver.DataflowErrorResolverNode; -import org.enso.interpreter.node.callable.resolver.DoubleResolverNode; -import org.enso.interpreter.node.callable.resolver.FunctionResolverNode; -import org.enso.interpreter.node.callable.resolver.LongResolverNode; -import org.enso.interpreter.node.callable.resolver.OtherResolverNode; -import org.enso.interpreter.node.callable.resolver.TextResolverNode; +import org.enso.interpreter.node.callable.resolver.*; +import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode; +import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.callable.atom.AtomConstructor; import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; -import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.error.DataflowError; import org.enso.interpreter.runtime.error.PanicSentinel; -import org.enso.interpreter.runtime.number.EnsoBigInteger; +import org.enso.interpreter.runtime.error.PanicException; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import org.enso.interpreter.runtime.state.Stateful; +@ImportStatic({HostMethodCallNode.PolyglotCallType.class, HostMethodCallNode.class}) public abstract class InvokeMethodNode extends BaseNode { private @Child InvokeFunctionNode invokeFunctionNode; private final ConditionProfile errorProfile = ConditionProfile.createCountingProfile(); + private final int argumentCount; /** * Creates a new node for method invocation. @@ -57,6 +53,7 @@ public static InvokeMethodNode build( InvokeCallableNode.ArgumentsExecutionMode argumentsExecutionMode) { this.invokeFunctionNode = InvokeFunctionNode.build(schema, defaultsExecutionMode, argumentsExecutionMode); + this.argumentCount = schema.length; } @Override @@ -68,100 +65,22 @@ public void setTailStatus(TailStatus tailStatus) { public abstract Stateful execute( VirtualFrame frame, Object state, UnresolvedSymbol symbol, Object _this, Object[] arguments); - @Specialization - Stateful doAtom( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - Atom _this, - Object[] arguments, - @Cached AtomResolverNode atomResolverNode) { - Function function = atomResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doConstructor( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - AtomConstructor _this, - Object[] arguments, - @Cached ConstructorResolverNode constructorResolverNode) { - Function function = constructorResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doBigInteger( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - EnsoBigInteger _this, - Object[] arguments, - @Cached BigIntegerResolverNode bigIntegerResolverNode) { - Function function = bigIntegerResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doLong( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - long _this, - Object[] arguments, - @Cached LongResolverNode longResolverNode) { - Function function = longResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doDouble( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - double _this, - Object[] arguments, - @Cached DoubleResolverNode doubleResolverNode) { - Function function = doubleResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doBoolean( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - boolean _this, - Object[] arguments, - @Cached BooleanResolverNode booleanResolverNode) { - Function function = booleanResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doText( - VirtualFrame frame, - Object state, - UnresolvedSymbol symbol, - Text _this, - Object[] arguments, - @Cached TextResolverNode textResolverNode) { - Function function = textResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization - Stateful doFunction( + @Specialization(guards = "dispatch.hasFunctionalDispatch(_this)") + Stateful doFunctionalDispatch( VirtualFrame frame, Object state, UnresolvedSymbol symbol, - Function _this, + Object _this, Object[] arguments, - @Cached FunctionResolverNode functionResolverNode) { - Function function = functionResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); + @CachedLibrary(limit = "10") MethodDispatchLibrary dispatch, + @CachedContext(Language.class) TruffleLanguage.ContextReference ctx) { + try { + Function function = dispatch.getFunctionalDispatch(_this, symbol); + return invokeFunctionNode.execute(function, frame, state, arguments); + } catch (MethodDispatchLibrary.NoSuchMethodException e) { + throw new PanicException( + ctx.get().getBuiltins().error().makeNoSuchMethodError(_this, symbol), this); + } } @Specialization @@ -190,49 +109,70 @@ Stateful doPanicSentinel( throw _this; } - @Specialization - Stateful doArray( + @ExplodeLoop + @Specialization( + guards = { + "!methods.hasFunctionalDispatch(_this)", + "!methods.hasSpecialDispatch(_this)", + "polyglotCallType != NOT_SUPPORTED" + }) + Stateful doPolyglot( VirtualFrame frame, Object state, UnresolvedSymbol symbol, - Array _this, + Object _this, Object[] arguments, - @Cached ArrayResolverNode arrayResolverNode) { - Function function = arrayResolverNode.execute(symbol, _this); - return invokeFunctionNode.execute(function, frame, state, arguments); - } - - @Specialization(guards = "isFallback(_this)") - Stateful doOther( + @CachedLibrary(limit = "10") MethodDispatchLibrary methods, + @CachedLibrary(limit = "10") InteropLibrary interop, + @Bind("getPolyglotCallType(_this, symbol.getName(), interop)") + HostMethodCallNode.PolyglotCallType polyglotCallType, + @Cached("buildExecutors()") ThunkExecutorNode[] argExecutors, + @Cached AnyResolverNode anyResolverNode, + @Cached HostMethodCallNode hostMethodCallNode) { + Object[] args = new Object[argExecutors.length]; + for (int i = 0; i < argExecutors.length; i++) { + Stateful r = argExecutors[i].executeThunk(arguments[i + 1], state, TailStatus.NOT_TAIL); + state = r.getState(); + args[i] = r.getValue(); + } + return new Stateful( + state, hostMethodCallNode.execute(polyglotCallType, symbol.getName(), _this, args)); + } + + @ExplodeLoop + @Specialization( + guards = { + "!methods.hasFunctionalDispatch(_this)", + "!methods.hasSpecialDispatch(_this)", + "getPolyglotCallType(_this, symbol.getName(), interop) == NOT_SUPPORTED" + }) + Stateful doFallback( VirtualFrame frame, Object state, UnresolvedSymbol symbol, Object _this, Object[] arguments, - @Cached OtherResolverNode otherResolverNode) { - Function function = otherResolverNode.execute(symbol, _this); + @CachedLibrary(limit = "10") MethodDispatchLibrary methods, + @CachedLibrary(limit = "10") InteropLibrary interop, + @Cached AnyResolverNode anyResolverNode) { + Function function = anyResolverNode.execute(symbol, _this); return invokeFunctionNode.execute(function, frame, state, arguments); } - static boolean isFallback(Object _this) { - return !(_this instanceof Atom) - && !(_this instanceof AtomConstructor) - && !(_this instanceof EnsoBigInteger) - && !(_this instanceof Long) - && !(_this instanceof Double) - && !(_this instanceof Boolean) - && !(_this instanceof Text) - && !(_this instanceof Function) - && !(_this instanceof DataflowError) - && !(_this instanceof Array); - } - @Override public SourceSection getSourceSection() { Node parent = getParent(); return parent == null ? null : parent.getSourceSection(); } + ThunkExecutorNode[] buildExecutors() { + ThunkExecutorNode[] result = new ThunkExecutorNode[argumentCount - 1]; + for (int i = 0; i < argumentCount - 1; i++) { + result[i] = ThunkExecutorNode.build(); + } + return result; + } + /** * Sets the expression ID of this node. * diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/DoubleResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AnyResolverNode.java similarity index 52% rename from engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/DoubleResolverNode.java rename to engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AnyResolverNode.java index 1a6902ddf8c4..3c4e962811cc 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/DoubleResolverNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AnyResolverNode.java @@ -1,36 +1,33 @@ package org.enso.interpreter.node.callable.resolver; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.dsl.*; import org.enso.interpreter.Language; import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.error.DataflowError; @GenerateUncached @ReportPolymorphism -public abstract class DoubleResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, double self); +public abstract class AnyResolverNode extends BaseResolverNode { + + public abstract Function execute(UnresolvedSymbol symbol, Object _this); @Specialization( guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, limit = "CACHE_SIZE") Function resolveCached( UnresolvedSymbol symbol, - double _this, + Object _this, @CachedContext(Language.class) Context context, @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnDouble(context, cachedSymbol)") Function function) { + @Cached("resolveMethodOnAny(context, cachedSymbol)") Function function) { return function; } @Specialization(replaces = "resolveCached") Function resolve( - UnresolvedSymbol symbol, double _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnDouble(context, symbol); - return throwIfNull(context, function, _this, symbol); + UnresolvedSymbol symbol, Object _this, @CachedContext(Language.class) Context context) { + return throwIfNull(context, resolveMethodOnAny(context, symbol), _this, symbol); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ArrayResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ArrayResolverNode.java deleted file mode 100644 index 65d8f835c74c..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ArrayResolverNode.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Array; - -@GenerateUncached -@ReportPolymorphism -public abstract class ArrayResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, Array _this); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - Array _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnArray(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, Array _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnArray(context, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AtomResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AtomResolverNode.java deleted file mode 100644 index 9534ab90da06..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/AtomResolverNode.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.callable.function.Function; - -@GenerateUncached -@ReportPolymorphism -public abstract class AtomResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, Atom self); - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "symbol == cachedSymbol", - "_this.getConstructor() == cachedConstructor", - "function != null" - }, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - Atom _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("_this.getConstructor()") AtomConstructor cachedConstructor, - @Cached("resolveMethodOnAtom(context, cachedConstructor, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, Atom atom, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnAtom(context, atom.getConstructor(), symbol); - return throwIfNull(context, function, atom, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BaseResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BaseResolverNode.java index feaf421c1521..bec6ad75e30f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BaseResolverNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BaseResolverNode.java @@ -23,101 +23,13 @@ protected Function throwIfNull( return function; } - @CompilerDirectives.TruffleBoundary - protected Function resolveMethodOnAtom( - Context context, AtomConstructor cons, UnresolvedSymbol symbol) { - return symbol.resolveFor(cons, context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnLong(Context context, UnresolvedSymbol symbol) { - Number number = context.getBuiltins().number(); - return symbol.resolveFor( - number.getSmallInteger(), - number.getInteger(), - number.getNumber(), - context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnBigInteger(Context context, UnresolvedSymbol symbol) { - Number number = context.getBuiltins().number(); - return symbol.resolveFor( - number.getBigInteger(), - number.getInteger(), - number.getNumber(), - context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnDouble(Context context, UnresolvedSymbol symbol) { - Number number = context.getBuiltins().number(); - return symbol.resolveFor(number.getDecimal(), number.getNumber(), context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnPrimBoolean(Context context, UnresolvedSymbol symbol) { - Bool bool = context.getBuiltins().bool(); - if (symbol.resolveFor(bool.getFalse()) != null) { - return null; - } - if (symbol.resolveFor(bool.getTrue()) != null) { - return null; - } - return symbol.resolveFor(bool.getBool(), context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnBool(Context context, boolean self, UnresolvedSymbol symbol) { - Bool bool = context.getBuiltins().bool(); - AtomConstructor cons = self ? bool.getTrue() : bool.getFalse(); - return symbol.resolveFor(cons, bool.getBool(), context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnString(Context context, UnresolvedSymbol symbol) { - return symbol.resolveFor(context.getBuiltins().text().getText(), context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function resolveMethodOnFunction(Context context, UnresolvedSymbol symbol) { - return symbol.resolveFor(context.getBuiltins().function(), context.getBuiltins().any()); - } - @CompilerDirectives.TruffleBoundary Function resolveMethodOnError(Context context, UnresolvedSymbol symbol) { return symbol.resolveFor(context.getBuiltins().dataflowError().constructor()); } @CompilerDirectives.TruffleBoundary - Function resolveMethodOnArray(Context context, UnresolvedSymbol symbol) { - return symbol.resolveFor(context.getBuiltins().mutable().array(), context.getBuiltins().any()); - } - - @CompilerDirectives.TruffleBoundary - Function buildHostResolver(Context context, UnresolvedSymbol symbol) { - if (symbol.getName().equals("new")) { - return context.getBuiltins().polyglot().getConstructorDispatch(); - } else if (symbol.getName().equals("to_text")) { - return context.getBuiltins().polyglot().getPolyglotToTextFunction(); - } else if (symbol.getName().equals("catch")) { - return symbol.resolveFor(context.getBuiltins().any()); - } else if (symbol.getName().equals("==")) { - return symbol.resolveFor(context.getBuiltins().any()); - } else { - return context.getBuiltins().polyglot().buildPolyglotMethodDispatch(symbol); - } - } - - static boolean isPolyglotArrayMethod(UnresolvedSymbol symbol) { - return symbol.getName().equals("at") || symbol.getName().equals("length"); - } - - Function resolveMethodOnPolyglotArray(Context context, UnresolvedSymbol symbol) { - if (symbol.getName().equals("length")) { - return context.getBuiltins().polyglot().getPolyglotArrayLengthFunction(); - } else { - return context.getBuiltins().polyglot().getPolyglotArrayAtFunction(); - } + Function resolveMethodOnAny(Context context, UnresolvedSymbol symbol) { + return symbol.resolveFor(context.getBuiltins().any()); } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BigIntegerResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BigIntegerResolverNode.java deleted file mode 100644 index b34a8fd91b0a..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BigIntegerResolverNode.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.number.EnsoBigInteger; - -@GenerateUncached -@ReportPolymorphism -public abstract class BigIntegerResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, EnsoBigInteger self); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - EnsoBigInteger _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnBigInteger(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, - EnsoBigInteger _this, - @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnBigInteger(context, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BooleanResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BooleanResolverNode.java deleted file mode 100644 index 23371aa90aed..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/BooleanResolverNode.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; - -@GenerateUncached -@ReportPolymorphism -public abstract class BooleanResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, boolean self); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - boolean _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnPrimBoolean(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "cachedSymbol == symbol", - "_this", - "function != null" - }, - limit = "CACHE_SIZE", - replaces = "resolveCached") - Function resolveTrueCached( - UnresolvedSymbol symbol, - boolean _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnBool(context, true, cachedSymbol)") Function function) { - return function; - } - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "cachedSymbol == symbol", - "!_this", - "function != null" - }, - limit = "CACHE_SIZE", - replaces = "resolveCached") - Function resolveFalseCached( - UnresolvedSymbol symbol, - boolean _this, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @CachedContext(Language.class) Context context, - @Cached("resolveMethodOnBool(context, false, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = {"resolveTrueCached", "resolveFalseCached"}) - Function resolve( - UnresolvedSymbol symbol, boolean _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnBool(context, _this, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ConstructorResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ConstructorResolverNode.java deleted file mode 100644 index 6e9b2bf81b04..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/ConstructorResolverNode.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.*; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.atom.Atom; -import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.callable.function.Function; - -@GenerateUncached -@ReportPolymorphism -public abstract class ConstructorResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, AtomConstructor self); - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "cachedSymbol == symbol", - "_this == cachedConstructor", - "function != null" - }, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - AtomConstructor _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("_this") AtomConstructor cachedConstructor, - @Cached("resolveMethodOnAtom(context, cachedConstructor, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, - AtomConstructor _this, - @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnAtom(context, _this, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/FunctionResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/FunctionResolverNode.java deleted file mode 100644 index 3bd6a03214c6..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/FunctionResolverNode.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; - -@GenerateUncached -@ReportPolymorphism -public abstract class FunctionResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, Function self); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - Function _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnFunction(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, Function _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnFunction(context, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/HostMethodCallNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/HostMethodCallNode.java new file mode 100644 index 000000000000..6b392f665dba --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/HostMethodCallNode.java @@ -0,0 +1,194 @@ +package org.enso.interpreter.node.callable.resolver; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.interop.*; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.BranchProfile; +import org.enso.interpreter.Language; +import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.error.PanicException; + +/** Discovers and performs method calls on foreign values. */ +@GenerateUncached +@ReportPolymorphism +@ImportStatic(HostMethodCallNode.PolyglotCallType.class) +public abstract class HostMethodCallNode extends Node { + + /** Represents a mode of calling a method on a polyglot value. */ + public enum PolyglotCallType { + CALL_METHOD, + GET_MEMBER, + INSTANTIATE, + GET_ARRAY_LENGTH, + READ_ARRAY_ELEMENT, + NOT_SUPPORTED + } + + private static final String ARRAY_LENGTH_NAME = "length"; + private static final String ARRAY_READ_NAME = "at"; + private static final String NEW_NAME = "new"; + + static final int LIB_LIMIT = 3; + + /** + * Returns a token instructing the caller about what mode of calling the given method should be + * used. + * + * @param _this the method call target + * @param methodName the method name + * @param library an instance of interop library to use for interacting with the target + * @return a {@link PolyglotCallType} to use for this target and method + */ + public static PolyglotCallType getPolyglotCallType( + Object _this, String methodName, InteropLibrary library) { + if (library.isMemberInvocable(_this, methodName)) { + return PolyglotCallType.CALL_METHOD; + } else if (library.isMemberReadable(_this, methodName)) { + return PolyglotCallType.GET_MEMBER; + } else if (library.isInstantiable(_this) && methodName.equals(NEW_NAME)) { + return PolyglotCallType.INSTANTIATE; + } else if (library.hasArrayElements(_this) && methodName.equals(ARRAY_LENGTH_NAME)) { + return PolyglotCallType.GET_ARRAY_LENGTH; + } else if (library.hasArrayElements(_this) && methodName.equals(ARRAY_READ_NAME)) { + return PolyglotCallType.READ_ARRAY_ELEMENT; + } else { + return PolyglotCallType.NOT_SUPPORTED; + } + } + + /** + * Calls a method on an object, using a specified {@link PolyglotCallType}. + * + * @param callType the call type to perform + * @param symbol the method name + * @param _this the call receiver + * @param args the arguments + * @return the result of calling the method on the receiver + */ + public abstract Object execute( + PolyglotCallType callType, String symbol, Object _this, Object[] args); + + @Specialization(guards = {"callType == CALL_METHOD"}) + Object resolveHostMethod( + PolyglotCallType callType, + String symbol, + Object _this, + Object[] args, + @CachedLibrary(limit = "LIB_LIMIT") InteropLibrary members, + @CachedContext(Language.class) Context context, + @Cached HostValueToEnsoNode hostValueToEnsoNode) { + try { + return hostValueToEnsoNode.execute(members.invokeMember(_this, symbol, args)); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw new IllegalStateException( + "Impossible to reach here. The member is checked to be invocable."); + } catch (ArityException e) { + throw new PanicException( + context.getBuiltins().error().makeArityError(e.getExpectedArity(), e.getActualArity()), + this); + } catch (UnsupportedTypeException e) { + throw new PanicException( + context.getBuiltins().error().makeUnsupportedArgumentsError(e.getSuppliedValues()), this); + } + } + + @Specialization(guards = {"callType == GET_MEMBER"}) + Object resolveHostField( + PolyglotCallType callType, + String symbol, + Object _this, + Object[] args, + @CachedLibrary(limit = "LIB_LIMIT") InteropLibrary members, + @CachedContext(Language.class) Context context, + @Cached HostValueToEnsoNode hostValueToEnsoNode, + @Cached BranchProfile errorProfile) { + if (args.length != 0) { + errorProfile.enter(); + throw new PanicException(context.getBuiltins().error().makeArityError(0, args.length), this); + } + try { + return hostValueToEnsoNode.execute(members.readMember(_this, symbol)); + } catch (UnsupportedMessageException | UnknownIdentifierException e) { + throw new IllegalStateException( + "Impossible to reach here. The member is checked to be readable."); + } + } + + @Specialization(guards = {"callType == INSTANTIATE"}) + Object resolveHostConstructor( + PolyglotCallType callType, + String symbol, + Object _this, + Object[] args, + @CachedLibrary(limit = "LIB_LIMIT") InteropLibrary instances, + @CachedContext(Language.class) Context context, + @Cached HostValueToEnsoNode hostValueToEnsoNode) { + try { + return hostValueToEnsoNode.execute(instances.instantiate(_this, args)); + } catch (UnsupportedMessageException e) { + throw new IllegalStateException( + "Impossible to reach here. The member is checked to be instantiable."); + } catch (ArityException e) { + throw new PanicException( + context.getBuiltins().error().makeArityError(e.getExpectedArity(), e.getActualArity()), + this); + } catch (UnsupportedTypeException e) { + throw new PanicException( + context.getBuiltins().error().makeUnsupportedArgumentsError(e.getSuppliedValues()), this); + } + } + + @Specialization(guards = {"callType == GET_ARRAY_LENGTH"}) + Object resolveHostArrayLength( + PolyglotCallType callType, + String symbol, + Object _this, + Object[] args, + @CachedLibrary(limit = "LIB_LIMIT") InteropLibrary arrays, + @CachedContext(Language.class) Context ctx, + @Cached BranchProfile errorProfile, + @Cached HostValueToEnsoNode hostValueToEnsoNode) { + if (args.length != 0) { + errorProfile.enter(); + throw new PanicException(ctx.getBuiltins().error().makeArityError(0, args.length), this); + } + try { + return hostValueToEnsoNode.execute(arrays.getArraySize(_this)); + } catch (UnsupportedMessageException e) { + throw new IllegalStateException("Impossible to reach here, _this is checked to be an array"); + } + } + + @Specialization(guards = {"callType == READ_ARRAY_ELEMENT"}) + Object resolveHostArrayRead( + PolyglotCallType callType, + String symbol, + Object _this, + Object[] args, + @CachedLibrary(limit = "LIB_LIMIT") InteropLibrary arrays, + @Cached BranchProfile arityErrorProfile, + @Cached BranchProfile typeErrorProfile, + @CachedContext(Language.class) Context ctx, + @Cached HostValueToEnsoNode hostValueToEnsoNode) { + if (args.length != 1) { + arityErrorProfile.enter(); + throw new PanicException(ctx.getBuiltins().error().makeArityError(1, args.length), this); + } + if (!(args[0] instanceof Long)) { + typeErrorProfile.enter(); + throw new PanicException( + ctx.getBuiltins().error().makeInvalidArrayIndexError(_this, args[0]), this); + } + long idx = (Long) args[0]; + try { + return hostValueToEnsoNode.execute(arrays.readArrayElement(_this, idx)); + } catch (UnsupportedMessageException e) { + throw new IllegalStateException("Impossible to reach here, _this is checked to be an array"); + } catch (InvalidArrayIndexException e) { + throw new PanicException( + ctx.getBuiltins().error().makeInvalidArrayIndexError(_this, idx), this); + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/LongResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/LongResolverNode.java deleted file mode 100644 index 096fdb379ef1..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/LongResolverNode.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; - -@GenerateUncached -@ReportPolymorphism -public abstract class LongResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, long self); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - long _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnLong(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, long _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnLong(context, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/OtherResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/OtherResolverNode.java deleted file mode 100644 index f197b8f2466c..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/OtherResolverNode.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.CachedLibrary; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.error.PanicException; - -@GenerateUncached -@ReportPolymorphism -public abstract class OtherResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, Object _this); - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "symbol == cachedSymbol", - "isPolyglotArrayMethod(cachedSymbol)", - "arrays.hasArrayElements(_this)" - }, - limit = "CACHE_SIZE") - Function resolvePolyglotArrayCached( - UnresolvedSymbol symbol, - Object _this, - @CachedContext(Language.class) Context context, - @CachedLibrary("_this") InteropLibrary arrays, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnPolyglotArray(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization( - guards = {"isPolyglotArrayMethod(symbol)", "arrays.hasArrayElements(_this)"}, - replaces = "resolvePolyglotArrayCached") - Function resolvePolyglotArray( - UnresolvedSymbol symbol, - Object _this, - @CachedContext(Language.class) Context context, - @CachedLibrary(limit = "CACHE_SIZE") InteropLibrary arrays) { - return resolveMethodOnPolyglotArray(context, symbol); - } - - @Specialization( - guards = { - "!context.isCachingDisabled()", - "cachedSymbol == symbol", - "context.getEnvironment().isHostObject(_this)" - }, - limit = "CACHE_SIZE") - Function resolveHostCached( - UnresolvedSymbol symbol, - Object _this, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @CachedContext(Language.class) Context context, - @Cached("buildHostResolver(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization( - guards = "context.getEnvironment().isHostObject(_this)", - replaces = "resolveHostCached") - Function resolveHost( - UnresolvedSymbol symbol, Object _this, @CachedContext(Language.class) Context context) { - return buildHostResolver(context, symbol); - } - - @Fallback - Function resolveUnknown(UnresolvedSymbol symbol, Object _this) { - CompilerDirectives.transferToInterpreter(); - Context context = lookupContextReference(Language.class).get(); - throw new PanicException( - context.getBuiltins().error().makeNoSuchMethodError(_this, symbol), this); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/TextResolverNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/TextResolverNode.java deleted file mode 100644 index 40c783068608..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/callable/resolver/TextResolverNode.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.enso.interpreter.node.callable.resolver; - -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.CachedContext; -import com.oracle.truffle.api.dsl.GenerateUncached; -import com.oracle.truffle.api.dsl.ReportPolymorphism; -import com.oracle.truffle.api.dsl.Specialization; -import org.enso.interpreter.Language; -import org.enso.interpreter.runtime.Context; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.text.Text; - -@GenerateUncached -@ReportPolymorphism -public abstract class TextResolverNode extends BaseResolverNode { - public abstract Function execute(UnresolvedSymbol symbol, Text self); - - @Specialization( - guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, - limit = "CACHE_SIZE") - Function resolveCached( - UnresolvedSymbol symbol, - Text _this, - @CachedContext(Language.class) Context context, - @Cached("symbol") UnresolvedSymbol cachedSymbol, - @Cached("resolveMethodOnString(context, cachedSymbol)") Function function) { - return function; - } - - @Specialization(replaces = "resolveCached") - Function resolve( - UnresolvedSymbol symbol, Text _this, @CachedContext(Language.class) Context context) { - Function function = resolveMethodOnString(context, symbol); - return throwIfNull(context, function, _this, symbol); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ArrayLengthNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ArrayLengthNode.java deleted file mode 100644 index e4e911b56b81..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ArrayLengthNode.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.interop.syntax; - -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.Constants; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.error.PanicException; - -@BuiltinMethod( - type = "Any", - name = "", - description = "Returns the length of a polyglot array.") -public class ArrayLengthNode extends Node { - private @Child InteropLibrary library = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private final BranchProfile err = BranchProfile.create(); - - public Object execute(Object _this) { - try { - return library.getArraySize(_this); - } catch (UnsupportedMessageException e) { - err.enter(); - throw new PanicException(e.getMessage(), this); - } - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ConstructorDispatchNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ConstructorDispatchNode.java deleted file mode 100644 index 70650af980bd..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/ConstructorDispatchNode.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.interop.syntax; - -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.ArityException; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; -import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.Constants; -import org.enso.interpreter.Language; -import org.enso.interpreter.node.expression.builtin.BuiltinRootNode; -import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.error.PanicException; -import org.enso.interpreter.runtime.state.Stateful; -import org.enso.interpreter.runtime.type.TypesGen; - -@NodeInfo(shortName = "", description = "Instantiates a polyglot constructor.") -public class ConstructorDispatchNode extends BuiltinRootNode { - - private ConstructorDispatchNode(Language language) { - super(language); - } - - private @Child InteropLibrary library = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private @Child HostValueToEnsoNode hostValueToEnsoNode = HostValueToEnsoNode.build(); - private final BranchProfile err = BranchProfile.create(); - - /** - * Creates a function wrapping this node. - * - * @param language the current language instance - * @return a function wrapping this node - */ - public static Function makeFunction(Language language) { - return Function.fromBuiltinRootNode( - new ConstructorDispatchNode(language), - new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE), - new ArgumentDefinition(1, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE)); - } - - /** - * Executes the node. - * - * @param frame current execution frame. - * @return the result of converting input into a string. - */ - @Override - public Stateful execute(VirtualFrame frame) { - Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments()); - Object cons = args[0]; - Object state = Function.ArgumentsHelper.getState(frame.getArguments()); - try { - Object[] arguments = TypesGen.expectArray(args[1]).getItems(); - Object res = hostValueToEnsoNode.execute(library.instantiate(cons, arguments)); - return new Stateful(state, res); - } catch (UnsupportedMessageException - | ArityException - | UnsupportedTypeException - | UnexpectedResultException e) { - err.enter(); - throw new PanicException(e.getMessage(), this); - } - } - - /** - * Returns a language-specific name for this node. - * - * @return the name of this node - */ - @Override - public String getName() { - return ""; - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/GetArrayElementNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/GetArrayElementNode.java deleted file mode 100644 index 93ff63eae0fc..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/GetArrayElementNode.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.interop.syntax; - -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.Constants; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.error.PanicException; - -@BuiltinMethod( - type = "Any", - name = "", - description = "Returns the element of a polyglot array at a given index.") -public class GetArrayElementNode extends Node { - private @Child InteropLibrary library = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private @Child HostValueToEnsoNode hostValueToEnsoNode = HostValueToEnsoNode.build(); - private final BranchProfile err = BranchProfile.create(); - - public Object execute(Object _this, long index) { - try { - return hostValueToEnsoNode.execute(library.readArrayElement(_this, index)); - } catch (UnsupportedMessageException | InvalidArrayIndexException e) { - err.enter(); - throw new PanicException(e.getMessage(), this); - } - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/MethodDispatchNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/MethodDispatchNode.java deleted file mode 100644 index fc7af7c70dc8..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/MethodDispatchNode.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.interop.syntax; - -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.*; -import com.oracle.truffle.api.nodes.NodeInfo; -import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.Constants; -import org.enso.interpreter.Language; -import org.enso.interpreter.node.callable.InvokeCallableNode; -import org.enso.interpreter.node.expression.builtin.BuiltinRootNode; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.error.PanicException; -import org.enso.interpreter.runtime.scope.ModuleScope; -import org.enso.interpreter.runtime.state.Stateful; -import org.enso.interpreter.runtime.type.TypesGen; - -@NodeInfo(shortName = "", description = "Invokes a polyglot method by name.") -@ReportPolymorphism -public abstract class MethodDispatchNode extends BuiltinRootNode { - MethodDispatchNode(Language language) { - super(language); - } - - private @Child InteropLibrary library = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private @Child HostValueToEnsoNode hostValueToEnsoNode = HostValueToEnsoNode.build(); - private final BranchProfile err = BranchProfile.create(); - - private @Child InvokeCallableNode invokeCallableNode = - InvokeCallableNode.build( - new CallArgumentInfo[] {new CallArgumentInfo()}, - InvokeCallableNode.DefaultsExecutionMode.EXECUTE, - InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED); - - /** - * Creates an instance of this node. - * - * @param language the current language instance - * @return a function wrapping this node - */ - public static MethodDispatchNode build(Language language) { - return MethodDispatchNodeGen.create(language); - } - - /** - * Executes the node. - * - * @param frame current execution frame. - * @return the result of converting input into a string. - */ - @Specialization(guards = "symbol.getScope() == cachedScope") - public Stateful run( - VirtualFrame frame, - @Bind("getSymbol(frame)") UnresolvedSymbol symbol, - @Cached("symbol.getScope()") ModuleScope cachedScope, - @Cached("buildToArray(cachedScope)") UnresolvedSymbol toArray) { - Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments()); - Object callable = args[0]; - Object state = Function.ArgumentsHelper.getState(frame.getArguments()); - Object arguments = args[2]; - Stateful casted = invokeCallableNode.execute(toArray, frame, state, new Object[] {arguments}); - try { - Object[] castedArgs = TypesGen.expectArray(casted.getValue()).getItems(); - Object res = - hostValueToEnsoNode.execute(library.invokeMember(callable, symbol.getName(), castedArgs)); - return new Stateful(casted.getState(), res); - } catch (UnsupportedMessageException - | ArityException - | UnsupportedTypeException - | UnexpectedResultException - | UnknownIdentifierException e) { - err.enter(); - throw new PanicException(e.getMessage(), this); - } - } - - @Specialization - public Stateful runUncached(VirtualFrame frame) { - UnresolvedSymbol sym = getSymbol(frame); - return run(frame, sym, sym.getScope(), buildToArray(sym.getScope())); - } - - UnresolvedSymbol buildToArray(ModuleScope scope) { - return UnresolvedSymbol.build("to_array", scope); - } - - UnresolvedSymbol getSymbol(VirtualFrame frame) { - return TypesGen.asUnresolvedSymbol( - Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]); - } - - /** - * Returns a language-specific name for this node. - * - * @return the name of this node - */ - @Override - public String getName() { - return ""; - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/PolyglotToTextNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/PolyglotToTextNode.java deleted file mode 100644 index 40c2912e221b..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/interop/syntax/PolyglotToTextNode.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.interop.syntax; - -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; -import org.enso.interpreter.Constants; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.data.text.Text; -import org.enso.interpreter.runtime.error.PanicException; - -@BuiltinMethod( - type = "Any", - name = "", - description = "Returns human-readable representation of a polyglot object.") -public class PolyglotToTextNode extends Node { - private @Child InteropLibrary library = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private @Child InteropLibrary strings = - InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH); - private final BranchProfile err = BranchProfile.create(); - - public Text execute(Object _this) { - try { - return Text.create(strings.asString(library.toDisplayString(_this))); - } catch (UnsupportedMessageException e) { - err.enter(); - throw new PanicException(e.getMessage(), this); - } - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Context.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Context.java index d565ed3e90c9..e5e16dfdce7b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Context.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Context.java @@ -74,8 +74,6 @@ public Context(Language language, String home, Env environment) { /** Perform expensive initialization logic for the context. */ public void initialize() { - this.getCompiler().initializeBuiltinsIr(); - TruffleFileSystem fs = new TruffleFileSystem(); packages = new ArrayList<>(); diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java index 349484be9629..e683a99292e7 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Builtins.java @@ -3,6 +3,8 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Objects; + +import com.oracle.truffle.api.CompilerDirectives; import org.enso.compiler.Passes; import org.enso.compiler.context.FreshNameSupply; import org.enso.compiler.exception.CompilerError; @@ -179,7 +181,8 @@ public boolean isIrInitialized() { * @param freshNameSupply the compiler's fresh name supply * @param passes the passes manager for the compiler */ - public void initializedBuiltinsIr(FreshNameSupply freshNameSupply, Passes passes) { + @CompilerDirectives.TruffleBoundary + public void initializeBuiltinsIr(FreshNameSupply freshNameSupply, Passes passes) { try { var builtinsModuleBytes = Objects.requireNonNull( diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java index c902e98232fe..b299f31be6d2 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Error.java @@ -5,6 +5,7 @@ import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; import org.enso.interpreter.runtime.callable.atom.Atom; import org.enso.interpreter.runtime.callable.atom.AtomConstructor; +import org.enso.interpreter.runtime.data.Array; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.scope.ModuleScope; @@ -20,6 +21,8 @@ public class Error { private final AtomConstructor moduleNotInPackageError; private final AtomConstructor arithmeticError; private final AtomConstructor invalidArrayIndexError; + private final AtomConstructor arityError; + private final AtomConstructor unsupportedArgumentsError; private final Atom arithmeticErrorShiftTooBig; private final Atom arithmeticErrorDivideByZero; @@ -78,6 +81,17 @@ public Error(Language language, ModuleScope scope) { new ArgumentDefinition(0, "array", ArgumentDefinition.ExecutionMode.EXECUTE), new ArgumentDefinition(1, "index", ArgumentDefinition.ExecutionMode.EXECUTE)); + arityError = + new AtomConstructor("Arity_Error", scope) + .initializeFields( + new ArgumentDefinition(0, "expected", ArgumentDefinition.ExecutionMode.EXECUTE), + new ArgumentDefinition(0, "actual", ArgumentDefinition.ExecutionMode.EXECUTE)); + + unsupportedArgumentsError = + new AtomConstructor("Unsupported_Argument_Types", scope) + .initializeFields( + new ArgumentDefinition(0, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE)); + scope.registerConstructor(syntaxError); scope.registerConstructor(typeError); scope.registerConstructor(compileError); @@ -88,6 +102,9 @@ public Error(Language language, ModuleScope scope) { scope.registerConstructor(moduleNotInPackageError); scope.registerConstructor(arithmeticError); scope.registerConstructor(invalidArrayIndexError); + scope.registerConstructor(typeError); + scope.registerConstructor(arityError); + scope.registerConstructor(unsupportedArgumentsError); } /** @return the builtin {@code Syntax_Error} atom constructor. */ @@ -180,4 +197,22 @@ public Atom getDivideByZeroError() { public Atom makeInvalidArrayIndexError(Object array, Object index) { return invalidArrayIndexError.newInstance(array, index); } + + /** + * @param expected the expected arity + * @param actual the actual arity + * @return an error informing about the arity being mismatched + */ + public Atom makeArityError(long expected, long actual) { + return arityError.newInstance(expected, actual); + } + + /** + * @param args an array containing objects + * @return an error informing about the particular assortment of arguments not being valid for a + * given method callp + */ + public Atom makeUnsupportedArgumentsError(Object[] args) { + return unsupportedArgumentsError.newInstance(new Array(args)); + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Polyglot.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Polyglot.java index 84e58eb96424..136d4635e87f 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Polyglot.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Polyglot.java @@ -1,28 +1,14 @@ package org.enso.interpreter.runtime.builtin; -import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.Truffle; import org.enso.interpreter.Language; import org.enso.interpreter.node.expression.builtin.interop.generic.*; -import org.enso.interpreter.node.expression.builtin.interop.syntax.*; -import org.enso.interpreter.runtime.callable.UnresolvedSymbol; -import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; -import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo; import org.enso.interpreter.runtime.callable.atom.AtomConstructor; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.callable.function.FunctionSchema; import org.enso.interpreter.runtime.scope.ModuleScope; /** A container class for all Polyglot-related stdlib builtins. */ public class Polyglot { private final AtomConstructor polyglot; - private final RootCallTarget interopDispatchRoot; - private final FunctionSchema interopDispatchSchema; - private final Function newInstanceFunction; - private final Function polyglotArrayLengthFunction; - private final Function polyglotArrayAtFunction; - private final Function polyglotToTextFunction; /** * Creates and registers all polyglot-related functions and types. @@ -32,35 +18,9 @@ public class Polyglot { */ public Polyglot(Language language, ModuleScope scope) { this.polyglot = new AtomConstructor("Polyglot", scope).initializeFields(); - - // Note [Syntactic Functions] - interopDispatchRoot = Truffle.getRuntime().createCallTarget(MethodDispatchNode.build(language)); - interopDispatchSchema = - new FunctionSchema( - FunctionSchema.CallerFrameAccess.NONE, - new ArgumentDefinition[] { - new ArgumentDefinition(1, "this", ArgumentDefinition.ExecutionMode.EXECUTE), - new ArgumentDefinition(2, "method_name", ArgumentDefinition.ExecutionMode.EXECUTE), - new ArgumentDefinition(3, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE) - }, - new boolean[] {false, true, false}, - new CallArgumentInfo[0]); - newInstanceFunction = ConstructorDispatchNode.makeFunction(language); - polyglotArrayAtFunction = GetArrayElementMethodGen.makeFunction(language); - polyglotArrayLengthFunction = ArrayLengthMethodGen.makeFunction(language); - polyglotToTextFunction = PolyglotToTextMethodGen.makeFunction(language); - createPolyglot(language, scope); } - /* Note [Syntactic Functions] - * ~~~~~~~~~~~~~~~~~~~~~~~~~~ - * Certain functions in this module (ones that are not being directly registered in the scope) - * are not parts of the standard library. Instead, they are used by the method dispatch system - * to call into functionality of polyglot objects. As such, they are represented as Enso-level - * functions, but they are not directly accessible through the standard library. - */ - private void createPolyglot(Language language, ModuleScope scope) { scope.registerConstructor(polyglot); scope.registerMethod(polyglot, "execute", ExecuteMethodGen.makeFunction(language)); @@ -71,42 +31,8 @@ private void createPolyglot(Language language, ModuleScope scope) { scope.registerMethod(polyglot, "get_members", GetMembersMethodGen.makeFunction(language)); } - /* - * Builds a function dispatching to a polyglot method call. - * - * @param method the name and scope of the method this function will dispatch to. - * @return a function calling {@code method} with given arguments. - */ - public Function buildPolyglotMethodDispatch(UnresolvedSymbol method) { - Object[] preAppliedArr = new Object[] {null, method, null}; - return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null); - } - /** @return the atom constructor for polyglot */ public AtomConstructor getPolyglot() { return polyglot; } - - /** @return a function taking a polyglot array and returning its length. */ - public Function getPolyglotArrayLengthFunction() { - return polyglotArrayLengthFunction; - } - - /** - * @return a function taking a polyglot array and an index and accessing the item at the given - * index. - */ - public Function getPolyglotArrayAtFunction() { - return polyglotArrayAtFunction; - } - - /** @return a function taking a polyglot object and displaying it as a human-readable string. */ - public Function getPolyglotToTextFunction() { - return polyglotToTextFunction; - } - - /** @return a function executing a constructor with given arguments. */ - public Function getConstructorDispatch() { - return newInstanceFunction; - } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java index 606bf8ce3bf7..98b2a0dec841 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/Atom.java @@ -1,8 +1,6 @@ package org.enso.interpreter.runtime.callable.atom; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.Specialization; @@ -12,12 +10,12 @@ import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.UnexpectedResultException; import org.enso.interpreter.Language; -import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode; import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.data.Array; import org.enso.interpreter.runtime.data.text.Text; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import org.enso.interpreter.runtime.type.TypesGen; import java.util.Arrays; @@ -27,8 +25,9 @@ /** A runtime representation of an Atom in Enso. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public class Atom implements TruffleObject { - private final AtomConstructor constructor; + final AtomConstructor constructor; private final Object[] fields; /** @@ -176,4 +175,48 @@ Text toDisplayString(boolean allowSideEffects, @CachedLibrary("this") InteropLib boolean isNull(@CachedContext(Language.class) Context ctx) { return this.getConstructor() == ctx.getBuiltins().nothing(); } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, AtomConstructor cons, UnresolvedSymbol symbol) { + return symbol.resolveFor(cons, context.getBuiltins().any()); + } + + @Specialization( + guards = { + "!context.isCachingDisabled()", + "cachedSymbol == symbol", + "_this.constructor == cachedConstructor", + "function != null" + }, + limit = "CACHE_SIZE") + static Function resolveCached( + Atom _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("_this.constructor") AtomConstructor cachedConstructor, + @Cached("doResolve(context, cachedConstructor, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Atom _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, _this.constructor, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java index bc8513d16440..2fe044feaa80 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/atom/AtomConstructor.java @@ -3,26 +3,34 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.RootNode; +import org.enso.interpreter.Language; import org.enso.interpreter.node.ExpressionNode; import org.enso.interpreter.node.callable.argument.ReadArgumentNode; import org.enso.interpreter.node.expression.atom.GetFieldNode; import org.enso.interpreter.node.expression.atom.InstantiateNode; import org.enso.interpreter.node.expression.atom.QualifiedAccessorNode; import org.enso.interpreter.node.expression.builtin.InstantiateAtomNode; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.callable.function.FunctionSchema; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.pkg.QualifiedName; /** A representation of an Atom constructor. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public final class AtomConstructor implements TruffleObject { private final String name; @@ -212,4 +220,52 @@ public QualifiedName getQualifiedName() { public ArgumentDefinition[] getFields() { return constructorFunction.getSchema().getArgumentInfos(); } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve( + Context context, AtomConstructor cons, UnresolvedSymbol symbol) { + return symbol.resolveFor(cons, context.getBuiltins().any()); + } + + @Specialization( + guards = { + "!context.isCachingDisabled()", + "cachedSymbol == symbol", + "_this == cachedConstructor", + "function != null" + }, + limit = "CACHE_SIZE") + static Function resolveCached( + AtomConstructor _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("_this") AtomConstructor cachedConstructor, + @Cached("doResolve(context, cachedConstructor, cachedSymbol)") + Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + AtomConstructor _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, _this, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java index d7d33713d525..98ba9b319326 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/callable/function/Function.java @@ -24,8 +24,10 @@ import org.enso.interpreter.node.expression.builtin.BuiltinRootNode; import org.enso.interpreter.runtime.Context; import org.enso.interpreter.runtime.callable.CallerInfo; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition; import org.enso.interpreter.runtime.callable.argument.Thunk; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import org.enso.interpreter.runtime.state.data.EmptyMap; import org.enso.interpreter.runtime.data.Array; import org.enso.interpreter.runtime.type.Types; @@ -33,6 +35,7 @@ /** A runtime representation of a function object in Enso. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public final class Function implements TruffleObject { private final RootCallTarget callTarget; private final MaterializedFrame scope; @@ -359,4 +362,43 @@ public static MaterializedFrame getLocalScope(Object[] arguments) { return (MaterializedFrame) arguments[0]; } } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + return symbol.resolveFor(context.getBuiltins().function(), context.getBuiltins().any()); + } + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Function _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Function _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java index e7c13ec3bf4e..8a1e66bb0878 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/Array.java @@ -1,13 +1,25 @@ package org.enso.interpreter.runtime.data; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; + +import java.util.Arrays; /** A primitve boxed array type for use in the runtime. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public class Array implements TruffleObject { private final Object[] items; @@ -99,4 +111,49 @@ boolean isArrayElementModifiable(long index) { boolean isArrayElementInsertable(long index) { return false; } + + @Override + public String toString() { + return Arrays.toString(items); + } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + return symbol.resolveFor( + context.getBuiltins().mutable().array(), context.getBuiltins().any()); + } + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Array _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Array _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java index 2cba37b47a3d..527857ab5d0c 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/data/text/Text.java @@ -1,17 +1,27 @@ package org.enso.interpreter.runtime.data.text; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Number; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** The main runtime type for Enso's Text. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public class Text implements TruffleObject { private volatile Object contents; private volatile boolean isFlat; @@ -125,4 +135,43 @@ public String toString() { return ToJavaStringNode.inplaceFlatten(this); } } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + return symbol.resolveFor(context.getBuiltins().text().getText(), context.getBuiltins().any()); + } + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Text _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Text _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/DataflowError.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/DataflowError.java index e42d3478b54c..ef6e87e6fe7b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/DataflowError.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/DataflowError.java @@ -1,6 +1,10 @@ package org.enso.interpreter.runtime.error; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleException; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.library.CachedLibrary; @@ -8,6 +12,12 @@ import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; + import javax.xml.crypto.Data; /** @@ -17,13 +27,15 @@ * they are handled. Another term used to describe these errors is "broken values". */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public class DataflowError extends RuntimeException implements TruffleObject, TruffleException { private final Object payload; private final Node location; - /** Construct a new dataflow error with the default stack trace. + /** + * Construct a new dataflow error with the default stack trace. * - * The default stack trace has the throwing location as the top element of the stack trace. + *

The default stack trace has the throwing location as the top element of the stack trace. * * @param payload the user-provided value carried by the error * @param location the node in which the error was created @@ -35,10 +47,11 @@ public static DataflowError withDefaultTrace(Object payload, Node location) { return error; } - /** Construct a new dataflow error with the provided stack trace. + /** + * Construct a new dataflow error with the provided stack trace. * - * This is useful for when the dataflow error is created from the recovery of a panic, and we want - * to point to the original location of the panic. + *

This is useful for when the dataflow error is created from the recovery of a panic, and we + * want to point to the original location of the panic. * * @param payload the user-provided value carried by the error * @param location the node in which the error was located @@ -91,4 +104,9 @@ public String toDisplayString( return "Error"; } } + + @ExportMessage + boolean hasSpecialDispatch() { + return true; + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/PanicSentinel.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/PanicSentinel.java index 8fca2ec4d6ee..ec2acddc247e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/PanicSentinel.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/error/PanicSentinel.java @@ -1,7 +1,10 @@ package org.enso.interpreter.runtime.error; import com.oracle.truffle.api.TruffleException; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; /** * A sentinel value used to trace the propagation of panics through the program. @@ -9,6 +12,7 @@ *

This tracing is enabled by the active intervention of the runtime instrumentation, and does * not function in textual mode. */ +@ExportLibrary(MethodDispatchLibrary.class) public class PanicSentinel extends RuntimeException implements TruffleException { private final PanicException panic; private final Node location; @@ -57,4 +61,9 @@ public Object getExceptionObject() { public Throwable fillInStackTrace() { return this; } + + @ExportMessage + boolean hasSpecialDispatch() { + return true; + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultBooleanExports.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultBooleanExports.java new file mode 100644 index 000000000000..b7281c7d4bea --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultBooleanExports.java @@ -0,0 +1,110 @@ +package org.enso.interpreter.runtime.library.dispatch; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Bool; +import org.enso.interpreter.runtime.builtin.Number; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.atom.AtomConstructor; +import org.enso.interpreter.runtime.callable.function.Function; + +@ExportLibrary(value = MethodDispatchLibrary.class, receiverType = Boolean.class) +public class DefaultBooleanExports { + @ExportMessage + static boolean hasFunctionalDispatch(Boolean receiver) { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + @CompilerDirectives.TruffleBoundary + static Function resolveMethodOnPrimBoolean(Context context, UnresolvedSymbol symbol) { + Bool bool = context.getBuiltins().bool(); + if (symbol.resolveFor(bool.getFalse()) != null) { + return null; + } + if (symbol.resolveFor(bool.getTrue()) != null) { + return null; + } + return symbol.resolveFor(bool.getBool(), context.getBuiltins().any()); + } + + @CompilerDirectives.TruffleBoundary + static Function resolveMethodOnBool(Context context, boolean self, UnresolvedSymbol symbol) { + Bool bool = context.getBuiltins().bool(); + AtomConstructor cons = self ? bool.getTrue() : bool.getFalse(); + return symbol.resolveFor(cons, bool.getBool(), context.getBuiltins().any()); + } + + static final int CACHE_SIZE = 10; + + static boolean unbox(Boolean b) { + return b; + } + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Boolean _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("resolveMethodOnPrimBoolean(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization( + guards = { + "!context.isCachingDisabled()", + "cachedSymbol == symbol", + "unbox(_this)", + "function != null" + }, + limit = "CACHE_SIZE", + replaces = "resolveCached") + static Function resolveTrueCached( + Boolean _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("resolveMethodOnBool(context, _this, cachedSymbol)") Function function) { + return function; + } + + @Specialization( + guards = { + "!context.isCachingDisabled()", + "cachedSymbol == symbol", + "!unbox(_this)", + "function != null" + }, + limit = "CACHE_SIZE", + replaces = "resolveCached") + static Function resolveFalseCached( + Boolean _this, + UnresolvedSymbol symbol, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @CachedContext(Language.class) Context context, + @Cached("resolveMethodOnBool(context, _this, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = {"resolveTrueCached", "resolveFalseCached"}) + static Function resolve( + Boolean _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = resolveMethodOnBool(context, _this, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultDoubleExports.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultDoubleExports.java new file mode 100644 index 000000000000..f610eb3c7661 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultDoubleExports.java @@ -0,0 +1,56 @@ +package org.enso.interpreter.runtime.library.dispatch; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Number; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; + +@ExportLibrary(value = MethodDispatchLibrary.class, receiverType = Double.class) +public class DefaultDoubleExports { + @ExportMessage + static boolean hasFunctionalDispatch(Double receiver) { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + Number number = context.getBuiltins().number(); + return symbol.resolveFor( + number.getDecimal(), number.getNumber(), context.getBuiltins().any()); + } + + static final int CACHE_SIZE = 10; + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Double _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Double _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultLongExports.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultLongExports.java new file mode 100644 index 000000000000..41061cbd1321 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/DefaultLongExports.java @@ -0,0 +1,59 @@ +package org.enso.interpreter.runtime.library.dispatch; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Number; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; + +@ExportLibrary(value = MethodDispatchLibrary.class, receiverType = Long.class) +public class DefaultLongExports { + @ExportMessage + static boolean hasFunctionalDispatch(Long receiver) { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + Number number = context.getBuiltins().number(); + return symbol.resolveFor( + number.getSmallInteger(), + number.getInteger(), + number.getNumber(), + context.getBuiltins().any()); + } + + static final int CACHE_SIZE = 10; + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + Long _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + Long _this, UnresolvedSymbol symbol, @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/MethodDispatchLibrary.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/MethodDispatchLibrary.java new file mode 100644 index 000000000000..e221530e3c8a --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/library/dispatch/MethodDispatchLibrary.java @@ -0,0 +1,78 @@ +package org.enso.interpreter.runtime.library.dispatch; + +import com.oracle.truffle.api.library.GenerateLibrary; +import com.oracle.truffle.api.library.Library; +import com.oracle.truffle.api.library.LibraryFactory; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; + +/** + * A library used for equipping data structures with Enso-style (fully unapplied) method dispatch. + * This is used for all method calls in the language. + */ +@GenerateLibrary +@GenerateLibrary.DefaultExport(DefaultLongExports.class) +@GenerateLibrary.DefaultExport(DefaultDoubleExports.class) +@GenerateLibrary.DefaultExport(DefaultBooleanExports.class) +public abstract class MethodDispatchLibrary extends Library { + + /** + * Returns a resolved library factory for this library. + * + * @return a library factory instance + */ + public static LibraryFactory getFactory() { + return FACTORY; + } + + /** + * Returns the uncached instance of this library. + * + * @return the uncached instance of this library + */ + public static MethodDispatchLibrary getUncached() { + return FACTORY.getUncached(); + } + + /** An exception thrown when the library cannot lookup the method definition. */ + public static class NoSuchMethodException extends Exception {} + + private static final LibraryFactory FACTORY = + LibraryFactory.resolve(MethodDispatchLibrary.class); + + /** + * Checks if the receiver supports Enso-style method dispatch + * + * @param receiver the receiver to check + * @return whether the receiver supports method dispatch through this library + */ + @GenerateLibrary.Abstract(ifExported = {"getFunctionalDispatch"}) + public boolean hasFunctionalDispatch(Object receiver) { + return false; + } + + /** + * Denotes an object that has special dispatch semantics, that must be handled specially in the + * method dispatch logic. + * + * @param receiver the receiver to check + * @return whether the receiver has special dispatch semantics + */ + public boolean hasSpecialDispatch(Object receiver) { + return false; + } + + /** + * Looks up the method definition for the given receiver and symbol + * + * @param receiver the method call receiver + * @param symbol the symbol being dispatched + * @return the corresponding function definition + * @throws NoSuchMethodException if the function definition could not be found + */ + @GenerateLibrary.Abstract(ifExported = {"hasFunctionalDispatch"}) + public Function getFunctionalDispatch(Object receiver, UnresolvedSymbol symbol) + throws NoSuchMethodException { + throw new NoSuchMethodException(); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java index 94962531baef..88bddcedd82b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/number/EnsoBigInteger.java @@ -1,15 +1,26 @@ package org.enso.interpreter.runtime.number; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.CachedContext; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import org.enso.interpreter.Language; +import org.enso.interpreter.runtime.Context; +import org.enso.interpreter.runtime.builtin.Number; +import org.enso.interpreter.runtime.callable.UnresolvedSymbol; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary; + import java.math.BigInteger; /** Internal wrapper for a {@link BigInteger}. */ @ExportLibrary(InteropLibrary.class) +@ExportLibrary(MethodDispatchLibrary.class) public class EnsoBigInteger implements TruffleObject { private final BigInteger value; @@ -37,4 +48,50 @@ public String toString() { String toDisplayString(boolean allowSideEffects) { return value.toString(); } + + @ExportMessage + boolean hasFunctionalDispatch() { + return true; + } + + @ExportMessage + static class GetFunctionalDispatch { + + static final int CACHE_SIZE = 10; + + @CompilerDirectives.TruffleBoundary + static Function doResolve(Context context, UnresolvedSymbol symbol) { + Number number = context.getBuiltins().number(); + return symbol.resolveFor( + number.getBigInteger(), + number.getInteger(), + number.getNumber(), + context.getBuiltins().any()); + } + + @Specialization( + guards = {"!context.isCachingDisabled()", "cachedSymbol == symbol", "function != null"}, + limit = "CACHE_SIZE") + static Function resolveCached( + EnsoBigInteger _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context, + @Cached("symbol") UnresolvedSymbol cachedSymbol, + @Cached("doResolve(context, cachedSymbol)") Function function) { + return function; + } + + @Specialization(replaces = "resolveCached") + static Function resolve( + EnsoBigInteger _this, + UnresolvedSymbol symbol, + @CachedContext(Language.class) Context context) + throws MethodDispatchLibrary.NoSuchMethodException { + Function function = doResolve(context, symbol); + if (function == null) { + throw new MethodDispatchLibrary.NoSuchMethodException(); + } + return function; + } + } } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java index c1ff5d7ffedb..d5e249ba38d3 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/type/Types.java @@ -1,7 +1,5 @@ package org.enso.interpreter.runtime.type; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.TypeSystem; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.UnsupportedTypeException; @@ -49,18 +47,6 @@ }) public class Types { - /** - * An implicit conversion between {@code int} and {@code long} for Enso programs. - * - * @param value the value to convert - * @return {@code value} as the appropriate type - */ - @ImplicitCast - @CompilerDirectives.TruffleBoundary - public static long castLong(int value) { - return value; - } - /** * A simple pair type * @@ -114,9 +100,7 @@ public static void extractArguments(Object[] arguments) throws ArityException { * @return the string representation of object's type. */ public static String getName(Object value) { - if (TypesGen.isLong(value) - || TypesGen.isImplicitLong(value) - || TypesGen.isEnsoBigInteger(value)) { + if (TypesGen.isLong(value) || TypesGen.isEnsoBigInteger(value)) { return Constants.INTEGER; } else if (TypesGen.isDouble(value)) { return Constants.DECIMAL; diff --git a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala index 69974a195e75..5e3099549b78 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala @@ -44,10 +44,20 @@ class Compiler(val context: Context, private val builtins: Builtins) { */ def initializeBuiltinsIr(): Unit = { if (!builtins.isIrInitialized) { - builtins.initializedBuiltinsIr(freshNameSupply, passes) + builtins.initializeBuiltinsIr(freshNameSupply, passes) } } + /** Runs the import resolver on the given module. + * + * @param module the entry module for import resolution + * @return the list of modules imported by `module` + */ + def runImportsResolution(module: Module): List[Module] = { + initializeBuiltinsIr() + importResolver.mapImports(module) + } + /** Processes the provided language sources, registering any bindings in the * given scope. * @@ -56,6 +66,7 @@ class Compiler(val context: Context, private val builtins: Builtins) { * executable functionality in the module corresponding to `source`. */ def run(module: Module): Unit = { + initializeBuiltinsIr() parseModule(module) val importedModules = importResolver.mapImports(module) val requiredModules = diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala index 401b9f9ea662..73bf0a15de84 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala @@ -79,10 +79,15 @@ case object ExpressionAnnotations extends IRPass { doExpression(arg.value) .updateMetadata(this -->> Annotations(Seq(ann))) case realFun :: args => - val recurFun = doExpression(realFun.value) + val recurFun = doExpression(realFun.value) + val (finalFun, preArgs) = recurFun match { + case IR.Application.Prefix(nextFun, moreArgs, _, _, _, _) => + (nextFun, moreArgs) + case _ => (recurFun, List()) + } val recurArgs = args.map(_.mapExpressions(doExpression)) app - .copy(function = recurFun, arguments = recurArgs) + .copy(function = finalFun, arguments = preArgs ++ recurArgs) .updateMetadata(this -->> Annotations(Seq(ann))) } } else { diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala index 19b034a08683..9b0ec38ff8e1 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala @@ -15,7 +15,6 @@ import org.enso.compiler.pass.analyse.{ CachePreferenceAnalysis, GatherDiagnostics } -import org.enso.compiler.phase.ImportResolver import org.enso.interpreter.instrument.{CacheInvalidation, InstrumentFrame} import org.enso.interpreter.instrument.execution.{ LocationResolver, @@ -75,8 +74,8 @@ class EnsureCompiledJob(protected val files: Iterable[File]) } val moduleCompilationStatus = modules.flatMap { module => val importedModules = - new ImportResolver(ctx.executionService.getContext.getCompiler) - .mapImports(module) + ctx.executionService.getContext.getCompiler + .runImportsResolution(module) .filter(_.getName != module.getName) ensureCompiledModule(module) +: ensureCompiledImports(importedModules) } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/ExpressionErrorsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/ExpressionErrorsTest.scala index 6bdddec368b3..bc08d5cfb281 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/ExpressionErrorsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/ExpressionErrorsTest.scala @@ -84,7 +84,7 @@ class ExpressionErrorsTest } def receive: Option[Api.Response] = { - Option(messageQueue.poll(3, TimeUnit.SECONDS)) + Option(messageQueue.poll(5, TimeUnit.SECONDS)) } def receive(n: Int): List[Api.Response] = { diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala index bf4d9c8893b3..e413768a9769 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/RuntimeServerTest.scala @@ -107,7 +107,7 @@ class RuntimeServerTest } def receive: Option[Api.Response] = { - Option(messageQueue.poll(5, TimeUnit.SECONDS)) + Option(messageQueue.poll(10, TimeUnit.SECONDS)) } def receive(n: Int): List[Api.Response] = { diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/SuggestionUpdatesTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/SuggestionUpdatesTest.scala index 58cce460fefe..52c10b2093b7 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/SuggestionUpdatesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/instrument/SuggestionUpdatesTest.scala @@ -87,7 +87,7 @@ class SuggestionUpdatesTest } def receive: Option[Api.Response] = { - Option(messageQueue.poll(3, TimeUnit.SECONDS)) + Option(messageQueue.poll(6, TimeUnit.SECONDS)) } def receive(n: Int): List[Api.Response] = { diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/JavaInteropTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/JavaInteropTest.scala index 7f8f7769b622..5518899e8f7f 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/JavaInteropTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/JavaInteropTest.scala @@ -16,7 +16,7 @@ class JavaInteropTest extends InterpreterTest { |polyglot java import org.enso.example.TestClass |from Builtins import all | - |main = TestClass.add (Array.new_2 1 2) + |main = TestClass.add 1 2 |""".stripMargin eval(code) shouldEqual 3 @@ -29,8 +29,8 @@ class JavaInteropTest extends InterpreterTest { |from Builtins import all | |main = - | instance = TestClass.new (Array.new_1 (x -> x * 2)) - | instance.callFunctionAndIncrement (Array.new_1 10) + | instance = TestClass.new (x -> x * 2) + | instance.callFunctionAndIncrement 10 |""".stripMargin eval(code) shouldEqual 21 } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/PanicsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/PanicsTest.scala index 056133cf1db6..a7f3b43c2214 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/PanicsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/PanicsTest.scala @@ -55,13 +55,13 @@ class PanicsTest extends InterpreterTest { |polyglot java import java.lang.Long | |main = - | caught = Panic.recover (Long.parseLong (Array.new_1 "oops")) + | caught = Panic.recover (Long.parseLong "oops") | IO.println caught | cause = caught.catch <| case _ of | Polyglot_Error err -> err | _ -> "fail" | IO.println cause - | message = cause.getMessage (Array.new 0) + | message = cause.getMessage | IO.println message |""".stripMargin eval(code) diff --git a/test/Benchmarks/src/Collections.enso b/test/Benchmarks/src/Collections.enso index d2b63a3433a7..704860641a23 100644 --- a/test/Benchmarks/src/Collections.enso +++ b/test/Benchmarks/src/Collections.enso @@ -19,8 +19,8 @@ sum_list_meta list = sum_recur n = if n == 0 then 0 else 1 + here.sum_recur n-1 build_map size = - rand = Random.new [].to_array - 0.up_to size . fold Map.empty (m -> i -> m.insert (rand.nextInt [10000]) i) + rand = Random.new + 0.up_to size . fold Map.empty (m -> i -> m.insert (rand.nextInt 10000) i) main = mil = 1000000 diff --git a/test/Benchmarks/src/Main.enso b/test/Benchmarks/src/Main.enso index 0f2c4319de63..635228a90c1b 100644 --- a/test/Benchmarks/src/Main.enso +++ b/test/Benchmarks/src/Main.enso @@ -32,7 +32,7 @@ sum_tco_eval = sumTo -> sum_tco_java = sum_to -> summator = acc -> current -> if current == 0 then acc else - @Tail_Call summator (Long.sum [acc, current]) (current - 1) + @Tail_Call summator (Long.sum acc current) (current - 1) res = summator 0 sum_to res diff --git a/test/Benchmarks/src/Text.enso b/test/Benchmarks/src/Text.enso index 978fcf5812d1..83e72f905f6b 100644 --- a/test/Benchmarks/src/Text.enso +++ b/test/Benchmarks/src/Text.enso @@ -10,9 +10,9 @@ build_long n = res build_long_bldr n = - bldr = StringBuilder.new [].to_array - 1.up_to n . each n-> bldr.append [n] - res = bldr.toString [] + bldr = StringBuilder.new + 1.up_to n . each (bldr.append _) + res = bldr.toString res main = diff --git a/test/Benchmarks/src/Vector.enso b/test/Benchmarks/src/Vector.enso index 62e96a169b77..672f200b0c52 100644 --- a/test/Benchmarks/src/Vector.enso +++ b/test/Benchmarks/src/Vector.enso @@ -18,22 +18,22 @@ make_sorted_ascending_vec n = 0.up_to n+1 . to_vector make_partially_sorted_vec : Integer -> Base.Vector.Vector make_partially_sorted_vec n = - random_gen = Random.new [n].to_array + random_gen = Random.new n direction = Ref.new Sort_Order.Ascending last_num = Ref.new 0 run_length = Ref.new 0 Base.Vector.fill n <| case (Ref.get run_length) == 0 of True -> - new_direction = if (random_gen.nextDouble []) > 0 then Sort_Order.Ascending else + new_direction = if random_gen.nextDouble > 0 then Sort_Order.Ascending else Sort_Order.Descending Ref.put direction new_direction - Ref.put run_length (((random_gen.nextLong []) % (n / 10).floor) - 1) - num = random_gen.nextInt [] + Ref.put run_length ((random_gen.nextLong % (n / 10).floor) - 1) + num = random_gen.nextInt Ref.put last_num num num False -> - change = ((random_gen.nextInt []).abs) % n + change = random_gen.nextInt.abs % n num = case Ref.get direction of Sort_Order.Ascending -> num = (Ref.get last_num) + change @@ -48,8 +48,8 @@ make_partially_sorted_vec n = make_random_vec : Integer -> Base.Vector.Vector make_random_vec n = - random_gen = Random.new [n].to_array - Base.Vector.fill n (random_gen.nextLong []) + random_gen = Random.new n + Base.Vector.fill n random_gen.nextLong diff --git a/test/Tests/src/Network/Http_Spec.enso b/test/Tests/src/Network/Http_Spec.enso index 95a5451aa010..cfc2374b0564 100644 --- a/test/Tests/src/Network/Http_Spec.enso +++ b/test/Tests/src/Network/Http_Spec.enso @@ -18,7 +18,7 @@ polyglot java import java.lang.System polyglot java import java.util.Objects spec = - is_ci = Objects.equals ["true", System.getenv ["CI"]] + is_ci = System.getenv "CI" == "true" if is_ci then here.spec_impl else Nothing spec_impl = diff --git a/test/Tests/src/Semantic/Case_Spec.enso b/test/Tests/src/Semantic/Case_Spec.enso index 05869f378bc5..093c5566c20d 100644 --- a/test/Tests/src/Semantic/Case_Spec.enso +++ b/test/Tests/src/Semantic/Case_Spec.enso @@ -66,7 +66,7 @@ spec = Test.group "Pattern Matches" <| Array -> Nothing _ -> Test.fail "Expected the Array constructor to match." Test.specify "should be able to match on the Polyglot type" <| - random_gen = Random.new [].to_array + random_gen = Random.new case random_gen of Polyglot -> Nothing _ -> Test.fail "Expected a polyglot object to match." diff --git a/test/Tests/src/Semantic/Java_Interop_Spec.enso b/test/Tests/src/Semantic/Java_Interop_Spec.enso index 3e1cc5a2f0b1..705393cc5250 100644 --- a/test/Tests/src/Semantic/Java_Interop_Spec.enso +++ b/test/Tests/src/Semantic/Java_Interop_Spec.enso @@ -10,22 +10,20 @@ polyglot java import java.lang.StringBuilder as Java_String_Builder spec = Test.group "Java FFI" <| Test.specify "should call methods imported from Java" <| - Long.sum [1, 2] . should_equal 3 + Long.sum 1 2 . should_equal 3 - ## TODO - https://github.com/enso-org/enso/issues/1163 - Test.specify "should call constructors imported from Java" pending=True <| - list = ArrayList.new [] + Test.specify "should call constructors imported from Java" <| + list = ArrayList.new list.add 432 - list.get [0] . should_equal 432 + list.get 0 . should_equal 432 Test.specify "should auto-convert numeric types across the polyglot boundary" <| - (Float.valueOf ["123.3"] + 5).should_equal 128.3 epsilon=0.0001 - (Integer.sum [1, 2] + 3) . should_equal 6 + (Float.valueOf "123.3" + 5).should_equal 128.3 epsilon=0.0001 + (Integer.sum 1 2 + 3) . should_equal 6 Test.specify "should auto-convert strings across the polyglot boundary" <| - (String.format ["%s bar %s", "baz", "quux"] + " foo").should_equal "baz bar quux foo" + (String.format "%s bar %s" "baz" "quux" + " foo").should_equal "baz bar quux foo" Test.specify "should support Java import renaming" <| - builder = Java_String_Builder.new [].to_array - builder.append ["foo"] - builder.append ["bar"] - str = builder.toString [] + builder = Java_String_Builder.new + builder.append "foo" + builder.append "bar" + str = builder.toString str.should_equal "foobar" diff --git a/test/Tests/src/Semantic/Meta_Spec.enso b/test/Tests/src/Semantic/Meta_Spec.enso index 15d4627a0060..24beac6e2c38 100644 --- a/test/Tests/src/Semantic/Meta_Spec.enso +++ b/test/Tests/src/Semantic/Meta_Spec.enso @@ -53,7 +53,7 @@ spec = Test.group "Meta-Value Manipulation" <| 1.0.is_an Integer . should_be_false 1.0.is_a Text . should_be_false - random_gen = Random.new [].to_array + random_gen = Random.new Meta.is_a random_gen Polyglot . should_be_true Meta.is_an random_gen Integer . should_be_false