Don't add module's builtins to the scope of a builtin type (#3791)

It appears that we were always adding builtin methods to the scope of the module and the builtin type that shared the same name.
This resulted in some methods being accidentally available even though they shouldn't.

This change treats differently builtins of types and modules and introduces auto-registration feature for builtins.
By default all builtin methods are registered with a type, unless explicitly defined in the annotation property.
Builtin methods that are auto-registered do not have to be explicitly defined and are registered with the underlying type.
Registration correctly infers the right type, depending whether we deal with static or instance methods.

Builtin methods that are not auto-registered have to be explicitly defined **always**. Modules' builtin methods are the prime example.

# Important Notes
Builtins now carry information whether they are static or not (inferred from the lack of `self` parameter).
They also carry a `autoRegister` property to determine if a builtin method should be automatically registered with the type.
This commit is contained in:
Hubert Plociniczak 2022-11-16 11:23:52 +01:00 committed by GitHub
parent 88e40479d1
commit 7b0759f8b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
106 changed files with 633 additions and 359 deletions

View File

@ -431,6 +431,7 @@
- [Distinguish static and instance methods][3740]
- [By-type pattern matching][3742]
- [Fix performance of method calls on polyglot arrays][3781]
- [Improved support for static and non-static builtins][3791]
- [Missing foreign language generates proper Enso error][3798]
- [Made Vector performance to be on par with Array][3811]
- [Introduced IO Permission Contexts][3828]
@ -494,6 +495,7 @@
[3764]: https://github.com/enso-org/enso/pull/3764
[3742]: https://github.com/enso-org/enso/pull/3742
[3781]: https://github.com/enso-org/enso/pull/3781
[3791]: https://github.com/enso-org/enso/pull/3791
[3798]: https://github.com/enso-org/enso/pull/3798
[3811]: https://github.com/enso-org/enso/pull/3811
[3828]: https://github.com/enso-org/enso/pull/3828

View File

@ -17,7 +17,7 @@ type Any
Arguments:
- handler: The function to call on this if it is an error value.
catch_primitive : (Error -> Any) -> Any
catch_primitive handler = @Builtin_Method "Any.catch_primitive"
catch_primitive self handler = @Builtin_Method "Any.catch_primitive"
## Generic conversion of an arbitrary Enso value to a corresponding textual
representation.

View File

@ -2,6 +2,7 @@
from Standard.Base import all
import Standard.Base.Data.Array
import Standard.Base.Data.Text.Regex
import Standard.Base.Data.Text.Matching_Mode

View File

@ -36,6 +36,7 @@ today = now
## Constructs a new Date from a year, month, and day.
Arguments
- year: The year to represent.
- month: The month-of-year to represent, from 1 (January) to 12 (December).
- day: The day-of-month to represent, from 1 to 31. It must be valid for the
year and month.
@ -63,10 +64,23 @@ new year (month = 1) (day = 1) =
instead of Enso format. Hopefully this will be fixed with
https://github.com/enso-org/enso/pull/3559
Then this should be switched to use `Panic.catch_java`.
Panic.recover Any (Date.internal_new year month day) . catch Any e-> case e of
Panic.recover Any (new_builtin year month day) . catch Any e-> case e of
Polyglot_Error_Data err -> Error.throw (Time_Error_Data err.getMessage)
ex -> ex
## PRIVATE
Constructs a new Date from a year, month, and day.
Arguments
- year: The year to represent.
- month: The month-of-year to represent, from 1 (January) to 12 (December).
- day: The day-of-month to represent, from 1 to 31. It must be valid for the
year and month.
Recommended to use `Date.new` instead which handles potential exceptions.
new_builtin : Integer -> Integer -> Integer -> Date
new_builtin year month day = @Builtin_Method "Date.new_builtin"
## ALIAS Date from Text
Converts text containing a date into a Date object.
@ -132,13 +146,42 @@ new year (month = 1) (day = 1) =
parse : Text -> (Text | Nothing) -> Date ! Time_Error
parse text pattern=Nothing =
result = Panic.recover Any <| case pattern of
Nothing -> Date.internal_parse text 0
_ : Text -> Date.internal_parse text pattern
Nothing -> parse_builtin text 0
_ : Text -> parse_builtin text pattern
_ -> Panic.throw (Time_Error_Data "An invalid pattern was provided.")
result . map_error <| case _ of
Polyglot_Error_Data err -> Time_Error_Data err.getMessage
ex -> ex
## PRIVATE
Converts text containing a date into a Date object.
Arguments:
- text: The text to try and parse as a date.
- pattern: An optional pattern describing how to parse the text.
Recommended to use `Date.parse` instead which handles potential exceptions.
? Pattern Syntax
Patterns are based on a simple sequence of letters and symbols. For
example, "d MMM yyyy" will format "2011-12-03" as "3 Dec 2011".
? Default Date Formatting
Unless you provide a custom format, the text must represent a valid date
that can be parsed using the ISO-8601 extended local date format. The
format consists of:
- Four digits or more for the year. Years in the range 0000 to 9999
will be pre-padded by zero to ensure four digits. Years outside
that range will have a prefixed positive or negative symbol.
- A dash
- Two digits for the month-of-year. This is pre-padded by zero to ensure
two digits.
- A dash
- Two digits for the day-of-month. This is pre-padded by zero to ensure two
digits.
parse_builtin : Text -> Any -> Date
parse_builtin text pattern = @Builtin_Method "Date.parse_builtin"
## This type represents a date, often viewed as year-month-day.
@ -484,7 +527,6 @@ type Date
_ ->
Error.throw (Illegal_Argument_Error_Data "Illegal period argument")
## A Date to Json conversion.
> Example

View File

@ -86,9 +86,29 @@ now = @Builtin_Method "Date_Time.now"
example_new = Date_Time.new 1986 8 5
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Time_Zone -> Date_Time ! Time_Error
new year (month = 1) (day = 1) (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) (zone = Time_Zone.system) =
Panic.catch_java Any (Date_Time.new_builtin year month day hour minute second nanosecond zone) java_exception->
Panic.catch_java Any (new_builtin year month day hour minute second nanosecond zone) java_exception->
Error.throw (Time_Error_Data java_exception.getMessage)
## PRIVATE
Obtains an instance of `Date_Time` from a year, month, day, hour, minute,
second, nanosecond and timezone.
Arguments:
- year: The year to represent, any Integer is valid.
- month: the month-of-year to represent, from 1 (January) to 12 (December)
- day: the day-of-month to represent, from 1 to 31 and must be valid for the
year and month
- hour: the hour-of-day to represent, from 0 to 23
- minute: the minute-of-hour to represent, from 0 to 59
- second: the second-of-minute to represent, from 0 to 59
- nanosecond: the nano-of-second to represent, from 0 to 999,999,999
- zone: the timezone
Recommended to use `Date_Time.new` instead which handles potential exceptions.
new_builtin : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Time_Zone -> Date_Time
new_builtin year month day hour minute second nanosecond zone = @Builtin_Method "Date_Time.new_builtin"
## ALIAS Time from Text
Obtains an instance of `Time` from a text such as
@ -171,9 +191,21 @@ parse : Text -> Text | Nothing -> Locale -> Date_Time ! Time_Error
parse text pattern=Nothing locale=Locale.default =
Panic.catch_java Any handler=(java_exception -> Error.throw (Time_Error_Data java_exception.getMessage)) <|
case pattern of
Nothing -> Date_Time.parse_builtin text
Nothing -> parse_builtin text
_ : Text -> Time_Utils.parse_datetime_format text pattern locale.java_locale
## PRIVATE
Obtains an instance of `Time` from a text such as
"2007-12-03T10:15:30+01:00 Europe/Paris".
Arguments:
- text: The text representing the time to be parsed.
Recommended to use `Date_Time.parse_builtin` instead which handles potential exceptions
and date time formats.
parse_builtin : Text -> Date_Time
parse_builtin text = @Builtin_Method "Date_Time.parse_builtin"
## PRIVATE
@ -330,7 +362,7 @@ type Date_Time
example_time_of_day = Date_Time.now.time_of_day
time_of_day : Time_Of_Day
time_of_day self = self.to_localtime_builtin
time_of_day self = @Builtin_Method "Date_Time.time_of_day"
## Returns the number of week of year this date falls into.
@ -420,7 +452,7 @@ type Date_Time
example_date = Date_Time.now.date
date : Date
date self = self.to_localdate_builtin
date self = @Builtin_Method "Date_Time.date"
## ALIAS Change Time Zone

View File

@ -24,7 +24,20 @@ polyglot java import java.lang.ArithmeticException
example_between = Duration.between Date_Time.now (Date_Time.new 2010 10 20)
between : Date_Time -> Date_Time -> Boolean -> Duration
between start_inclusive end_exclusive timezone_aware=True =
Duration.between_builtin start_inclusive end_exclusive timezone_aware
between_builtin start_inclusive end_exclusive timezone_aware
## PRIVATE
Create an interval representing the duration between two points in time.
Arguments:
- start_inclusive: The start datetime of the duration, included.
- end_exclusive: The end datetime of the duration, excluded.
- timezone_aware: Whether the duration between two given times should be
aware of the timezone, that can be set for start or end times.
Recommended to use `Duration.between` instead which provides defaults.
between_builtin : Date_Time -> Date_Time -> Boolean -> Duration
between_builtin start_inclusive end_exclusive timezone_aware = @Builtin_Method "Duration.between_builtin"
## Create a duration from time units.
@ -43,7 +56,21 @@ between start_inclusive end_exclusive timezone_aware=True =
example_duration = Duration.new hours=2
new : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Duration
new hours=0 minutes=0 seconds=0 milliseconds=0 nanoseconds=0 =
Duration.new_builtin hours minutes seconds milliseconds nanoseconds
new_builtin hours minutes seconds milliseconds nanoseconds
## PRIVATE
Create a duration from time units.
Arguments:
- hours: hours
- minutes: minutes
- seconds: seconds
- milliseconds: milliseconds
- nanoseconds: nanoseconds
Recommended to use `Duration.new` instead which provides defaults.
new_builtin : Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Duration
new_builtin hours minutes seconds milliseconds nanoseconds = @Builtin_Method "Duration.new_builtin"
## Create a Duration from hours.
hours : Integer -> Duration

View File

@ -47,9 +47,24 @@ now = @Builtin_Method "Time_Of_Day.now"
example_epoch = Time_Of_Day.new hour=9 minute=30
new : Integer -> Integer -> Integer -> Integer -> Time_Of_Day ! Time_Error
new (hour = 0) (minute = 0) (second = 0) (nanosecond = 0) =
Panic.catch_java Any (Time_Of_Day.new_builtin hour minute second nanosecond) java_exception->
Panic.catch_java Any (new_builtin hour minute second nanosecond) java_exception->
Error.throw (Time_Error_Data java_exception.getMessage)
## PRIVATE
Obtains an instance of `Time_Of_Day` from an hour, minute, second
and nanosecond.
Arguments:
- hour: The hour-of-day to represent, from 0 to 23.
- minute: The minute-of-hour to represent, from 0 to 59.
- second: The second-of-minute to represent, from 0 to 59.
- nanosecond: The nano-of-second to represent, from 0 to 999,999,999.
Recommended to use `Time_Of_Day.new` instead which handles potential exceptions.
new_builtin : Integer -> Integer -> Integer -> Integer -> Time_Of_Day
new_builtin hour minute second nanosecond = @Builtin_Method "Time_Of_Day.new_builtin"
## Obtains an instance of `Time_Of_Day` from a text such as "10:15".
Arguments:
@ -115,9 +130,21 @@ parse : Text -> Text | Nothing -> Locale -> Time_Of_Day ! Time_Error
parse text pattern=Nothing locale=Locale.default =
Panic.catch_java Any handler=(java_exception -> Error.throw (Time_Error_Data java_exception.getMessage)) <|
case pattern of
Nothing -> Time_Of_Day.parse_builtin text
Nothing -> parse_builtin text
_ : Text -> Time_Utils.parse_time text pattern locale.java_locale
## PRIVATE
Obtains an instance of `Time_Of_Day` from a text such as "10:15".
Arguments:
- text: The text to parse as a time of day.
Recommended to use `Time_Of_Day.parse_builtin` instead which handles potential
exceptions and different time formats.
parse_builtin : Text -> Time_Of_Day
parse_builtin text = @Builtin_Method "Time_Of_Day.parse_builtin"
## PRIVATE
This type is a date-time object that represents a time, often viewed
@ -204,7 +231,7 @@ type Time_Of_Day
example_to_time = Time_Of_Day.new 12 30 . to_time (Date.new 2020)
to_date_time : Date -> Time_Zone -> Date_Time
to_date_time self date (zone=Time_Zone.system) = self.to_time_builtin date zone
to_date_time self date (zone=Time_Zone.system) = self.to_date_time_builtin date zone
## Add the specified amount of time to this instant to get a new instant.

View File

@ -60,7 +60,22 @@ utc = parse "UTC"
example_new = Zone.new 1 1 50
new : Integer -> Integer -> Integer -> Time_Zone
new (hours = 0) (minutes = 0) (seconds = 0) =
Time_Zone.new_builtin hours minutes seconds
new_builtin hours minutes seconds
## PRIVATE
Obtains an instance of `Time_Zone` using an offset in hours, minutes and seconds
from the UTC zone.
Arguments:
- hours: The timezone offset in hours from UTC, from -18 to +18.
- minutes: The timezone offset in minutes from the nearest hour, from 0 to
±59. The sign must match that of the hours argument.
- seconds: The timezone offset in seconds from the nearest minute, from 0 to
±59. The sign must match that of the minutes argument.
Recommended to use `Time_Zone.new` instead which provides defaults.
new_builtin : Integer -> Integer -> Integer -> Time_Zone
new_builtin hours minutes seconds = @Builtin_Method "Time_Zone.new_builtin"
## ALIAS Time Zone from Text
@ -96,10 +111,21 @@ new (hours = 0) (minutes = 0) (seconds = 0) =
from Standard.Base import Time_Zone
example_parse = Time_Zone.parse "+03:02:01"
parse : Text -> Time_Zone
parse : Text -> Time_Zone ! Time_Error
parse text =
Panic.catch_java Any handler=(java_exception -> Error.throw (Time_Error_Data java_exception.getMessage)) <|
Time_Zone.parse_builtin text
parse_builtin text
## PRIVATE
This method parses the ID producing a `Time_Zone`.
Arguments:
- text: The text representing a zone identifier.
Recommended to use `Time_Zone.parse` instead which handles potential exceptions.
parse_builtin : Text -> Time_Zone
parse_builtin text = @Builtin_Method "Time_Zone.parse_builtin"
## PRIVATE

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Array
import Standard.Base.Data.Index_Sub_Range
import Standard.Base.Random
@ -26,7 +27,7 @@ polyglot java import java.lang.ClassCastException
Vector.new my_vec.length (ix -> my_vec.at ix)
new : Number -> (Number -> Any) -> Vector Any
new length constructor = @Builtin_Method "Vector.new_builtin"
new length constructor = @Builtin_Method "Vector.new"
## ADVANCED
@ -453,7 +454,7 @@ type Vector a
self.fold 0 i-> vec->
Array.copy vec.to_array 0 arr i vec.length
i + vec.length
Vector.from_polyglot_array arr
from_polyglot_array arr
## Applies a function to each element of the vector, returning the vector
of results.
@ -568,7 +569,7 @@ type Vector a
_ : Vector ->
eq_at i = self.at i == that.at i
if self.length == that.length then 0.up_to self.length . all eq_at else False
_ : Array ->
_ : Array.Array ->
eq_at i = self.at i == that.at i
if self.length == that.length then 0.up_to self.length . all eq_at else False
_ -> False
@ -589,7 +590,7 @@ type Vector a
arr = Array.new (self_len + that.length)
Array.copy self.to_array 0 arr 0 self_len
Array.copy that.to_array 0 arr self_len that.length
Vector.from_polyglot_array arr
from_polyglot_array arr
## Add `element` to the beginning of `self` vector.
@ -867,7 +868,7 @@ type Vector a
handle_incomparable_value <|
new_vec_arr.sort compare
Vector.from_polyglot_array new_vec_arr
from_polyglot_array new_vec_arr
## UNSTABLE
Keeps only unique elements within the Vector, removing any duplicates.

View File

@ -766,6 +766,8 @@ type Time_Error
epoch_start : Time_Error
epoch_start = Time_Error_Data "Epoch start underflow"
to_display_text : Text
to_display_text self = self.error_message
## TODO Dubious constructor export
from project.Error.Common.Unsupported_File_Type import all

View File

@ -87,6 +87,7 @@ export project.Error.Problem_Behavior
export project.IO
export project.Math
export project.Meta
export project.Polyglot
export project.Polyglot.Java
export project.Runtime
export project.Runtime.State
@ -119,7 +120,6 @@ from project.Data.Text.Span export all
from project.Error.Common export all
from project.Function export all
from project.Nothing export all
from project.Polyglot export all
from project.Runtime.Extensions export all
from project.System.File_Format export File_Format, Plain_Text_Format, Plain_Text, Bytes, Infer, Auto_Detect
from project.Data.Index_Sub_Range export First, Last

View File

@ -330,8 +330,8 @@ is_a value typ = if is_same_object value typ then True else
_ : Duration.Duration -> typ.is_same_object_as Duration.Duration
_ : Time_Of_Day.Time_Of_Day -> typ.is_same_object_as Time_Of_Day.Time_Of_Day
_ : Time_Zone.Time_Zone -> typ.is_same_object_as Time_Zone.Time_Zone
Base.Polyglot ->
typ==Base.Polyglot || java_instance_check value typ
Base.Polyglot.Polyglot ->
typ==Base.Polyglot.Polyglot || java_instance_check value typ
_ ->
meta_val = meta value
case meta_val of
@ -361,7 +361,7 @@ java_instance_check value typ =
Arguments:
- value: the value to get the type of.
type_of : Any -> Any
type_of value = @Builtin_Method "Meta.type_of_builtin"
type_of value = @Builtin_Method "Meta.type_of"
# TODO Dubious constructor export
from project.Meta.Language import all
@ -427,17 +427,6 @@ is_polyglot value = @Builtin_Method "Meta.is_polyglot"
is_unresolved_symbol : Any -> Boolean
is_unresolved_symbol value = @Builtin_Method "Meta.is_unresolved_symbol"
## PRIVATE
Returns a Text representing the source location of a stack frame above
the call.
Arguments:
- frames_to_skip: how many frames on the stack to skip. Called with 0
will return exact location of the call.
get_source_location_builtin : Integer -> Text
get_source_location_builtin frames_to_skip = @Builtin_Method "Meta.get_source_location_builtin"
## PRIVATE
Returns a Text representing the source location of a stack frame above
@ -455,6 +444,17 @@ get_source_location : Integer -> Text
get_source_location skip_frames =
get_source_location_builtin skip_frames+1
## PRIVATE
Returns a Text representing the source location of a stack frame above
the call.
Arguments:
- frames_to_skip: how many frames on the stack to skip. Called with 0
will return exact location of the call.
get_source_location_builtin : Integer -> Text
get_source_location_builtin frames_to_skip = @Builtin_Method "Meta.get_source_location_builtin"
## PRIVATE
Displays the type of the provided value as text.

View File

@ -1,19 +1,19 @@
## Utilities for working with Java polyglot objects.
type Java
## Adds the provided entry to the host class path.
Arguments:
- path: The java classpath entry to add.
## Adds the provided entry to the host class path.
Use of the actual polyglot imports system should be preferred to use of
this method.
Arguments:
- path: The java classpath entry to add.
> Example
Adding Random to the classpath.
Use of the actual polyglot imports system should be preferred to use of
this method.
Java.add_to_class_path "java.util.Random"
add_to_class_path : Text -> Nothing
add_to_class_path path = @Builtin_Method "Java.add_to_class_path"
> Example
Adding Random to the classpath.
Java.add_to_class_path "java.util.Random"
add_to_class_path : Text -> Nothing
add_to_class_path path = @Builtin_Method "Java.add_to_class_path"
## Looks up a java symbol on the classpath by name.

View File

@ -1,28 +0,0 @@
from Standard.Base import Polyglot, Array
## TODO Dubious constructor export
from project.Polyglot.Proxy_Polyglot_Array.Proxy_Polyglot_Array import all
from project.Polyglot.Proxy_Polyglot_Array.Proxy_Polyglot_Array export all
## Advanced
Wrapper for Polyglot Arrays
type Proxy_Polyglot_Array
Proxy_Polyglot_Array_Data arr
## Returns the number of elements stored in this Polyglot Array.
length : Number
length self =
Polyglot.get_array_size self.arr
## Gets an element from this Polyglot Array at a specified index (0-based).
at : Number -> Any
at self index =
Polyglot.read_array_element self.arr index
to_array : Array Any
to_array self =
self.arr

View File

@ -1,12 +1,13 @@
from Standard.Base import all
import Standard.Base.System.File.Option
import Standard.Base.System.File.File_Permissions
import Standard.Base.Data.Array
import Standard.Base.Data.Text.Text_Sub_Range
from Standard.Base.Error.Common import Unsupported_File_Type
from Standard.Base.Error.Problem_Behavior import Report_Warning
import Standard.Base.Runtime.Resource
from Standard.Base.Runtime.Resource import Managed_Resource
from Standard.Base.Error.Common import Unsupported_File_Type
import Standard.Base.System.File.Option
import Standard.Base.System.File.File_Permissions
polyglot java import org.enso.base.Array_Builder
polyglot java import org.enso.base.Encoding_Utils
@ -391,14 +392,6 @@ type File
creation_time self =
handle_java_exceptions self <| self.creation_time_builtin
## PRIVATE
Builtin method that gets this file's creation time.
Recommended to use `File.creation_time` instead which handles potential
exceptions.
creation_time_builtin : File -> ZonedDateTime
creation_time_builtin self = @Builtin_Method "File.creation_time_builtin"
## Gets the last modified time of a file.
> Example
@ -411,14 +404,6 @@ type File
last_modified_time self =
handle_java_exceptions self <| self.last_modified_time_builtin
## PRIVATE
Builtin method that gets this file's last modified time.
Recommended to use `File.last_modified_time` instead which handles
potential exceptions.
last_modified_time_builtin : ZonedDateTime
last_modified_time_builtin self = @Builtin_Method "File.last_modified_time_builtin"
## Gets the POSIX permissions associated with the file.
> Example
@ -431,15 +416,6 @@ type File
posix_permissions self =
File_Permissions.from_java_set self.posix_permissions_builtin
## PRIVATE
Builtin method that gets this file's POSIX permissions as a Java Set.
Recommended to use `File.posix_permissions` instead which handles
potential exceptions and converts an Enso representation of the
permissions.
posix_permissions_builtin : Set
posix_permissions_builtin self = @Builtin_Method "File.posix_permissions_builtin"
## Checks whether the file exists and is a directory.
> Example
@ -593,13 +569,6 @@ type File
delete self =
handle_java_exceptions self self.delete_builtin
## PRIVATE
Builtin method that deletes the file.
Recommended to use `File.delete` instead which handles potential exceptions.
delete_builtin : Nothing
delete_builtin self = @Builtin_Method "File.delete_builtin"
## Moves the file to the specified destination.
Arguments:
@ -614,13 +583,6 @@ type File
self.copy_builtin destination copy_options
False -> self.copy_builtin destination Array.empty
## PRIVATE
Builtin method that copies this file to a new destination.
Recommended to use `File.copy_to` instead which handles potential exceptions.
copy_builtin : File -> Array Any -> Nothing
copy_builtin self destination copy_options = @Builtin_Method "File.copy_builtin"
## Moves the file to the specified destination.
Arguments:
@ -635,13 +597,6 @@ type File
self.move_builtin destination copy_options
False -> self.move_builtin destination Array.empty
## PRIVATE
Builtin method that moves this file to a new destination.
Recommended to use `File.move_to` instead which handles potential exceptions.
move_builtin : File -> Array Any -> Nothing
move_builtin self destination copy_options = @Builtin_Method "File.move_builtin"
## Deletes the file if it exists on disk.
If the file is a directory, it must be empty, otherwise a `Panic` will
@ -700,10 +655,6 @@ type File
handle_java_exceptions self <|
Vector.from_polyglot_array (self.read_last_bytes_builtin n)
## PRIVATE
read_last_bytes_builtin : Integer -> Array
read_last_bytes_builtin self n = @Builtin_Method "File.read_last_bytes_builtin"
## Lists files contained in the directory denoted by this file.
Arguments:
@ -790,12 +741,6 @@ type File
list_immediate_children : Vector.Vector File
list_immediate_children self = Vector.from_polyglot_array (self.list_immediate_children_array)
## PRIVATE
Utility function that lists immediate children of a directory.
list_immediate_children_array : Array File
list_immediate_children_array self = @Builtin_Method "File.list_immediate_children_array"
## PRIVATE
Return the absolute path of this File

View File

@ -1,4 +1,5 @@
from Standard.Base import all
import Standard.Base.Data.Array
from project.Internal.Vector_Builder.Vector_Builder import Leaf, Append

View File

@ -344,10 +344,10 @@ class BuiltinTypesTest
val requestId = UUID.randomUUID()
val metadata = new Metadata
val idMain = metadata.addItem(37, 19)
val idMain = metadata.addItem(39, 19)
val code =
"""from Standard.Base import all
"""import Standard.Base.Data.Array
|
|main =
| Array.new_1 42
@ -370,10 +370,11 @@ class BuiltinTypesTest
val requestId = UUID.randomUUID()
val metadata = new Metadata
val idMain = metadata.addItem(37, 34)
val idMain = metadata.addItem(69, 34)
val code =
"""from Standard.Base import all
|import Standard.Base.Data.Array
|
|main =
| Vector.from_array Array.empty

View File

@ -13,7 +13,11 @@ import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.callable.CallerInfo;
import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(type = "Debug", name = "breakpoint", description = "Instrumentation marker node.")
@BuiltinMethod(
type = "Debug",
name = "breakpoint",
description = "Instrumentation marker node.",
autoRegister = false)
@GenerateWrapper
public abstract class DebugBreakpointNode extends Node implements InstrumentableNode {
/**

View File

@ -12,7 +12,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "Debug",
name = "eval",
description = "Evaluates an expression passed as a Text argument, in the caller frame.")
description = "Evaluates an expression passed as a Text argument, in the caller frame.",
autoRegister = false)
public class DebugEvalNode extends Node {
private @Child EvalNode evalNode = EvalNode.build();
private @Child ExpectTextNode expectTextNode = ExpectTextNode.build();

View File

@ -9,10 +9,10 @@ import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.text.Text;
import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(type = "Module_Does_Not_Exist_Error", name = "to_display_text")
public abstract class ModuleDoesNotExistErrorToDisplayTextNode extends Node {
static ModuleDoesNotExistErrorToDisplayTextNode build() {
return ModuleDoesNotExistErrorToDisplayTextNodeGen.create();
@BuiltinMethod(type = "Module_Does_Not_Exist", name = "to_display_text")
public abstract class ModuleDoesNotExistToDisplayTextNode extends Node {
static ModuleDoesNotExistToDisplayTextNode build() {
return ModuleDoesNotExistToDisplayTextNodeGen.create();
}
abstract Text execute(Object self);

View File

@ -9,7 +9,7 @@ import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(type = "Uninitialized_State_Error", name = "to_display_text")
@BuiltinMethod(type = "Uninitialized_State", name = "to_display_text")
public abstract class UninitializedStateErrorToDisplayTextNode extends Node {
static UninitializedStateErrorToDisplayTextNode build() {
return UninitializedStateErrorToDisplayTextNodeGen.create();

View File

@ -2,14 +2,10 @@ package org.enso.interpreter.node.expression.builtin.immutable;
import com.oracle.truffle.api.dsl.*;
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.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.*;
import org.enso.interpreter.epb.node.CoercePrimitiveNode;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode;
import org.enso.interpreter.node.expression.foreign.CoerceNothing;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
@ -18,7 +14,8 @@ import org.enso.interpreter.runtime.data.Vector;
@BuiltinMethod(
type = "Vector",
name = "from_array",
description = "Creates a Vector by copying Array content.")
description = "Creates a Vector by copying Array content.",
autoRegister = false)
public abstract class FromArrayBuiltinVectorNode extends Node {
static FromArrayBuiltinVectorNode build() {
return FromArrayBuiltinVectorNodeGen.create();

View File

@ -4,7 +4,7 @@ import com.oracle.truffle.api.dsl.*;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.*;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.data.Vector;
@ -12,7 +12,9 @@ import org.enso.interpreter.runtime.data.Vector;
@BuiltinMethod(
type = "Vector",
name = "from_polyglot_array",
description = "Returns an Array representation of this Vector.")
description =
"Creates a Vector by providing its underlying storage as a polyglot array. The underlying array should be guaranteed to never be mutated.",
autoRegister = false)
public abstract class FromPolyglotArrayBuiltinVectorNode extends Node {
static FromPolyglotArrayBuiltinVectorNode build() {

View File

@ -12,13 +12,13 @@ import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.node.expression.builtin.mutable.CoerceArrayNode;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "execute",
description = "Executes a polyglot function object (e.g. a lambda).")
description = "Executes a polyglot function object (e.g. a lambda).",
autoRegister = false)
public abstract class ExecuteNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -13,7 +13,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "get_array_size",
description = "Returns the size of a polyglot array.")
description = "Returns the size of a polyglot array.",
autoRegister = false)
public class GetArraySizeNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -14,7 +14,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "get_executable_name",
description = "Returns the executable name of a polyglot object.")
description = "Returns the executable name of a polyglot object.",
autoRegister = false)
public class GetExecutableNameNode extends Node {
private @Child InteropLibrary functionsLibrary =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -13,7 +13,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "get_member",
description = "Gets a member by name from a polyglot object.")
description = "Gets a member by name from a polyglot object.",
autoRegister = false)
public class GetMemberNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -10,7 +10,8 @@ import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Polyglot",
name = "get_members",
description = "Returns a polyglot array of the object's member names.")
description = "Returns a polyglot array of the object's member names.",
autoRegister = false)
public class GetMembersNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -14,7 +14,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "get_source_location",
description = "Returns the source location of a polyglot object.")
description = "Returns the source location of a polyglot object.",
autoRegister = false)
public class GetSourceLocationNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.dsl.BuiltinMethod;
@BuiltinMethod(
type = "Polyglot",
name = "has_source_location",
description = "Checks if an object has a source location.")
description = "Checks if an object has a source location.",
autoRegister = false)
public class HasSourceLocationNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -16,7 +16,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "new",
description = "Instantiates a polyglot constructor.")
description = "Instantiates a polyglot constructor.",
autoRegister = false)
public abstract class InstantiateNode extends Node {
private @Child InteropLibrary library =

View File

@ -18,7 +18,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "invoke",
description = "Invokes a polyglot method by name, dispatching by the target argument.")
description = "Invokes a polyglot method by name, dispatching by the target argument.",
autoRegister = false)
public abstract class InvokeNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.Context;
@BuiltinMethod(
type = "Polyglot",
name = "is_language_installed",
description = "Checks if a polyglot language is installed in the runtime environment.")
description = "Checks if a polyglot language is installed in the runtime environment.",
autoRegister = false)
public abstract class IsLanguageInstalledNode extends Node {
static IsLanguageInstalledNode build() {

View File

@ -16,7 +16,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Polyglot",
name = "read_array_element",
description = "Read a value from the array specified by the index.")
description = "Read a value from the array specified by the index.",
autoRegister = false)
public class ReadArrayElementNode extends Node {
private @Child InteropLibrary library =
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);

View File

@ -13,22 +13,23 @@ import java.io.File;
@BuiltinMethod(
type = "Java",
name = "add_to_class_path",
description = "Adds a path to the host class path.")
description = "Adds a path to the host class path.",
autoRegister = false)
public abstract class AddToClassPathNode extends Node {
static AddToClassPathNode build() {
return AddToClassPathNodeGen.create();
}
abstract Object execute(Object path);
@CompilerDirectives.TruffleBoundary
@Specialization
Object doExecute(Object self, Object path, @Cached ExpectStringNode expectStringNode) {
Object doExecute(Object path, @Cached ExpectStringNode expectStringNode) {
Context context = Context.get(this);
context
.getEnvironment()
.addToHostClassPath(context.getTruffleFile(new File(expectStringNode.execute(path))));
return context.getBuiltins().nothing();
}
abstract Object execute(Object self, Object path);
}

View File

@ -7,16 +7,20 @@ import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.text.util.ExpectStringNode;
import org.enso.interpreter.runtime.Context;
@BuiltinMethod(type = "Java", name = "lookup_class", description = "Looks up a Java symbol.")
@BuiltinMethod(
type = "Java",
name = "lookup_class",
description = "Looks up a Java symbol.",
autoRegister = false)
public abstract class LookupClassNode extends Node {
static LookupClassNode build() {
return LookupClassNodeGen.create();
}
@Specialization
Object doExecute(Object self, Object name, @Cached("build()") ExpectStringNode expectStringNode) {
Object doExecute(Object name, @Cached("build()") ExpectStringNode expectStringNode) {
return Context.get(this).getEnvironment().lookupHostSymbol(expectStringNode.execute(name));
}
abstract Object execute(Object self, Object name);
abstract Object execute(Object name);
}

View File

@ -22,7 +22,8 @@ import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "IO",
name = "print_err",
description = "Prints its argument to standard error.")
description = "Prints its argument to standard error.",
autoRegister = false)
public abstract class PrintErrNode extends Node {
static PrintErrNode build() {
return PrintErrNodeGen.create();

View File

@ -19,7 +19,11 @@ import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.state.State;
import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(type = "IO", name = "println", description = "Prints its argument to standard out.")
@BuiltinMethod(
type = "IO",
name = "println",
description = "Prints its argument to standard out.",
autoRegister = false)
public abstract class PrintlnNode extends Node {
private @Child InvokeCallableNode invokeCallableNode =
InvokeCallableNode.build(

View File

@ -10,7 +10,11 @@ import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.data.text.Text;
import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(type = "IO", name = "readln", description = "Reads a line from standard in.")
@BuiltinMethod(
type = "IO",
name = "readln",
description = "Reads a line from standard in.",
autoRegister = false)
public abstract class ReadlnNode extends Node {
static ReadlnNode build() {
return ReadlnNodeGen.create();

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
@BuiltinMethod(
type = "Meta",
name = "create_unresolved_symbol",
description = "Creates a new unresolved symbol node")
description = "Creates a new unresolved symbol node",
autoRegister = false)
public class CreateUnresolvedSymbolNode extends Node {
private @Child ExpectStringNode expectStringNode = ExpectStringNode.build();

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.runtime.data.Type;
@BuiltinMethod(
type = "Meta",
name = "get_atom_constructor",
description = "Gets the constructor of an atom.")
description = "Gets the constructor of an atom.",
autoRegister = false)
public abstract class GetAtomConstructorNode extends Node {
abstract Object execute(Object atom);

View File

@ -8,7 +8,8 @@ import org.enso.interpreter.runtime.data.Array;
@BuiltinMethod(
type = "Meta",
name = "get_atom_fields",
description = "Gets the fields of an unresolved atom.")
description = "Gets the fields of an unresolved atom.",
autoRegister = false)
public class GetAtomFieldsNode extends Node {
Array execute(Atom atom) {
return new Array(atom.getFields());

View File

@ -10,7 +10,8 @@ import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Meta",
name = "get_constructor_fields",
description = "Gets the field names of a constructor.")
description = "Gets the field names of a constructor.",
autoRegister = false)
public class GetConstructorFieldNamesNode extends Node {
Array execute(AtomConstructor atom_constructor) {
ArgumentDefinition[] fields = atom_constructor.getFields();

View File

@ -10,7 +10,8 @@ import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Meta",
name = "get_constructor_name",
description = "Gets the name of a constructor.")
description = "Gets the name of a constructor.",
autoRegister = false)
public abstract class GetConstructorNameNode extends Node {
static GetConstructorNameNode build() {
return GetConstructorNameNodeGen.create();

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Meta",
name = "get_polyglot_language",
description = "Returns a text representation of a language of origin of a given value.")
description = "Returns a text representation of a language of origin of a given value.",
autoRegister = false)
public abstract class GetPolyglotLanguageNode extends Node {
static GetPolyglotLanguageNode build() {
return GetPolyglotLanguageNodeGen.create();

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.runtime.type.Types;
@BuiltinMethod(
type = "Meta",
name = "get_qualified_type_name",
description = "Returns a qualified type name of the given value.")
description = "Returns a qualified type name of the given value.",
autoRegister = false)
public class GetQualifiedTypeNameNode extends Node {
Text execute(@AcceptsError Object value) {
var typeName = Types.getName(value);

View File

@ -7,7 +7,11 @@ import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.node.expression.builtin.text.util.TypeToDisplayTextNode;
import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(type = "Meta", name = "get_simple_type_name", description = "Pretty prints a type.")
@BuiltinMethod(
type = "Meta",
name = "get_simple_type_name",
description = "Pretty prints a type.",
autoRegister = false)
public class GetSimpleTypeNameNode extends Node {
@Child @CompilationFinal TypeToDisplayTextNode displayTypeNode = TypeToDisplayTextNode.build();

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Meta",
name = "get_source_location_builtin",
description = "Returns a textual representation of the location of the callsite.")
description = "Returns a textual representation of the location of the callsite.",
autoRegister = false)
public class GetSourceLocationNode extends Node {
Text execute(long frames_to_skip) {

View File

@ -15,7 +15,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Meta",
name = "get_unresolved_symbol_name",
description = "Gets the name of an unresolved symbol")
description = "Gets the name of an unresolved symbol",
autoRegister = false)
public abstract class GetUnresolvedSymbolNameNode extends Node {
static GetUnresolvedSymbolNameNode build() {
return GetUnresolvedSymbolNameNodeGen.create();

View File

@ -14,7 +14,8 @@ import org.enso.interpreter.runtime.scope.ModuleScope;
@BuiltinMethod(
type = "Meta",
name = "get_unresolved_symbol_scope",
description = "Gets the scope of an unresolved symbol")
description = "Gets the scope of an unresolved symbol",
autoRegister = false)
public abstract class GetUnresolvedSymbolScopeNode extends Node {
static GetUnresolvedSymbolScopeNode build() {
return GetUnresolvedSymbolScopeNodeGen.create();

View File

@ -8,7 +8,8 @@ import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "Meta",
name = "is_atom_constructor",
description = "Checks if the argument is a constructor.")
description = "Checks if the argument is a constructor.",
autoRegister = false)
public class IsAtomConstructorNode extends Node {
boolean execute(@AcceptsError Object value) {
return TypesGen.isAtomConstructor(value);

View File

@ -6,7 +6,11 @@ import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.callable.atom.Atom;
import org.enso.interpreter.runtime.data.Type;
@BuiltinMethod(type = "Meta", name = "is_atom", description = "Checks if the argument is an atom")
@BuiltinMethod(
type = "Meta",
name = "is_atom",
description = "Checks if the argument is an atom",
autoRegister = false)
public class IsAtomNode extends Node {
boolean execute(@AcceptsError Object value) {
return value instanceof Atom || value instanceof Type;

View File

@ -8,7 +8,8 @@ import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "Meta",
name = "is_error",
description = "Checks if the argument is an error.")
description = "Checks if the argument is an error.",
autoRegister = false)
public class IsErrorNode extends Node {
boolean execute(@AcceptsError Object value) {
return TypesGen.isDataflowError(value);

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.runtime.Context;
@BuiltinMethod(
type = "Meta",
name = "is_polyglot",
description = "Checks if the argument is a polyglot value.")
description = "Checks if the argument is a polyglot value.",
autoRegister = false)
public abstract class IsPolyglotNode extends Node {
static IsPolyglotNode build() {
return IsPolyglotNodeGen.create();

View File

@ -10,7 +10,8 @@ import org.enso.interpreter.dsl.BuiltinMethod;
@BuiltinMethod(
type = "Meta",
name = "is_same_object",
description = "Checks if the two arguments share an underlying reference.")
description = "Checks if the two arguments share an underlying reference.",
autoRegister = false)
public abstract class IsSameObjectNode extends Node {
public static IsSameObjectNode build() {

View File

@ -8,7 +8,8 @@ import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "Meta",
name = "is_unresolved_symbol",
description = "Checks if the argument is an unresolved symbol.")
description = "Checks if the argument is an unresolved symbol.",
autoRegister = false)
public class IsUnresolvedSymbolNode extends Node {
boolean execute(@AcceptsError Object value) {
return TypesGen.isUnresolvedSymbol(value) || TypesGen.isUnresolvedConversion(value);

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
@BuiltinMethod(
type = "Meta",
name = "new_atom",
description = "Creates a new atom with given constructor and fields.")
description = "Creates a new atom with given constructor and fields.",
autoRegister = false)
public abstract class NewAtomInstanceNode extends Node {
static NewAtomInstanceNode build() {

View File

@ -7,7 +7,6 @@ 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.Node;
import org.enso.interpreter.Constants;
import org.enso.interpreter.dsl.AcceptsError;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.epb.runtime.PolyglotProxy;
@ -16,12 +15,12 @@ import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
import org.enso.interpreter.runtime.number.EnsoBigInteger;
import org.enso.interpreter.runtime.type.TypesGen;
@BuiltinMethod(
type = "Meta",
name = "type_of_builtin",
description = "Returns the type of a value.")
name = "type_of",
description = "Returns the type of a value.",
autoRegister = false)
public abstract class TypeOfNode extends Node {
public abstract Object execute(@AcceptsError Object value);

View File

@ -15,7 +15,11 @@ import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.data.Array;
import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(type = "Array", name = "copy", description = "Copies one array to another.")
@BuiltinMethod(
type = "Array",
name = "copy",
description = "Copies one array to another.",
autoRegister = false)
public abstract class CopyNode extends Node {
static CopyNode build() {

View File

@ -27,7 +27,8 @@ import org.enso.interpreter.runtime.type.TypesGen;
description =
"Takes a computation acquiring a resource, a function taking the resource and closing it,"
+ " and a function performing arbitrary operations on the resource. Ensures closing"
+ " the resource, even if an exception is raised in the computation.")
+ " the resource, even if an exception is raised in the computation.",
autoRegister = false)
public abstract class BracketNode extends Node {
private @Child ThunkExecutorNode invokeConstructorNode = ThunkExecutorNode.build();

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "Runtime",
name = "allow_input_in",
description = "Allows input in the specified scope.")
description = "Allows input in the specified scope.",
autoRegister = false)
public class AllowInputInNode extends Node {
private @Child ThunkExecutorNode thunkExecutorNode = ThunkExecutorNode.build();
private @Child ExpectStringNode expectStringNode = ExpectStringNode.build();

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "Runtime",
name = "allow_output_in",
description = "Allows output in the specified scope.")
description = "Allows output in the specified scope.",
autoRegister = false)
public class AllowOutputInNode extends Node {
private @Child ThunkExecutorNode thunkExecutorNode = ThunkExecutorNode.build();
private @Child ExpectStringNode expectStringNode = ExpectStringNode.build();

View File

@ -6,10 +6,14 @@ import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.Context;
@BuiltinMethod(type = "Runtime", name = "gc", description = "Forces garbage collection")
@BuiltinMethod(
type = "Runtime",
name = "gc",
description = "Forces garbage collection",
autoRegister = false)
public abstract class GCNode extends Node {
public abstract Object execute(Object self);
public abstract Object execute();
/** @return A new GCNode. */
public static GCNode build() {

View File

@ -9,7 +9,8 @@ import org.enso.interpreter.runtime.error.PanicException;
@BuiltinMethod(
type = "Runtime",
name = "primitive_get_stack_trace",
description = "Gets the current execution stacktrace.")
description = "Gets the current execution stacktrace.",
autoRegister = false)
public class GetStackTraceNode extends Node {
Array execute() {
var exception = new PanicException("Stacktrace", this);

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "Runtime",
name = "no_inline",
description = "Runs its argument without the possibility of getting inlined.")
description = "Runs its argument without the possibility of getting inlined.",
autoRegister = false)
public class NoInlineNode extends Node {
private @Child ThunkExecutorNode thunkExecutorNode = ThunkExecutorNode.build();

View File

@ -14,7 +14,8 @@ import org.enso.interpreter.runtime.state.State;
type = "Runtime",
name = "no_inline_with_arg",
description =
"Runs its first argument applied to the second argument without the possibility of the call or its argument getting inlined.")
"Runs its first argument applied to the second argument without the possibility of the call or its argument getting inlined.",
autoRegister = false)
public class NoInlineWithArgNode extends Node {
private @Child InvokeCallableNode invokeCallableNode;

View File

@ -15,7 +15,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "State",
name = "get",
description = "Returns the current value of monadic state.")
description = "Returns the current value of monadic state.",
autoRegister = false)
@ReportPolymorphism
public abstract class GetStateNode extends Node {
static GetStateNode build() {

View File

@ -12,7 +12,11 @@ import org.enso.interpreter.runtime.Context;
import org.enso.interpreter.runtime.error.PanicException;
import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(type = "State", name = "put", description = "Updates the value of monadic state.")
@BuiltinMethod(
type = "State",
name = "put",
description = "Updates the value of monadic state.",
autoRegister = false)
@ReportPolymorphism
public abstract class PutStateNode extends Node {
static PutStateNode build() {

View File

@ -15,7 +15,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "State",
name = "run",
description = "Runs a stateful computation in a local state environment.")
description = "Runs a stateful computation in a local state environment.",
autoRegister = false)
@ReportPolymorphism
public abstract class RunStateNode extends Node {
static RunStateNode build() {

View File

@ -10,7 +10,8 @@ import org.enso.interpreter.runtime.data.text.Text;
@BuiltinMethod(
type = "Prim_Text_Helper",
name = "optimize",
description = "Forces flattening of a text value, for testing purposes.")
description = "Forces flattening of a text value, for testing purposes.",
autoRegister = false)
public abstract class OptimizeNode extends Node {
private @Child ToJavaStringNode toJavaStringNode = ToJavaStringNode.build();

View File

@ -11,7 +11,8 @@ import org.enso.interpreter.runtime.state.State;
@BuiltinMethod(
type = "Thread",
name = "with_interrupt_handler",
description = "Runs a computation with a handler for thread interrupts.")
description = "Runs a computation with a handler for thread interrupts.",
autoRegister = false)
public class WithInterruptHandlerNode extends Node {
private @Child ThunkExecutorNode actExecutorNode = ThunkExecutorNode.build();
private @Child ThunkExecutorNode handlerExecutorNode = ThunkExecutorNode.build();

View File

@ -7,7 +7,8 @@ import org.enso.interpreter.runtime.callable.atom.Atom;
@BuiltinMethod(
type = "Unsafe",
name = "set_atom_field",
description = "Unsafely, in place, sets the value of an atom field by index.")
description = "Unsafely, in place, sets the value of an atom field by index.",
autoRegister = false)
public class SetAtomFieldNode extends Node {
Atom execute(Atom atom, long index, Object value) {
atom.getFields()[(int) index] = value;

View File

@ -27,6 +27,7 @@ import org.enso.compiler.core.IR;
import org.enso.interpreter.node.callable.dispatch.CallOptimiserNode;
import org.enso.interpreter.node.callable.dispatch.LoopingCallOptimiserNode;
import org.enso.interpreter.runtime.builtin.Builtins;
import org.enso.interpreter.runtime.builtin.BuiltinFunction;
import org.enso.interpreter.runtime.callable.CallerInfo;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.Array;
@ -571,14 +572,14 @@ public final class Module implements TruffleObject {
throws ArityException, UnsupportedTypeException {
String expr = Types.extractArguments(args, String.class);
Builtins builtins = context.getBuiltins();
Function eval =
BuiltinFunction eval =
builtins
.getBuiltinFunction(
builtins.debug(), Builtins.MethodNames.Debug.EVAL, context.getLanguage())
.orElseThrow();
CallerInfo callerInfo = new CallerInfo(null, LocalScope.root(), scope);
return callOptimiserNode.executeDispatch(
eval,
eval.getFunction(),
callerInfo,
context.emptyState(),
new Object[] {builtins.debug(), Text.create(expr)});

View File

@ -0,0 +1,23 @@
package org.enso.interpreter.runtime.builtin;
import org.enso.interpreter.runtime.callable.function.Function;
/** BuiltinFunction encapsulates information about a builtin runtime function and its metadata. */
public class BuiltinFunction {
// Note: ideally BuiltinFunction would be a record but there appears to be a bug in frgaal.
private Function fun;
private boolean autoRegister;
public BuiltinFunction(Function fun, boolean autoRegister) {
this.fun = fun;
this.autoRegister = autoRegister;
}
public boolean isAutoRegister() {
return this.autoRegister;
}
public Function getFunction() {
return this.fun;
}
}

View File

@ -3,12 +3,15 @@ package org.enso.interpreter.runtime.builtin;
import com.oracle.truffle.api.CompilerDirectives;
import java.lang.reflect.Constructor;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.enso.compiler.Passes;
import org.enso.compiler.context.FreshNameSupply;
import org.enso.compiler.exception.CompilerError;
@ -44,14 +47,13 @@ import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
/** Container class for static predefined atoms, methods, and their containing scope. */
public class Builtins {
private static final List<Constructor<? extends Builtin>> loadedBuiltinConstructors;
private static final Map<String, Method> loadedBbuiltinMethods;
private static final Map<String, LoadedBuiltinMethod> loadedBbuiltinMethods;
static {
loadedBuiltinConstructors = readBuiltinTypes();
@ -70,7 +72,7 @@ public class Builtins {
}
private final Map<Class<? extends Builtin>, Builtin> builtins;
private final Map<String, Map<String, Method>> builtinMethodNodes;
private final Map<String, Map<String, LoadedBuiltinMethod>> builtinMethodNodes;
private final Map<String, Builtin> builtinsByName;
private final Error error;
@ -162,19 +164,18 @@ public class Builtins {
for (Builtin builtin : builtins.values()) {
var type = builtin.getType();
String tpeName = type.getName();
Map<String, Method> methods = builtinMethodNodes.get(tpeName);
Map<String, LoadedBuiltinMethod> methods = builtinMethodNodes.get(tpeName);
if (methods != null) {
methods.forEach(
(methodName, meth) -> {
Optional<Function> fun;
try {
fun = Optional.ofNullable((Function) meth.invoke(null, language));
} catch (Exception e) {
e.printStackTrace();
fun = Optional.empty();
}
fun.ifPresent(f -> scope.registerMethod(type, methodName, f));
});
// Register a builtin method iff it is marked as auto-register.
// Methods can only register under a type or, if we deal with a static method, it's eigen-type.
// Such builtins are available on certain types without importing the whole stdlib, e.g. Any or Number.
methods.entrySet().stream().forEach(entry -> {
Type tpe = entry.getValue().isAutoRegister ? (!entry.getValue().isStatic() ? type : type.getEigentype()) : null;
if (tpe != null) {
Optional<BuiltinFunction> fun = entry.getValue().toFunction(language);
fun.ifPresent(f -> scope.registerMethod(tpe, entry.getKey(), f.getFunction()));
}
});
}
}
}
@ -209,14 +210,13 @@ public class Builtins {
}
/**
* Returns a map of Builtin Types and their instances.
* Returns a list of supported builtins.
*
* <p>Builtin types are marked via @BuiltinType annotation. THe metdata file represents a single
* builtin type per row. The format of the row is as follows: <Enso name of the builtin
* type>:<Name of the class representing it>:[<field1>,<field2>,...] where the last column gives a
* list of optional type's fields.
*
* @return map of builtin types' classes and their instances
*/
private static List<Constructor<? extends Builtin>> readBuiltinTypes() {
ClassLoader classLoader = Builtins.class.getClassLoader();
@ -281,12 +281,12 @@ public class Builtins {
* @param scope Builtins scope
* @return A map of builtin method nodes per builtin type name
*/
private Map<String, Map<String, Method>> readBuiltinMethodsMetadata(
Map<String, Method> classes, ModuleScope scope) {
private Map<String, Map<String, LoadedBuiltinMethod>> readBuiltinMethodsMetadata(
Map<String, LoadedBuiltinMethod> classes, ModuleScope scope) {
Map<String, Map<String, Method>> methodNodes = new HashMap<>();
Map<String, Map<String, LoadedBuiltinMethod>> methodNodes = new HashMap<>();
classes.forEach(
(fullBuiltinName, meth) -> {
(fullBuiltinName, builtin) -> {
String[] builtinName = fullBuiltinName.split("\\.");
if (builtinName.length != 2) {
throw new CompilerError("Invalid builtin metadata for " + fullBuiltinName);
@ -296,22 +296,22 @@ public class Builtins {
Optional.ofNullable(scope.getTypes().get(builtinMethodOwner))
.ifPresentOrElse(
constr -> {
Map<String, Method> atomNodes = methodNodes.get(builtinMethodOwner);
Map<String, LoadedBuiltinMethod> atomNodes = methodNodes.get(builtinMethodOwner);
if (atomNodes == null) {
atomNodes = new HashMap<>();
// TODO: move away from String Map once Builtins are gone
methodNodes.put(constr.getName(), atomNodes);
}
atomNodes.put(builtinMethodName, meth);
atomNodes.put(builtinMethodName, builtin);
},
() -> {
Map<String, Method> atomNodes = methodNodes.get(builtinMethodOwner);
Map<String, LoadedBuiltinMethod> atomNodes = methodNodes.get(builtinMethodOwner);
if (atomNodes == null) {
atomNodes = new HashMap<>();
// TODO: move away from String Map once Builtins are gone
methodNodes.put(builtinMethodOwner, atomNodes);
}
atomNodes.put(builtinMethodName, meth);
atomNodes.put(builtinMethodName, builtin);
});
});
return methodNodes;
@ -326,7 +326,7 @@ public class Builtins {
*
* @return A map of builtin method nodes per builtin type name
*/
private static Map<String, Method> readBuiltinMethodsMethods() {
private static Map<String, LoadedBuiltinMethod> readBuiltinMethodsMethods() {
ClassLoader classLoader = Builtins.class.getClassLoader();
List<String> lines;
try (InputStream resource = classLoader.getResourceAsStream(MethodDefinition.META_PATH)) {
@ -340,29 +340,32 @@ public class Builtins {
}
return lines.stream()
.map(
line -> {
String[] builtinMeta = line.split(":");
if (builtinMeta.length != 2) {
throw new CompilerError("Invalid builtin metadata in: " + line);
}
String[] builtinName = builtinMeta[0].split("\\.");
if (builtinName.length != 2) {
throw new CompilerError("Invalid builtin metadata in : " + line);
}
try {
@SuppressWarnings("unchecked")
Class<BuiltinRootNode> clazz =
(Class<BuiltinRootNode>) Class.forName(builtinMeta[1]);
Method meth = clazz.getMethod("makeFunction", Language.class);
// methodNodes.put(builtinMeta[0], meth);
return new AbstractMap.SimpleEntry<String, Method>(builtinMeta[0], meth);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
throw new CompilerError("Invalid builtin method " + line);
}
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
.map(
line -> {
String[] builtinMeta = line.split(":");
if (builtinMeta.length != 4) {
throw new CompilerError("Invalid builtin metadata in: " + line);
}
String[] builtinName = builtinMeta[0].split("\\.");
if (builtinName.length != 2) {
throw new CompilerError("Invalid builtin metadata in : " + line);
}
boolean isStatic = builtinMeta.length == 3 ? java.lang.Boolean.valueOf(builtinMeta[2]) : false;
boolean isAutoRegister = builtinMeta.length == 4 && java.lang.Boolean.valueOf(builtinMeta[3]);
try {
@SuppressWarnings("unchecked")
Class<BuiltinRootNode> clazz =
(Class<BuiltinRootNode>) Class.forName(builtinMeta[1]);
Method meth = clazz.getMethod("makeFunction", Language.class);
LoadedBuiltinMethod meta = new LoadedBuiltinMethod(meth, isStatic, isAutoRegister);
return new AbstractMap.SimpleEntry<String, LoadedBuiltinMethod>(builtinMeta[0], meta);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
throw new CompilerError("Invalid builtin method " + line);
}
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
/**
@ -374,21 +377,16 @@ public class Builtins {
* @return A non-empty function under the given name, if it exists. An empty value if no such
* builtin method was ever registerd
*/
public Optional<Function> getBuiltinFunction(String type, String methodName, Language language) {
public Optional<BuiltinFunction> getBuiltinFunction(String type, String methodName, Language language) {
// TODO: move away from String mapping once Builtins is gone
Map<String, Method> atomNodes = builtinMethodNodes.get(type);
Map<String, LoadedBuiltinMethod> atomNodes = builtinMethodNodes.get(type);
if (atomNodes == null) return Optional.empty();
Method meth = atomNodes.get(methodName);
if (meth == null) return Optional.empty();
try {
return Optional.ofNullable((Function) meth.invoke(null, language));
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
return Optional.empty();
}
LoadedBuiltinMethod builtin = atomNodes.get(methodName);
if (builtin == null) return Optional.empty();
return builtin.toFunction(language);
}
public Optional<Function> getBuiltinFunction(Type type, String methodName, Language language) {
public Optional<BuiltinFunction> getBuiltinFunction(Type type, String methodName, Language language) {
return getBuiltinFunction(type.getName(), methodName, language);
}
@ -611,4 +609,16 @@ public class Builtins {
public Type fromTypeSystem(String typeName) {
return TypesFromProxy.fromTypeSystem(this, typeName);
}
private record LoadedBuiltinMethod(Method meth, boolean isStatic, boolean isAutoRegister) {
Optional<BuiltinFunction> toFunction(Language language) {
try {
return Optional.ofNullable((Function) meth.invoke(null, language)).map(f-> new BuiltinFunction(f, isAutoRegister));
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
}
}

View File

@ -26,7 +26,7 @@ public final class Array implements TruffleObject {
*
* @param items the element values
*/
@Builtin.Method(expandVarargs = 4, description = "Creates an array with given elements.")
@Builtin.Method(expandVarargs = 4, description = "Creates an array with given elements.", autoRegister = false)
public Array(Object... items) {
this.items = items;
}
@ -36,7 +36,7 @@ public final class Array implements TruffleObject {
*
* @param size the size of the created array.
*/
@Builtin.Method(description = "Creates an uninitialized array of a given size.")
@Builtin.Method(description = "Creates an uninitialized array of a given size.", autoRegister = false)
public Array(long size) {
this.items = new Object[(int) size];
}
@ -80,7 +80,7 @@ public final class Array implements TruffleObject {
}
/** @return an empty array */
@Builtin.Method(description = "Creates an empty Array")
@Builtin.Method(description = "Creates an empty Array", autoRegister = false)
public static Object empty() {
return new Array();
}

View File

@ -31,13 +31,13 @@ public final class EnsoDate implements TruffleObject {
this.date = date;
}
@Builtin.Method(description = "Return current Date")
@Builtin.Method(description = "Return current Date", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static EnsoDate now() {
return new EnsoDate(LocalDate.now());
}
@Builtin.Method(name = "internal_parse", description = "Constructs a new Date from text with optional pattern")
@Builtin.Method(name = "parse_builtin", description = "Constructs a new Date from text with optional pattern", autoRegister = false)
@Builtin.Specialize
@Builtin.WrapException(from = DateTimeParseException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
@ -51,7 +51,7 @@ public final class EnsoDate implements TruffleObject {
}
}
@Builtin.Method(name = "internal_new", description = "Constructs a new Date from a year, month, and day")
@Builtin.Method(name = "new_builtin", description = "Constructs a new Date from a year, month, and day", autoRegister = false)
@Builtin.WrapException(from = DateTimeException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
public static EnsoDate create(long year, long month, long day) {

View File

@ -34,12 +34,15 @@ public final class EnsoDateTime implements TruffleObject {
this.dateTime = dateTime;
}
@Builtin.Method(name = "epoch_start", description = "Return the Enso start of the Epoch")
@Builtin.Method(
name = "epoch_start",
description = "Return the Enso start of the Epoch",
autoRegister = false)
public static EnsoDateTime epochStart() {
return epochStart;
}
@Builtin.Method(description = "Return current DateTime")
@Builtin.Method(description = "Return current DateTime", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static EnsoDateTime now() {
return new EnsoDateTime(ZonedDateTime.now());
@ -62,7 +65,8 @@ public final class EnsoDateTime implements TruffleObject {
*/
@Builtin.Method(
name = "parse_builtin",
description = "Constructs a new DateTime from text with optional pattern")
description = "Constructs a new DateTime from text with optional pattern",
autoRegister = false)
@Builtin.Specialize
@Builtin.WrapException(from = DateTimeParseException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
@ -78,7 +82,8 @@ public final class EnsoDateTime implements TruffleObject {
@Builtin.Method(
name = "new_builtin",
description = "Constructs a new Date from a year, month, and day")
description = "Constructs a new Date from a year, month, and day",
autoRegister = false)
@Builtin.WrapException(from = DateTimeException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
public static EnsoDateTime create(
@ -168,16 +173,14 @@ public final class EnsoDateTime implements TruffleObject {
}
@Builtin.Method(
name = "to_localtime_builtin",
name = "time_of_day",
description = "Return the localtime of this date time value.")
@CompilerDirectives.TruffleBoundary
public EnsoTimeOfDay toLocalTime() {
return new EnsoTimeOfDay(dateTime.toLocalTime());
}
@Builtin.Method(
name = "to_localdate_builtin",
description = "Return the localdate of this date time value.")
@Builtin.Method(name = "date", description = "Return the localdate of this date time value.")
@CompilerDirectives.TruffleBoundary
public EnsoDate toLocalDate() {
return new EnsoDate(dateTime.toLocalDate());
@ -189,15 +192,6 @@ public final class EnsoDateTime implements TruffleObject {
return new EnsoDateTime(dateTime.withZoneSameInstant(zone.asTimeZone()));
}
@Builtin.Method(
name = "to_time_builtin",
description = "Combine this day with time to create a point in time.")
@CompilerDirectives.TruffleBoundary
public EnsoDateTime toTime(EnsoTimeOfDay timeOfDay, EnsoTimeZone zone) {
return new EnsoDateTime(
dateTime.toLocalDate().atTime(timeOfDay.asTime()).atZone(zone.asTimeZone()));
}
@Builtin.Method(description = "Return this datetime to the datetime in the provided time zone.")
@CompilerDirectives.TruffleBoundary
public Text toText() {

View File

@ -1,6 +1,5 @@
package org.enso.interpreter.runtime.data;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
@ -43,7 +42,8 @@ public final class EnsoDuration implements TruffleObject {
@Builtin.Method(
name = "new_builtin",
description =
"Constructs a new Duration from hours, minutes, seconds, milliseconds and nanoseconds")
"Constructs a new Duration from hours, minutes, seconds, milliseconds and nanoseconds",
autoRegister = false)
@TruffleBoundary
public static EnsoDuration create(
long hours, long minutes, long seconds, long milliseconds, long nanoseconds) {
@ -59,7 +59,8 @@ public final class EnsoDuration implements TruffleObject {
@Builtin.Method(
name = "between_builtin",
description =
"Construct a new Duration that is between the given start date inclusive, and end date exclusive")
"Construct a new Duration that is between the given start date inclusive, and end date exclusive",
autoRegister = false)
@Builtin.Specialize
@TruffleBoundary
public static EnsoDuration between(

View File

@ -224,7 +224,8 @@ public final class EnsoFile implements TruffleObject {
@Builtin.Method(
name = "get_file",
description =
"Takes the text representation of a path and returns a TruffleFile corresponding to it.")
"Takes the text representation of a path and returns a TruffleFile corresponding to it.",
autoRegister = false)
@Builtin.Specialize
@CompilerDirectives.TruffleBoundary
public static EnsoFile fromString(Context context, String path) {
@ -234,7 +235,8 @@ public final class EnsoFile implements TruffleObject {
@Builtin.Method(
name = "get_cwd",
description = "A file corresponding to the current working directory.")
description = "A file corresponding to the current working directory.",
autoRegister = false)
@Builtin.Specialize
@CompilerDirectives.TruffleBoundary
public static EnsoFile currentDirectory(Context context) {
@ -242,7 +244,10 @@ public final class EnsoFile implements TruffleObject {
return new EnsoFile(file);
}
@Builtin.Method(name = "home", description = "Gets the user's system-defined home directory.")
@Builtin.Method(
name = "home",
description = "Gets the user's system-defined home directory.",
autoRegister = false)
@Builtin.Specialize
@CompilerDirectives.TruffleBoundary
public static EnsoFile userHome(Context context) {

View File

@ -32,7 +32,8 @@ public final class EnsoTimeOfDay implements TruffleObject {
@Builtin.Method(
name = "parse_builtin",
description = "Constructs a new DateTime from text with optional pattern")
description = "Constructs a new DateTime from text with optional pattern",
autoRegister = false)
@Builtin.Specialize
@Builtin.WrapException(from = DateTimeParseException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
@ -40,7 +41,10 @@ public final class EnsoTimeOfDay implements TruffleObject {
return new EnsoTimeOfDay(LocalTime.parse(text));
}
@Builtin.Method(name = "new_builtin", description = "Constructs a new Time_OF_Day from an hour")
@Builtin.Method(
name = "new_builtin",
description = "Constructs a new Time_OF_Day from an hour",
autoRegister = false)
@Builtin.WrapException(from = DateTimeException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
public static EnsoTimeOfDay create(long hour, long minute, long second, long nanosecond) {
@ -52,7 +56,7 @@ public final class EnsoTimeOfDay implements TruffleObject {
Math.toIntExact(nanosecond)));
}
@Builtin.Method(description = "Gets a value of hour")
@Builtin.Method(description = "Gets a value of hour", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static EnsoTimeOfDay now() {
return new EnsoTimeOfDay(LocalTime.now());
@ -107,7 +111,7 @@ public final class EnsoTimeOfDay implements TruffleObject {
}
@Builtin.Method(
name = "to_time_builtin",
name = "to_date_time_builtin",
description = "Combine this time of day with a date to create a point in time.")
@CompilerDirectives.TruffleBoundary
public EnsoDateTime toTime(EnsoDate date, EnsoTimeZone zone) {

View File

@ -15,7 +15,6 @@ import org.enso.interpreter.runtime.library.dispatch.TypesLibrary;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.zone.ZoneRulesException;
@ExportLibrary(InteropLibrary.class)
@ -34,7 +33,10 @@ public final class EnsoTimeZone implements TruffleObject {
return Text.create(this.zone.getId());
}
@Builtin.Method(name = "parse_builtin", description = "Parse the ID producing a Time_Zone.")
@Builtin.Method(
name = "parse_builtin",
description = "Parse the ID producing a Time_Zone.",
autoRegister = false)
@Builtin.Specialize
@Builtin.WrapException(from = ZoneRulesException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
@ -45,7 +47,8 @@ public final class EnsoTimeZone implements TruffleObject {
@Builtin.Method(
name = "new_builtin",
description =
"Obtains an instance of `Time_Zone` using an offset in hours, minutes and seconds from the UTC zone.")
"Obtains an instance of `Time_Zone` using an offset in hours, minutes and seconds from the UTC zone.",
autoRegister = false)
@Builtin.WrapException(from = DateTimeException.class, to = PolyglotError.class)
@CompilerDirectives.TruffleBoundary
public static EnsoTimeZone create(long hours, long minutes, long seconds) {
@ -54,7 +57,10 @@ public final class EnsoTimeZone implements TruffleObject {
Math.toIntExact(hours), Math.toIntExact(minutes), Math.toIntExact(seconds)));
}
@Builtin.Method(name = "system", description = "The system default timezone.")
@Builtin.Method(
name = "system",
description = "The system default timezone.",
autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static EnsoTimeZone system() {
return new EnsoTimeZone(ZoneId.systemDefault());

View File

@ -19,7 +19,7 @@ public final class Ref implements TruffleObject {
*
* @param value the initial value to store in the reference.
*/
@Builtin.Method(description = "Creates a new Ref")
@Builtin.Method(description = "Creates a new Ref", autoRegister = false)
public Ref(Object value) {
this.value = value;
}

View File

@ -37,8 +37,9 @@ public final class Vector implements TruffleObject {
}
@Builtin.Method(
name = "new_builtin",
description = "Creates new Vector with given length and provided elements.")
name = "new",
description = "Creates new Vector with given length and provided elements.",
autoRegister = false)
@Builtin.Specialize
public static Object newFromFunction(long length, Function fun, InteropLibrary interop) {
Object[] target = new Object[Math.toIntExact(length)];

View File

@ -53,7 +53,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "create",
description = "Creates a new instance of the primitive warning value.")
description = "Creates a new instance of the primitive warning value.",
autoRegister = false)
@Builtin.Specialize
public static Warning create(Context ctx, Object payload, Object origin) {
return new Warning(payload, origin, ctx.clockTick());
@ -67,7 +68,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "attach_with_stacktrace",
description = "Attaches the given warning to the value.")
description = "Attaches the given warning to the value.",
autoRegister = false)
@Builtin.Specialize
public static WithWarnings attach(
Context ctx, WithWarnings value, Object warning, Object origin) {
@ -76,7 +78,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "attach_with_stacktrace",
description = "Attaches the given warning to the value.")
description = "Attaches the given warning to the value.",
autoRegister = false)
@Builtin.Specialize(fallback = true)
public static WithWarnings attach(Context ctx, Object value, Object warning, Object origin) {
return new WithWarnings(value, new Warning(warning, origin, ctx.clockTick()));
@ -84,7 +87,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "get_all_array",
description = "Gets all the warnings associated with the value.")
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize
@CompilerDirectives.TruffleBoundary
public static Array getAll(WithWarnings value) {
@ -97,7 +101,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "get_all_array",
description = "Gets all the warnings associated with the value.")
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize(fallback = true)
public static Array getAll(Object value) {
return new Array();
@ -105,7 +110,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "set_array",
description = "Gets all the warnings associated with the value.")
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize
public static Object set(WithWarnings value, Object warnings, InteropLibrary interop) {
return setGeneric(value.getValue(), interop, warnings);
@ -113,7 +119,8 @@ public final class Warning implements TruffleObject {
@Builtin.Method(
name = "set_array",
description = "Gets all the warnings associated with the value.")
description = "Gets all the warnings associated with the value.",
autoRegister = false)
@Builtin.Specialize(fallback = true)
public static Object set(Object value, Object warnings, InteropLibrary interop) {
return setGeneric(value, interop, warnings);

View File

@ -22,7 +22,7 @@ public class System {
private static final Text WINDOWS = Text.create("windows");
private static final Text UNKNOWN = Text.create("unknown");
@Builtin.Method(description = "Get the type of operating system.")
@Builtin.Method(description = "Get the type of operating system.", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static Text os() {
if (SystemUtils.IS_OS_LINUX) return LINUX;
@ -31,26 +31,30 @@ public class System {
return UNKNOWN;
}
@Builtin.Method(description = "Check if the operating system is UNIX.")
@Builtin.Method(description = "Check if the operating system is UNIX.", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static Boolean is_unix() {
return SystemUtils.IS_OS_UNIX;
}
@Builtin.Method(description = "Gets the nanosecond resolution system time.")
@Builtin.Method(description = "Gets the nanosecond resolution system time.", autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static long nanoTime() {
return java.lang.System.nanoTime();
}
@Builtin.Method(description = "Exits the process, returning the provided code.")
@Builtin.Method(
description = "Exits the process, returning the provided code.",
autoRegister = false)
@CompilerDirectives.TruffleBoundary
public static void exit(long code) {
java.lang.System.exit((int) code);
}
@Builtin.Specialize
@Builtin.Method(description = "Create a system process, returning the exit code.")
@Builtin.Method(
description = "Create a system process, returning the exit code.",
autoRegister = false)
@Builtin.WrapException(from = IOException.class, to = PanicException.class)
@Builtin.WrapException(from = InterruptedException.class, to = PanicException.class)
@CompilerDirectives.TruffleBoundary

View File

@ -331,8 +331,10 @@ class IrToTruffle(
}
consOpt.foreach { cons =>
val fullMethodDefName =
cons.getName ++ Constants.SCOPE_SEPARATOR ++ methodDef.methodName.name
val expressionProcessor = new ExpressionProcessor(
cons.getName ++ Constants.SCOPE_SEPARATOR ++ methodDef.methodName.name,
fullMethodDefName,
scopeInfo.graph,
scopeInfo.graph.rootScope,
dataflowInfo
@ -375,7 +377,11 @@ class IrToTruffle(
) Right(None)
else Left(l)
)
.map(_.filterNot(_ => cons.isBuiltin))
.map(fOpt =>
// Register builtin iff it has not been automatically registered at an early stage
// of builtins initialization.
fOpt.filter(m => !m.isAutoRegister()).map(m => m.getFunction)
)
case fn: IR.Function =>
val bodyBuilder =
new expressionProcessor.BuildFunctionBody(

View File

@ -16,6 +16,7 @@ class PolyglotTest extends InterpreterTest {
"allow calling methods on static objects" in {
val code =
"""from Standard.Base import all
|import Standard.Base.Data.Array
|
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
@ -60,6 +61,7 @@ class PolyglotTest extends InterpreterTest {
"allow instantiating objects and calling methods on them" in {
val code =
"""from Standard.Base import all
|import Standard.Base.Data.Array
|
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
@ -72,6 +74,7 @@ class PolyglotTest extends InterpreterTest {
"allow listing available members of an object" in {
val code =
"""from Standard.Base import all
|import Standard.Base.Data.Array
|
|main =
| class = Java.lookup_class "org.enso.example.TestClass"
@ -106,7 +109,7 @@ class PolyglotTest extends InterpreterTest {
consumeOut shouldEqual List("0", "[]")
}
"match on Polyglot type when imported everything from stdlib" in {
"fail to match on Polyglot symbol when imported everything from stdlib" in {
val code =
"""from Standard.Base import all
|polyglot java import java.util.Random
@ -119,7 +122,7 @@ class PolyglotTest extends InterpreterTest {
|""".stripMargin
eval(code)
val count :: Nil = consumeOut
count shouldEqual "OK"
count shouldEqual "FAIL"
}
"fail to match on Polyglot type when explicitly importing everything from Polyglot module" in {

View File

@ -153,6 +153,13 @@ public @interface Builtin {
* @return number of desired expansions for vararg parameter.
*/
int expandVarargs() default 0;
/**
* `autoRegister` property indicates whether the builtin method should be automatically
* registered with the underlying type. By default every builtin method is registered with a
* type. Auto-registered methods do not have to be declared explicitly.
*/
boolean autoRegister() default true;
}
/**

View File

@ -20,4 +20,7 @@ public @interface BuiltinMethod {
/** @return a list of aliases (names) of this method */
String aliases() default "";
/** @return whether a method should be registered automatically with a type */
boolean autoRegister() default true;
}

View File

@ -97,7 +97,7 @@ public abstract class BuiltinsMetadataProcessor<T extends BuiltinsMetadataProces
/**
* The method called at the end of the round of annotation processing. It allows to write any
* collected metadata to a related resoource (see {@link
* collected metadata to a related resources (see {@link
* BuiltinsMetadataProcessor#metadataPath()}).
*
* @param writer a writer to the metadata resource

View File

@ -169,7 +169,8 @@ public class BuiltinsProcessor extends AbstractProcessor {
processingEnv,
methodName,
annotation.description(),
method.getSimpleName().toString());
method.getSimpleName().toString(),
annotation.autoRegister());
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
@ -222,7 +223,8 @@ public class BuiltinsProcessor extends AbstractProcessor {
processingEnv,
builtinMethodName,
annotation.description(),
method.getSimpleName().toString());
method.getSimpleName().toString(),
annotation.autoRegister());
} else {
return;
}
@ -235,7 +237,8 @@ public class BuiltinsProcessor extends AbstractProcessor {
processingEnv,
builtinMethodName,
annotation.description(),
method.getSimpleName().toString());
method.getSimpleName().toString(),
annotation.autoRegister());
}
}
} else {

View File

@ -23,6 +23,7 @@ import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import org.enso.interpreter.dsl.model.MethodDefinition;
import org.enso.interpreter.dsl.model.MethodDefinition.ArgumentDefinition;
import org.openide.util.lookup.ServiceProvider;
@ -35,7 +36,7 @@ import org.openide.util.lookup.ServiceProvider;
@ServiceProvider(service = Processor.class)
public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.MethodMetadataEntry> {
private final Map<Filer, Map<String, String>> builtinMethods = new HashMap<>();
private final Map<Filer, Map<String, String[]>> builtinMethods = new HashMap<>();
/**
* Processes annotated elements, generating code for each of them. The method also records
@ -108,10 +109,10 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
return;
}
String fullClassName = def.getPackageName() + "." + def.getClassName();
registerBuiltinMethod(processingEnv.getFiler(), def.getDeclaredName(), fullClassName);
registerBuiltinMethod(processingEnv.getFiler(), def.getDeclaredName(), fullClassName, def.isStatic(), def.isAutoRegister());
if (def.hasAliases()) {
for (String alias : def.aliases()) {
registerBuiltinMethod(processingEnv.getFiler(), alias, fullClassName);
registerBuiltinMethod(processingEnv.getFiler(), alias, fullClassName, def.isStatic(), def.isAutoRegister());
}
}
}
@ -463,8 +464,8 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
*/
protected void storeMetadata(Writer writer, Map<String, MethodMetadataEntry> pastEntries) throws IOException {
for (Filer f : builtinMethods.keySet()) {
for (Map.Entry<String, String> entry : builtinMethods.get(f).entrySet()) {
writer.append(entry.getKey() + ":" + entry.getValue() + "\n");
for (Map.Entry<String, String[]> entry : builtinMethods.get(f).entrySet()) {
writer.append(entry.getKey() + ":" + String.join(":", Arrays.asList(entry.getValue())) + "\n");
if (pastEntries.containsKey(entry.getKey())) {
pastEntries.remove(entry.getKey());
}
@ -472,13 +473,13 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
}
}
protected void registerBuiltinMethod(Filer f, String name, String clazzName) {
Map<String, String> methods = builtinMethods.get(f);
protected void registerBuiltinMethod(Filer f, String name, String clazzName, boolean isStatic, boolean isAutoRegister) {
Map<String, String[]> methods = builtinMethods.get(f);
if (methods == null) {
methods = new HashMap<>();
builtinMethods.put(f, methods);
}
methods.put(name, clazzName);
methods.put(name, new String[] { clazzName, String.valueOf(isStatic), String.valueOf(isAutoRegister) });
}
@Override
@ -511,11 +512,11 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
return SourceVersion.latest();
}
public record MethodMetadataEntry(String fullEnsoName, String clazzName) implements MetadataEntry {
public record MethodMetadataEntry(String fullEnsoName, String clazzName, boolean isStatic, boolean isAutoRegister) implements MetadataEntry {
@Override
public String toString() {
return fullEnsoName + ":" + clazzName;
return fullEnsoName + ":" + clazzName + ":" + isStatic + ":" + isAutoRegister;
}
@Override
@ -527,8 +528,8 @@ public class MethodProcessor extends BuiltinsMetadataProcessor<MethodProcessor.M
@Override
protected MethodMetadataEntry toMetadataEntry(String line) {
String[] elements = line.split(":");
if (elements.length != 2) throw new RuntimeException("invalid builtin metadata entry: " + line);
return new MethodMetadataEntry(elements[0], elements[1]);
if (elements.length != 4) throw new RuntimeException("invalid builtin metadata entry: " + line);
return new MethodMetadataEntry(elements[0], elements[1], Boolean.valueOf(elements[2]), Boolean.valueOf(elements[3]));
}
private static final String DATAFLOW_ERROR_PROFILE = "IsDataflowErrorConditionProfile";

View File

@ -9,7 +9,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.enso.interpreter.dsl.Builtin;
@ -39,7 +38,8 @@ public abstract class MethodNodeClassGenerator {
ProcessingEnvironment processingEnv,
String methodName,
String description,
String ownerMethodName)
String ownerMethodName,
boolean isAutoRegister)
throws IOException {
JavaFileObject gen =
processingEnv.getFiler().createSourceFile(builtinNode.jvmFriendlyFullyQualifiedName());
@ -54,6 +54,10 @@ public abstract class MethodNodeClassGenerator {
}
out.println("import " + ownerClazz.fullyQualifiedName() + ";");
out.println();
String moduleOwnerInfo = "";
if (!isAutoRegister) {
moduleOwnerInfo = ", autoRegister = " + isAutoRegister;
}
out.println(
"@BuiltinMethod(type = \""
+ ensoTypeName
@ -61,7 +65,9 @@ public abstract class MethodNodeClassGenerator {
+ ensoMethodName
+ "\", description = \"\"\"\n"
+ description
+ "\"\"\")");
+ "\"\"\""
+ moduleOwnerInfo
+ ")");
if (isAbstract()) {
out.println("public abstract class " + builtinNode.jvmFriendlyName() + " extends Node {");
out.println();

View File

@ -8,7 +8,6 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.util.*;
import java.util.stream.Collectors;
/** A domain-specific representation of a builtin method. */
public class MethodDefinition {
@ -199,6 +198,18 @@ public class MethodDefinition {
return constructorExpression;
}
public boolean isStatic() {
return arguments.stream()
.filter(arg -> arg.isSelf())
.findFirst()
.map(arg -> arg.isSyntheticSelf())
.orElseGet(() -> false);
}
public boolean isAutoRegister() {
return annotation.autoRegister();
}
public interface ArgumentDefinition {
boolean validate(ProcessingEnvironment processingEnvironment);
@ -242,6 +253,8 @@ public class MethodDefinition {
boolean isSelf();
boolean isSyntheticSelf();
boolean shouldCheckErrors();
boolean shouldCheckWarnings();
@ -332,6 +345,11 @@ public class MethodDefinition {
return true;
}
@Override
public boolean isSyntheticSelf() {
return true;
}
@Override
public boolean shouldCheckErrors() {
return false;
@ -518,6 +536,11 @@ public class MethodDefinition {
return name.equals(SELF);
}
@Override
public boolean isSyntheticSelf() {
return false;
}
public boolean shouldCheckErrors() {
return isPositional() && !isSelf() && !acceptsError();
}

View File

@ -1,10 +1,11 @@
from Standard.Base import all
import Standard.Base.Data.Array
from Standard.Test import Test, Test_Suite
polyglot java import java.util.LinkedHashSet
Array.method self = 0
Array.Array.method self = 0
## Returns an array with the same contents as the given vector, surely backed by
the Enso Array primitive.

View File

@ -427,7 +427,7 @@ js_set_zone local_datetime =
zone = Time_Zone.utc
datetime_with_tz = local_datetime.at_zone zone
diff = Duration.between datetime_with_tz local_datetime (timezone_aware=False)
(datetime_with_tz + diff).to_localdate_builtin
(datetime_with_tz + diff).date
js_date year month=1 day=1 =
Panic.catch Any (js_set_zone (js_date_impl year month day)) (err -> Error.throw (Time_Error_Data err.payload.cause))

View File

@ -101,10 +101,10 @@ spec = Test.group "Pattern Matches" <|
Test.specify "should be able to match on the Polyglot type" <|
random_gen = Random.new
case random_gen of
Polyglot -> Nothing
Polyglot.Polyglot -> Nothing
_ -> Test.fail "Expected a polyglot object to match."
case Polyglot of
Polyglot -> Nothing
case Polyglot.Polyglot of
Polyglot.Polyglot -> Nothing
_ -> Test.fail "Expected the Polyglot constructor to match."
Test.specify "should be able to match on the Any type" <|
value_1 = 1.23143

View File

@ -79,7 +79,7 @@ spec = Test.group "Meta-Value Manipulation" <|
1.0.is_a Text . should_be_false
random_gen = Random.new
Meta.is_a random_gen Polyglot . should_be_true
Meta.is_a random_gen Polyglot.Polyglot . should_be_true
Meta.is_a random_gen Integer . should_be_false
(My_Type.Value 1 "foo" Nothing).is_a My_Type.Value . should_be_true

View File

@ -1,2 +1,5 @@
@Builtin_Type
type Any
catch_primitive handler = @Builtin_Method "Any.catch_primitive"
to_text self = @Builtin_Method "Any.to_text"
to_display_text self = @Builtin_Method "Any.to_display_text"

Some files were not shown because too many files have changed in this diff Show More