Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improved polyglot Date support #3559

Merged
merged 67 commits into from
Jul 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
1225591
Run the same test suite four times for different flavours of Date
JaroslavTulach Jul 1, 2022
d063b66
Make sure isDate and asDate messages are properly propagated
JaroslavTulach Jul 1, 2022
4c98949
Convert polyglot date to Java wrapper around LocalDate
JaroslavTulach Jul 1, 2022
4811ba2
Adding tests based on Table.
jdunkerley Jul 7, 2022
7bb9767
Other way tests in Table.
jdunkerley Jul 7, 2022
b55417b
Add failing test to be fixed.
jdunkerley Jul 7, 2022
89d5c9f
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
JaroslavTulach Jul 11, 2022
61e4480
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
JaroslavTulach Jul 11, 2022
b4822cb
Removing here keyword
JaroslavTulach Jul 11, 2022
6a59a3d
Adjust the test to the removal of here keyword
JaroslavTulach Jul 11, 2022
fa0cf95
Merging with origin/develop
JaroslavTulach Jul 11, 2022
69320d4
import project.Util and invoke with --in-project test/Table_Tests/
JaroslavTulach Jul 11, 2022
e9b0800
Request Value and convert it later in Java code
JaroslavTulach Jul 12, 2022
fc2dca2
Ensure scope exists
JaroslavTulach Jul 12, 2022
f16d07e
Convert values returned from polyglot calls into Enso Date - when isDate
JaroslavTulach Jul 12, 2022
93abfa1
EnsoDate is able execute Date.now.year
JaroslavTulach Jul 12, 2022
4cb9636
Avoid "Cannot install GraalVM MBean" when running on GraalVM 21.3
JaroslavTulach Jul 13, 2022
459addf
Encapsulating builtin methods into Date_Internal.enso
JaroslavTulach Jul 13, 2022
9f5ad98
Proper name of the date_now node
JaroslavTulach Jul 13, 2022
a79a7d3
Enso works with longs not integers
JaroslavTulach Jul 13, 2022
f2c6ea1
Support for parsing Date
JaroslavTulach Jul 13, 2022
b578f48
More magic with exceptions
JaroslavTulach Jul 13, 2022
0a466d9
Use builtins DSL to generate boilerplate code
hubertp Jul 13, 2022
bc2b7f3
Date_Spec successful for EnsoDate
JaroslavTulach Jul 13, 2022
cff9001
No need for Atom to pretend it is a Date - there is EnsoDate instead
JaroslavTulach Jul 14, 2022
71e3460
Changelog: PR-3559 is continuation of PR-3374
JaroslavTulach Jul 14, 2022
ab4776d
Formatting
JaroslavTulach Jul 14, 2022
108dc0c
Exposing year, month and day as EnsoDate polyglot members
JaroslavTulach Jul 14, 2022
2a6dc82
Return [] for Polyglot.get_members if message isn't supported
JaroslavTulach Jul 14, 2022
50420c4
Prefer Date.format method over polyglot LocalDate.format invocation
JaroslavTulach Jul 14, 2022
bc7d01d
Removing useless import
JaroslavTulach Jul 14, 2022
2cea130
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
JaroslavTulach Jul 14, 2022
0f69a68
Enso uses snake_case
JaroslavTulach Jul 14, 2022
f2e16c8
Using Hubert's DSL changes with current state of the branch
JaroslavTulach Jul 14, 2022
005f9d0
Runtime represention needs to be interop type. TruffleObject or Strin…
JaroslavTulach Jul 14, 2022
e656f76
Replacing YearMonthDayNode with @Builtin.Method
JaroslavTulach Jul 14, 2022
a356457
Replacing ParseNode with @Builtin.Method
JaroslavTulach Jul 14, 2022
b935308
Giving the internal methods internal_ prefix
JaroslavTulach Jul 14, 2022
1c2975c
Merging with most recent develop branch
JaroslavTulach Jul 14, 2022
b57017a
Avoid the Polyglot.get_member experiment
JaroslavTulach Jul 15, 2022
9611cb5
Checking isString next to isDate - e.g. sooner than polyglot types
JaroslavTulach Jul 15, 2022
922ead2
Using List<Value> parameter to simplify iteration
JaroslavTulach Jul 15, 2022
566bf7d
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
JaroslavTulach Jul 15, 2022
ebb0dd0
No need to access internal_local_date or use Date.Date constructor
JaroslavTulach Jul 15, 2022
8b686b1
PanicException can only accept interop values
JaroslavTulach Jul 16, 2022
60da5e7
Adding java_exception.has_type method
JaroslavTulach Jul 17, 2022
36d4480
Simple builtin methods for year, month, day
JaroslavTulach Jul 17, 2022
fdf33e2
Removing unused imports
JaroslavTulach Jul 17, 2022
bd5a91e
Can no longer access err.getClass
JaroslavTulach Jul 17, 2022
766e5ef
Ability to call ColumnNameMismatchException.getMissing method by dele…
JaroslavTulach Jul 17, 2022
08db35a
Need to read org.enso.table.read.ParsingFailedException.problem field
JaroslavTulach Jul 17, 2022
05edca4
Name the method internal_local_date - the same name as Date field use…
JaroslavTulach Jul 17, 2022
e027ed9
Removing use-less internal_local_time invocation
JaroslavTulach Jul 17, 2022
6d00b59
Accept also Value if it looks like a date
JaroslavTulach Jul 17, 2022
b5038a5
Formatting Java sources
JaroslavTulach Jul 17, 2022
f34ffc4
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 18, 2022
e742bb4
Fix tests under Windows.
jdunkerley Jul 18, 2022
9fbcd1c
Changing to more functional style
JaroslavTulach Jul 19, 2022
67e9256
Enough to check just for instanceof Text
JaroslavTulach Jul 19, 2022
4eb0a24
Removing no longer needed method
JaroslavTulach Jul 19, 2022
fabef71
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 19, 2022
4a7b860
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 19, 2022
ec0b51d
Using is_a message as that one is defined on Any
JaroslavTulach Jul 19, 2022
a58649b
Merging with developer branch and resolving conflicts
JaroslavTulach Jul 20, 2022
1933f2e
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 20, 2022
ccb6a96
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 20, 2022
313f98e
Merge branch 'develop' into wip/jtulach/PolyglotDateSupport_181755990
mergify[bot] Jul 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
- [Fixed issues related to constructors' default arguments][3330]
- [Fixed compiler issue related to module cache.][3367]
- [Fixed execution of defaulted arguments of Atom Constructors][3358]
- [Converting Enso Date to java.time.LocalDate and back][3374]
- [Converting Enso Date to java.time.LocalDate and back][3559]
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
- [Incremental Reparsing of a Simple Edits][3508]
- [Functions with all-defaulted arguments now execute automatically][3414]
- [Provide `tagValues` for function arguments in the language server][3422]
Expand Down Expand Up @@ -297,7 +297,7 @@
[3358]: https://github.com/enso-org/enso/pull/3358
[3360]: https://github.com/enso-org/enso/pull/3360
[3367]: https://github.com/enso-org/enso/pull/3367
[3374]: https://github.com/enso-org/enso/pull/3374
[3559]: https://github.com/enso-org/enso/pull/3559
[3508]: https://github.com/enso-org/enso/pull/3508
[3412]: https://github.com/enso-org/enso/pull/3412
[3414]: https://github.com/enso-org/enso/pull/3414
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ type Engine

internal_pattern = maybe_java_pattern.map_error case _ of
Polyglot_Error err ->
if Java.is_instance err PatternSyntaxException . not then err else
if err.is_a PatternSyntaxException . not then err else
Regex.Syntax_Error err.getMessage
other -> other

Expand Down Expand Up @@ -823,8 +823,8 @@ type Match
handle_error : Any -> (Text | Integer) -> Any
handle_error error id = case error of
Polyglot_Error err ->
is_ioob = Java.is_instance err IndexOutOfBoundsException
is_iae = Java.is_instance err IllegalArgumentException
is_ioob = err.is_a IndexOutOfBoundsException
is_iae = err.is_a IllegalArgumentException
maps_to_no_such_group = is_ioob || is_iae

if maps_to_no_such_group.not then err else
Expand Down
12 changes: 5 additions & 7 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time.enso
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ type Time

example_date = Time.now.date
date : Date
date = Date.Date self.internal_zoned_date_time.toLocalDate
date = self.internal_zoned_date_time.toLocalDate

## ALIAS Change Time Zone

Expand Down Expand Up @@ -466,13 +466,11 @@ type Time
sign = self.internal_zoned_date_time.compareTo that.internal_zoned_date_time
Ordering.from_sign sign

## Checks if `self` equals `that`.

Arguments:
- that: The other `Time` to compare against.
## Compares two Time for equality.
== : Time -> Boolean
== that =
self.internal_zoned_date_time.equals that.internal_zoned_date_time
== that = case that of
Time _ -> self.internal_zoned_date_time.equals that.internal_zoned_date_time
_ -> False

type Time_Error

Expand Down
61 changes: 25 additions & 36 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Time/Date.enso
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,8 @@ import Standard.Base.Data.Time
import Standard.Base.Data.Time.Duration
import Standard.Base.Data.Time.Time_Of_Day
import Standard.Base.Data.Time.Zone
import Standard.Base.Polyglot

polyglot java import java.time.format.DateTimeFormatter
polyglot java import java.time.Instant
polyglot java import java.time.LocalDate
polyglot java import java.time.temporal.WeekFields
polyglot java import org.enso.base.Time_Utils

## Obtains the current date from the system clock in the system timezone.
Expand All @@ -20,7 +17,7 @@ polyglot java import org.enso.base.Time_Utils

example_now = Date.now
now : Date
now = LocalDate.now
now = @Builtin_Method "Date.now"

## ALIAS Current Date

Expand Down Expand Up @@ -67,9 +64,9 @@ 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 (LocalDate.of year month day) . catch Any e-> case e of
Panic.recover Any (Date.internal_new year month day) . catch Any e-> case e of
Polyglot_Error err -> Error.throw (Time.Time_Error err.getMessage)
x -> x
ex -> ex

## ALIAS Date from Text

Expand Down Expand Up @@ -136,27 +133,25 @@ new year (month = 1) (day = 1) =
parse : Text -> (Text | Nothing) -> Date ! Time.Time_Error
parse text pattern=Nothing =
result = Panic.recover Any <| case pattern of
Nothing -> LocalDate.parse text
Text -> LocalDate.parse text (DateTimeFormatter.ofPattern pattern)
Nothing -> Date.internal_parse text 0
Text -> Date.internal_parse text pattern
_ -> Panic.throw (Time.Time_Error "An invalid pattern was provided.")
Date result . map_error <| case _ of
result . map_error <| case _ of
Polyglot_Error err -> Time.Time_Error err.getMessage
x -> x
ex -> ex

type Date

## This type represents a date, often viewed as year-month-day.

Arguments:
- internal_local_date: The internal date representation.

For example, the value "2nd October 2007" can be stored in a `Date`.

This class does not store or represent a time or timezone. Instead, it
is a description of the date, as used for birthdays. It cannot represent
an instant on the time-line without additional information such as an
offset or timezone.
type Date internal_local_date
@Builtin_Type
type Date

## Get the year field.

Expand All @@ -167,7 +162,7 @@ type Date

example_year = Date.now.year
year : Integer
year = self . internal_local_date . getYear
year = @Builtin_Method "Date.year"

## Get the month of year field, as a number from 1 to 12.

Expand All @@ -178,7 +173,7 @@ type Date

example_month = Date.now.month
month : Integer
month = self . internal_local_date . getMonthValue
month = @Builtin_Method "Date.month"

## Get the day of month field.

Expand All @@ -189,7 +184,7 @@ type Date

example_day = Date.now.day
day : Integer
day = self . internal_local_date . getDayOfMonth
day = @Builtin_Method "Date.day"

## Returns the number of week of year this date falls into.

Expand All @@ -205,9 +200,7 @@ type Date
containing the first Thursday of the year. Therefore it is important to
properly specify the `locale` argument.
week_of_year : Locale.Locale -> Integer
week_of_year locale=Locale.default =
field = WeekFields.of locale.java_locale . weekOfYear
self.internal_local_date.get field
week_of_year locale=Locale.default = Time_Utils.week_of_year self locale.java_locale

## ALIAS Date to Time

Expand All @@ -226,7 +219,7 @@ type Date

example_to_time = Date.new 2020 2 3 . to_time Time_Of_Day.new Zone.utc
to_time : Time_Of_Day -> Zone -> Time
to_time time_of_day (zone = Zone.system) = Time.Time (self . internal_local_date . atTime time_of_day.internal_local_time . atZone zone.internal_zone_id)
to_time time_of_day (zone = Zone.system) = Time.Time (Time_Utils.date_with_time self time_of_day.internal_local_time zone.internal_zone_id)

## Add the specified amount of time to this instant to get another date.

Expand All @@ -242,7 +235,7 @@ type Date
example_add = Date.new 2020 + 6.months
+ : Duration -> Date
+ amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else
Date (self . internal_local_date . plus amount.internal_period)
(Time_Utils.date_adjust self 1 amount.internal_period) . internal_local_date

## Subtract the specified amount of time from this instant to get another
date.
Expand All @@ -259,18 +252,8 @@ type Date
example_subtract = Date.new 2020 - 7.days
- : Duration -> Date
- amount = if amount.is_time then Error.throw (Time.Time_Error "Date does not support time intervals") else
(self . internal_local_date . minus amount.internal_period)

## Format this date using the default formatter.

> Example
Convert the current date to text.

import Standard.Base.Data.Time.Date
(Time_Utils.date_adjust self -1 amount.internal_period) . internal_local_date

example_to_text = Date.now.to_text
to_text : Text
to_text = Time_Utils.default_date_formatter . format self.internal_local_date

## A Date to Json conversion.

Expand Down Expand Up @@ -327,7 +310,7 @@ type Date

example_format = Date.new 2020 6 2 . format "yyyyGG"
format : Text -> Text
format pattern = DateTimeFormatter.ofPattern pattern . format self.internal_local_date
format pattern = Time_Utils.local_date_format self pattern

## Compares `self` to `that` to produce an ordering.

Expand All @@ -340,5 +323,11 @@ type Date
(Date.new 2000).compare_to (Date.new 2001)
compare_to : Date -> Ordering
compare_to that =
sign = self.internal_local_date.compareTo that.internal_local_date
sign = Time_Utils.compare_to self that
Ordering.from_sign sign

## Compares two Dates for equality.
== : Date -> Boolean
== that =
sign = Time_Utils.compare_to self that
0 == sign
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ type Time_Of_Day
example_to_time = Time_Of_Day.new 12 30 . to_time (Date.new 2020)
to_time : Date -> Zone -> Time
to_time date (zone = Zone.system) =
Time.Time (self . internal_local_time . atDate date.internal_local_date . atZone zone.internal_zone_id)
Time.Time (self . internal_local_time . atDate date . atZone zone.internal_zone_id)

## Add the specified amount of time to this instant to get a new instant.

Expand Down Expand Up @@ -332,3 +332,9 @@ type Time_Of_Day
compare_to that =
sign = self.internal_local_time.compareTo that.internal_local_time
Ordering.from_sign sign

## Compares two Time_Of_Day for equality.
== : Date -> Boolean
== that = case that of
Time_Of_Day _ -> self.internal_local_time.equals that.internal_local_time
_ -> False
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ type Panic
False -> Panic.throw caught_panic
True -> case caught_panic.payload of
Polyglot_Error java_exception ->
case Java.is_instance java_exception panic_type of
case java_exception.is_a panic_type of
True -> handler caught_panic
False -> Panic.throw caught_panic
_ -> Panic.throw caught_panic
Expand Down Expand Up @@ -392,7 +392,7 @@ type Panic
catch_java panic_type ~action handler =
Panic.catch_primitive action caught_panic-> case caught_panic.payload of
Polyglot_Error java_exception ->
case (panic_type == Any) || (Java.is_instance java_exception panic_type) of
case (panic_type == Any) || (java_exception.is_a panic_type) of
True -> handler java_exception
False -> Panic.throw caught_panic
_ -> Panic.throw caught_panic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ type Http
request : Request -> Response ! Request_Error
request req =
handle_request_error =
Panic.catch_java Any handler=(err-> Error.throw (Request_Error err.getClass.getSimpleName err.getMessage))
Panic.catch_java Any handler=(err-> Error.throw (Request_Error 'IllegalArgumentException' err.getMessage))
Panic.recover Any <| handle_request_error <|
body_publishers = HttpRequest.BodyPublishers
builder = HttpRequest.newBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -955,10 +955,10 @@ handle_java_exceptions file ~action =

Converts a Java `IOException` into its Enso counterpart.
wrap_io_exception file io_exception =
if Java.is_instance io_exception NoSuchFileException then Error.throw (File_Not_Found file) else
if Java.is_instance io_exception FileAlreadyExistsException then Error.throw (File_Already_Exists_Error file) else
if Java.is_instance io_exception AccessDeniedException then Error.throw (IO_Error file "You do not have permission to access the file") else
Error.throw (IO_Error file "An IO error has occurred: "+io_exception.getMessage)
if io_exception.is_a NoSuchFileException then Error.throw (File_Not_Found file) else
if io_exception.is_a FileAlreadyExistsException then Error.throw (File_Already_Exists_Error file) else
if io_exception.is_a AccessDeniedException then Error.throw (IO_Error file "You do not have permission to access the file") else
Error.throw (IO_Error file "An IO error has occurred: "+io_exception.to_text)

## PRIVATE

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.profiles.BranchProfile;
import java.time.LocalDate;
import org.enso.interpreter.epb.node.ContextRewrapExceptionNode;
import org.enso.interpreter.epb.node.ContextRewrapNode;

Expand Down Expand Up @@ -909,4 +910,29 @@ Object getExceptionMessage(
leaveOrigin(node, p);
}
}

@ExportMessage
boolean isDate(
@CachedLibrary("this.delegate") InteropLibrary datum,
@CachedLibrary("this") InteropLibrary node) {
Object p = enterOrigin(node);
try {
return datum.isDate(delegate);
} finally {
leaveOrigin(node, p);
}
}

@ExportMessage
LocalDate asDate(
@CachedLibrary("this.delegate") InteropLibrary datume,
@CachedLibrary("this") InteropLibrary node)
throws UnsupportedMessageException {
Object p = enterOrigin(node);
try {
return datume.asDate(delegate);
} finally {
leaveOrigin(node, p);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
import org.enso.interpreter.runtime.callable.function.Function;
import org.enso.interpreter.runtime.data.ArrayRope;
import org.enso.interpreter.runtime.data.EnsoDate;
import org.enso.interpreter.runtime.data.text.Text;
import org.enso.interpreter.runtime.error.*;
import org.enso.interpreter.runtime.library.dispatch.MethodDispatchLibrary;
Expand Down Expand Up @@ -246,15 +247,15 @@ Stateful doConvertDate(
@CachedLibrary(limit = "10") MethodDispatchLibrary methods,
@CachedLibrary(limit = "1") MethodDispatchLibrary dateDispatch,
@CachedLibrary(limit = "10") InteropLibrary interop) {
var ctx = Context.get(this);
try {
var dateConstructor = Context.get(this).getDateConstructor();
Object date = dateConstructor.isPresent() ? dateConstructor.get().newInstance(self) : self;
var hostLocalDate = interop.asDate(self);
var date = new EnsoDate(hostLocalDate);
Function function = dateDispatch.getFunctionalDispatch(date, symbol);
arguments[0] = date;
return invokeFunctionNode.execute(function, frame, state, arguments);
} catch (MethodDispatchLibrary.NoSuchMethodException e) {
throw new PanicException(
Context.get(this).getBuiltins().error().makeNoSuchMethodError(self, symbol), this);
} catch (MethodDispatchLibrary.NoSuchMethodException | UnsupportedMessageException e) {
throw new PanicException(ctx.getBuiltins().error().makeNoSuchMethodError(self, symbol), this);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ public boolean isInteropLibrary() {
*/
public static PolyglotCallType getPolyglotCallType(
Object self, String methodName, InteropLibrary library) {
if (library.isMemberInvocable(self, methodName)) {
if (library.isDate(self) && !library.isTime(self)) {
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
return PolyglotCallType.CONVERT_TO_DATE;
} else if (library.isString(self)) {
return PolyglotCallType.CONVERT_TO_TEXT;
} else if (library.isMemberInvocable(self, methodName)) {
return PolyglotCallType.CALL_METHOD;
} else if (library.isMemberReadable(self, methodName)) {
return PolyglotCallType.GET_MEMBER;
Expand All @@ -90,12 +94,6 @@ public static PolyglotCallType getPolyglotCallType(
return PolyglotCallType.GET_ARRAY_LENGTH;
} else if (library.hasArrayElements(self) && methodName.equals(ARRAY_READ_NAME)) {
return PolyglotCallType.READ_ARRAY_ELEMENT;
} else if (library.isString(self)) {
return PolyglotCallType.CONVERT_TO_TEXT;
} else if (library.isDate(self)) {
if (!library.isTime(self)) {
return PolyglotCallType.CONVERT_TO_DATE;
}
}
return PolyglotCallType.NOT_SUPPORTED;
}
Expand Down
Loading