mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 18:38:11 +03:00
Enso's Text Type (#1166)
This commit is contained in:
parent
bd9689a2b4
commit
a1748c3978
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@ -188,6 +188,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp enso.exe ${{ env.LAUNCHER_DIST_DIR }}/bin/
|
cp enso.exe ${{ env.LAUNCHER_DIST_DIR }}/bin/
|
||||||
|
|
||||||
|
- name: Build Base Java Extensions
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd std-bits
|
||||||
|
mvn package
|
||||||
|
|
||||||
# The way artifacts are uploaded currently does not preserve the
|
# The way artifacts are uploaded currently does not preserve the
|
||||||
# executable bits for Unix. However putting artifacts into a ZIP would
|
# executable bits for Unix. However putting artifacts into a ZIP would
|
||||||
# create a twice nested ZIP file. For now, users downloading artifacts
|
# create a twice nested ZIP file. For now, users downloading artifacts
|
||||||
|
6
.github/workflows/scala.yml
vendored
6
.github/workflows/scala.yml
vendored
@ -320,6 +320,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp enso.exe ${{ env.LAUNCHER_DIST_DIR }}/bin/
|
cp enso.exe ${{ env.LAUNCHER_DIST_DIR }}/bin/
|
||||||
|
|
||||||
|
- name: Build Base Java Extensions
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd std-bits
|
||||||
|
mvn package
|
||||||
|
|
||||||
# The way artifacts are uploaded currently does not preserve the
|
# The way artifacts are uploaded currently does not preserve the
|
||||||
# executable bits for Unix. However putting artifacts into a ZIP would
|
# executable bits for Unix. However putting artifacts into a ZIP would
|
||||||
# create a twice nested ZIP file. For now, users downloading artifacts
|
# create a twice nested ZIP file. For now, users downloading artifacts
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,6 +13,7 @@ graal_dumps/
|
|||||||
target/
|
target/
|
||||||
*.class
|
*.class
|
||||||
*.log
|
*.log
|
||||||
|
.java-version
|
||||||
|
|
||||||
##########
|
##########
|
||||||
## Rust ##
|
## Rust ##
|
||||||
@ -62,6 +63,7 @@ package-lock.json
|
|||||||
*.swp
|
*.swp
|
||||||
.projections.json
|
.projections.json
|
||||||
.nvmrc
|
.nvmrc
|
||||||
|
*.iml
|
||||||
|
|
||||||
############################
|
############################
|
||||||
## Rendered Documentation ##
|
## Rendered Documentation ##
|
||||||
|
28
build.sbt
28
build.sbt
@ -4,6 +4,7 @@ import com.typesafe.sbt.SbtLicenseReport.autoImportImpl.{
|
|||||||
licenseReportNotes,
|
licenseReportNotes,
|
||||||
licenseReportStyleRules
|
licenseReportStyleRules
|
||||||
}
|
}
|
||||||
|
import scala.sys.process._
|
||||||
import org.enso.build.BenchTasks._
|
import org.enso.build.BenchTasks._
|
||||||
import org.enso.build.WithDebugCommand
|
import org.enso.build.WithDebugCommand
|
||||||
import sbt.Keys.{libraryDependencies, scalacOptions}
|
import sbt.Keys.{libraryDependencies, scalacOptions}
|
||||||
@ -893,6 +894,21 @@ lazy val runtime = (project in file("engine/runtime"))
|
|||||||
.dependsOn(Def.task { (Compile / sourceManaged).value.mkdirs })
|
.dependsOn(Def.task { (Compile / sourceManaged).value.mkdirs })
|
||||||
.value
|
.value
|
||||||
)
|
)
|
||||||
|
.settings(
|
||||||
|
(Test / compile) := (Test / compile)
|
||||||
|
.dependsOn(Def.task {
|
||||||
|
val cmd = Seq("mvn", "package", "-f", "std-bits")
|
||||||
|
val exitCode = if (sys.props("os.name").toLowerCase().contains("win")) {
|
||||||
|
(Seq("cmd", "/c") ++ cmd).!
|
||||||
|
} else {
|
||||||
|
cmd.!
|
||||||
|
}
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException("std-bits build failed.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.value
|
||||||
|
)
|
||||||
.settings(
|
.settings(
|
||||||
logBuffered := false,
|
logBuffered := false,
|
||||||
bench := (test in Benchmark).tag(Exclusive).value,
|
bench := (test in Benchmark).tag(Exclusive).value,
|
||||||
@ -989,12 +1005,12 @@ lazy val runner = project
|
|||||||
commands += WithDebugCommand.withDebug,
|
commands += WithDebugCommand.withDebug,
|
||||||
inConfig(Compile)(truffleRunOptionsSettings),
|
inConfig(Compile)(truffleRunOptionsSettings),
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||||
"commons-cli" % "commons-cli" % commonsCliVersion,
|
"commons-cli" % "commons-cli" % commonsCliVersion,
|
||||||
"com.monovore" %% "decline" % declineVersion,
|
"com.monovore" %% "decline" % declineVersion,
|
||||||
"org.jline" % "jline" % jlineVersion,
|
"org.jline" % "jline" % jlineVersion,
|
||||||
"org.typelevel" %% "cats-core" % catsVersion,
|
"org.typelevel" %% "cats-core" % catsVersion
|
||||||
),
|
),
|
||||||
connectInput in run := true
|
connectInput in run := true
|
||||||
)
|
)
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import Base.List
|
import Base.List
|
||||||
import Base.Vector
|
import Base.Vector
|
||||||
import Base.Number.Extensions
|
import Base.Number.Extensions
|
||||||
from Builtins import Unit, Number, Integer
|
import Base.Text.Extensions
|
||||||
|
from Builtins import Unit, Number, Integer, Any, True, False
|
||||||
|
|
||||||
from Builtins export all
|
from Builtins export all
|
||||||
|
|
||||||
from Base.List export Nil, Cons
|
from Base.List export Nil, Cons
|
||||||
from Base.Vector export Vector
|
from Base.Vector export Vector
|
||||||
from Base.Number.Extensions export all hiding Math
|
from Base.Number.Extensions export all hiding Math
|
||||||
|
from Base.Text.Extensions export Text
|
||||||
|
|
||||||
## Represents a right-exclusive range of integer values.
|
## Represents a right-exclusive range of integer values.
|
||||||
type Range
|
type Range
|
||||||
@ -44,9 +46,22 @@ type Range
|
|||||||
res = it initial this.start this.end
|
res = it initial this.start this.end
|
||||||
res
|
res
|
||||||
|
|
||||||
|
## Checks whether `predicate` is satisfied for every number in this range.
|
||||||
|
every predicate =
|
||||||
|
it start end = if start==end then True else
|
||||||
|
r = predicate start
|
||||||
|
if r then (it start+1 end) else False
|
||||||
|
res = it this.start this.end
|
||||||
|
res
|
||||||
|
|
||||||
type Math
|
type Math
|
||||||
|
|
||||||
## The mathematical constant pi, equal to the ratio of a circle circumference
|
## The mathematical constant pi, equal to the ratio of a circle circumference
|
||||||
to its diameter.
|
to its diameter.
|
||||||
Math.pi : Decimal
|
Math.pi : Decimal
|
||||||
Math.pi = 3.141592653589793
|
Math.pi = 3.141592653589793
|
||||||
|
|
||||||
|
## Equality definition for types defining `==`.
|
||||||
|
|
||||||
|
TODO remove when operators can be defined in-language.
|
||||||
|
Any.equals that = this == that
|
||||||
|
@ -82,4 +82,4 @@ Integer.upto n = Range this n
|
|||||||
|
|
||||||
Returns `True` when `this` and `that` are at most `epsilon` apart.
|
Returns `True` when `this` and `that` are at most `epsilon` apart.
|
||||||
Number.equals : Number -> Number -> Boolean
|
Number.equals : Number -> Number -> Boolean
|
||||||
Number.equals that epsilon = (this - that).abs <= epsilon
|
Number.equals that epsilon=0.0 = (this - that).abs <= epsilon
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from Builtins import System
|
from Builtins import System
|
||||||
|
from Base import all
|
||||||
|
|
||||||
type Os
|
type Os
|
||||||
type Linux
|
type Linux
|
||||||
@ -10,7 +11,7 @@ type Os
|
|||||||
Create an Os object from text.
|
Create an Os object from text.
|
||||||
from_text: Text -> Os
|
from_text: Text -> Os
|
||||||
from_text os =
|
from_text os =
|
||||||
if os == "linux" then Linux else if os == "macos" then MacOS else if os == "windows" then Windows else Unknown
|
if os.equals "linux" then Linux else if os.equals "macos" then MacOS else if os.equals "windows" then Windows else Unknown
|
||||||
|
|
||||||
## Return the type of operating system.
|
## Return the type of operating system.
|
||||||
|
|
||||||
|
@ -22,16 +22,18 @@ Suite.is_fail = this.specs.any is_fail
|
|||||||
type Assertion
|
type Assertion
|
||||||
type Success
|
type Success
|
||||||
type Failure message
|
type Failure message
|
||||||
|
type Pending
|
||||||
|
|
||||||
is_fail = case this of
|
is_fail = case this of
|
||||||
Success -> False
|
Success -> False
|
||||||
Failure _ -> True
|
Failure _ -> True
|
||||||
|
Pending -> False
|
||||||
|
|
||||||
## Fail a test with the given message.
|
## Fail a test with the given message.
|
||||||
fail message = Panic.throw (Failure message)
|
fail message = Panic.throw (Failure message)
|
||||||
|
|
||||||
## Asserts that `this` value is equal to the expected value.
|
## Asserts that `this` value is equal to the expected value.
|
||||||
Any.should_equal that = case this == that of
|
Any.should_equal that = case this.equals that of
|
||||||
True -> Success
|
True -> Success
|
||||||
False ->
|
False ->
|
||||||
msg = this.to_text + " did not equal " + that.to_text + "."
|
msg = this.to_text + " did not equal " + that.to_text + "."
|
||||||
@ -64,6 +66,8 @@ Spec.print_report =
|
|||||||
Failure msg ->
|
Failure msg ->
|
||||||
IO.print_err (" - [FAILED] " + behavior.name)
|
IO.print_err (" - [FAILED] " + behavior.name)
|
||||||
IO.print_err (" Reason: " + msg)
|
IO.print_err (" Reason: " + msg)
|
||||||
|
Pending ->
|
||||||
|
IO.print_err (" - [PENDING] " + behavior.name)
|
||||||
|
|
||||||
## Creates a new test group, desribing properties of the object
|
## Creates a new test group, desribing properties of the object
|
||||||
described by `this`.
|
described by `this`.
|
||||||
@ -93,16 +97,21 @@ Text.describe ~behaviors =
|
|||||||
2+3 . should_equal 5
|
2+3 . should_equal 5
|
||||||
it "should define multiplication" <|
|
it "should define multiplication" <|
|
||||||
2*3 . should_equal 6
|
2*3 . should_equal 6
|
||||||
Text.it ~behavior =
|
Text.it ~behavior pending=False =
|
||||||
|
result = if pending then Pending else here.run_spec behavior
|
||||||
spec = State.get Spec
|
spec = State.get Spec
|
||||||
|
new_spec = Spec spec.name (Cons (Behavior this result) spec.behaviors)
|
||||||
|
State.put Spec new_spec
|
||||||
|
|
||||||
|
run_spec ~behavior =
|
||||||
maybeExc = case Panic.recover behavior of
|
maybeExc = case Panic.recover behavior of
|
||||||
_ -> Success
|
_ -> Success
|
||||||
result = maybeExc.catch ex->
|
result = maybeExc.catch ex->
|
||||||
case ex of
|
case ex of
|
||||||
Failure _ -> ex
|
Failure _ -> ex
|
||||||
_ -> Failure ("Unexpected error has been thrown: " + ex.to_text)
|
_ -> Failure ("Unexpected error has been thrown: " + ex.to_text)
|
||||||
new_spec = Spec spec.name (Cons (Behavior this result) spec.behaviors)
|
result
|
||||||
State.put Spec new_spec
|
|
||||||
|
|
||||||
## Runs a suite of tests, consisting of multiple `describe` blocks.
|
## Runs a suite of tests, consisting of multiple `describe` blocks.
|
||||||
|
|
||||||
|
105
distribution/std-lib/Base/src/Text/Extensions.enso
Normal file
105
distribution/std-lib/Base/src/Text/Extensions.enso
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
from Base import all
|
||||||
|
from Builtins import Text, Prim_Text_Helpers
|
||||||
|
|
||||||
|
from Builtins export Text
|
||||||
|
|
||||||
|
polyglot java import com.ibm.icu.text.BreakIterator
|
||||||
|
polyglot java import org.enso.base.Text_Utils
|
||||||
|
|
||||||
|
## Applies `function` to each character in `this`.
|
||||||
|
|
||||||
|
A character is defined as an Extended Grapheme Cluster, see
|
||||||
|
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||||
|
|
||||||
|
This is the smallest unit that still has semantic meaning in most
|
||||||
|
text-processing applications.
|
||||||
|
Text.each : (Text -> Any) -> Unit
|
||||||
|
Text.each function =
|
||||||
|
iterator = BreakIterator.getCharacterInstance []
|
||||||
|
iterator.setText [this]
|
||||||
|
|
||||||
|
fst = iterator.first []
|
||||||
|
nxt = iterator.next []
|
||||||
|
|
||||||
|
iterate prev nxt = if nxt == -1 then Unit else
|
||||||
|
function (Text_Utils.substring [this, prev, nxt])
|
||||||
|
next_nxt = iterator.next []
|
||||||
|
iterate nxt next_nxt
|
||||||
|
iterate fst nxt
|
||||||
|
Unit
|
||||||
|
|
||||||
|
## Returns a vector containing all characters in the given text.
|
||||||
|
|
||||||
|
A character is defined as an Extended Grapheme Cluster, see
|
||||||
|
[Unicode Standard Annex #29](https://unicode.org/reports/tr29/).
|
||||||
|
|
||||||
|
This is the smallest unit that still has semantic meaning in most
|
||||||
|
text-processing applications.
|
||||||
|
Text.characters : Vector
|
||||||
|
Text.characters =
|
||||||
|
bldr = Vector.new_builder
|
||||||
|
this.each bldr.append
|
||||||
|
r = bldr.to_vector
|
||||||
|
r
|
||||||
|
|
||||||
|
## Takes a separator string and returns a vector resulting from splitting
|
||||||
|
`this` on each occurence of `separator`.
|
||||||
|
|
||||||
|
> Example
|
||||||
|
In the following example, we'll split the text into a vector of
|
||||||
|
comma-separated items:
|
||||||
|
"ham,eggs,cheese,tomatoes".split_at ","
|
||||||
|
The code above returns:
|
||||||
|
["ham", "eggs", "cheese", "tomatoes"]
|
||||||
|
Text.split_at : Text -> Vector
|
||||||
|
Text.split_at separator =
|
||||||
|
Vector.from_polyglot_array (Text_Utils.split_at [this, separator])
|
||||||
|
|
||||||
|
## Checks whether `this` is equal to `that`.
|
||||||
|
|
||||||
|
The definition of equality includes Unicode canonicalization. I.e. two texts
|
||||||
|
are equal if they are identical after canonical decomposition. This ensures
|
||||||
|
that different ways of expressing the same character in the underlying
|
||||||
|
binary representation are considered equal.
|
||||||
|
|
||||||
|
> Example
|
||||||
|
The string 'é' (i.e. the character U+00E9, LATIN SMALL LETTER E WITH
|
||||||
|
ACUTE) is canonically the same as the string 'e\u0301' (i.e. the letter
|
||||||
|
`e` followed by U+0301, COMBINING ACUTE ACCENT). Therefore:
|
||||||
|
('é'.equals 'e\u0301') == True
|
||||||
|
Text.equals : Text -> Boolean
|
||||||
|
Text.equals that = Text_Utils.equals [this, that]
|
||||||
|
|
||||||
|
## Returns a vector containing bytes representing the UTF-8 encoding of the
|
||||||
|
input text.
|
||||||
|
|
||||||
|
This is useful for low-level operations, such as binary data encoding and
|
||||||
|
decoding.
|
||||||
|
Text.utf_8 : Vector
|
||||||
|
Text.utf_8 = Vector.from_polyglot_array (Text_Utils.get_bytes [this])
|
||||||
|
|
||||||
|
## Takes an array of bytes and returns Text resulting from decoding it as
|
||||||
|
UTF-8.
|
||||||
|
|
||||||
|
This is useful for low-level operations, such as binary data encoding and
|
||||||
|
decoding.
|
||||||
|
Text.from_utf_8 : Vector -> Text
|
||||||
|
Text.from_utf_8 bytes = Text_Utils.from_utf_8 [bytes.to_array]
|
||||||
|
|
||||||
|
## Returns a vector containing integers representing the Unicode codepoints of
|
||||||
|
the input text.
|
||||||
|
|
||||||
|
This is useful for low-level operations, such as binary data encoding and
|
||||||
|
decoding.
|
||||||
|
Text.codepoints : Vector
|
||||||
|
Text.codepoints =
|
||||||
|
Vector.from_polyglot_array (Text_Utils.get_codepoints [this])
|
||||||
|
|
||||||
|
## Takes an array of numbers and returns the text resulting from interpreting it
|
||||||
|
as a sequence of Unicode codepoints.
|
||||||
|
|
||||||
|
This is useful for low-level operations, such as binary data encoding and
|
||||||
|
decoding.
|
||||||
|
Text.from_codepoints : Vector -> Text
|
||||||
|
Text.from_codepoints codepoints = Text_Utils.from_codepoints [codepoints.to_array]
|
||||||
|
|
@ -25,6 +25,40 @@ type Vector
|
|||||||
at : Number -> Any
|
at : Number -> Any
|
||||||
at index = this.to_array.at index
|
at index = this.to_array.at index
|
||||||
|
|
||||||
|
## Creates a new vector builder instance.
|
||||||
|
|
||||||
|
A vector builder is a mutable data structure, that allows for gathering
|
||||||
|
a number of elements and then converting them into a vector. This is
|
||||||
|
particularly useful when the number of elements is not known upfront.
|
||||||
|
|
||||||
|
> Example
|
||||||
|
In the following example we'll read items from the standard input,
|
||||||
|
until the string "end" is entered by the user and then return a vector
|
||||||
|
containing all items.
|
||||||
|
from Base import all
|
||||||
|
|
||||||
|
main =
|
||||||
|
builder = Vector.new_builder
|
||||||
|
do_read =
|
||||||
|
item = IO.readln
|
||||||
|
if item.equals "end" then Unit else
|
||||||
|
builder.append item
|
||||||
|
do_read
|
||||||
|
do_read
|
||||||
|
vec = builder.to_vector
|
||||||
|
IO.println vec
|
||||||
|
new_builder : Builder
|
||||||
|
new_builder = Builder.new
|
||||||
|
|
||||||
|
## Converts a polyglot value representing an array into a vector. This is
|
||||||
|
useful when wrapping polyglot APIs for further use in Enso.
|
||||||
|
from_polyglot_array : Any -> Vector
|
||||||
|
from_polyglot_array arr =
|
||||||
|
a = Array.new arr.length
|
||||||
|
0.upto arr.length . each i->
|
||||||
|
a.set_at i (arr.at i)
|
||||||
|
Vector a
|
||||||
|
|
||||||
## Returns the number of elements stored in this vector.
|
## Returns the number of elements stored in this vector.
|
||||||
length : Number
|
length : Number
|
||||||
length = this.to_array.length
|
length = this.to_array.length
|
||||||
@ -104,3 +138,71 @@ type Vector
|
|||||||
folder = str -> ix -> str + ", " + (arr.at ix).to_text
|
folder = str -> ix -> str + ", " + (arr.at ix).to_text
|
||||||
tail_elems = 1.upto arr.length . fold "" folder
|
tail_elems = 1.upto arr.length . fold "" folder
|
||||||
"[" + (arr.at 0 . to_text) + tail_elems + "]"
|
"[" + (arr.at 0 . to_text) + tail_elems + "]"
|
||||||
|
|
||||||
|
## Checks whether this vector is equal to `that`. Two vectors are considered
|
||||||
|
equal, when they have the same length and their items are pairwise equal.
|
||||||
|
equals : Vector -> Boolean
|
||||||
|
equals that =
|
||||||
|
arr1 = this.to_array
|
||||||
|
arr2 = that.to_array
|
||||||
|
eq_at i = (arr1.at i) . equals (arr2.at i)
|
||||||
|
r = if arr1.length == arr2.length then 0.upto arr1.length . every eq_at else False
|
||||||
|
r
|
||||||
|
|
||||||
|
## A builder type for Enso vectors.
|
||||||
|
|
||||||
|
A vector builder is a mutable data structure, that allows to gather a
|
||||||
|
number of elements and then convert them to a vector. This is
|
||||||
|
particularly useful when the number of elements is not known upfront.
|
||||||
|
|
||||||
|
> Example
|
||||||
|
In the following example we'll read items from the standard input,
|
||||||
|
until the string "end" is entered by the user and then return a vector
|
||||||
|
containing all items.
|
||||||
|
from Base import all
|
||||||
|
|
||||||
|
main =
|
||||||
|
builder = Vector.new_builder
|
||||||
|
do_read =
|
||||||
|
item = IO.readln
|
||||||
|
if item.equals "end" then Unit else
|
||||||
|
builder.append item
|
||||||
|
do_read
|
||||||
|
do_read
|
||||||
|
vec = builder.to_vector
|
||||||
|
IO.println vec
|
||||||
|
type Builder
|
||||||
|
type Builder to_array length
|
||||||
|
|
||||||
|
## Creates a new builder.
|
||||||
|
new = Builder (Array.new 1) 0
|
||||||
|
|
||||||
|
## Returns the current capacity (i.e. the size of the underlying storage)
|
||||||
|
of this builder.
|
||||||
|
capacity = this.to_array.length
|
||||||
|
|
||||||
|
## Appends a new element into this builder.
|
||||||
|
append : Any -> Unit
|
||||||
|
append item = case this.capacity > this.length of
|
||||||
|
True ->
|
||||||
|
this.to_array.set_at this.length item
|
||||||
|
Unsafe.set_atom_field this 1 (this.length + 1)
|
||||||
|
False ->
|
||||||
|
old_array = this.to_array
|
||||||
|
new_array = Array.new old_array.length*2
|
||||||
|
0.upto this.length . each i->
|
||||||
|
new_array.set_at i (old_array.at i)
|
||||||
|
Unit
|
||||||
|
Unsafe.set_atom_field this 0 new_array
|
||||||
|
this.append item
|
||||||
|
Unit
|
||||||
|
|
||||||
|
## Converts this builder to a vector containing all the appended elements.
|
||||||
|
to_vector : Vector
|
||||||
|
to_vector =
|
||||||
|
old_array = this.to_array
|
||||||
|
new_array = Array.new this.length
|
||||||
|
0.upto this.length . each i->
|
||||||
|
new_array.set_at i (old_array.at i)
|
||||||
|
Unit
|
||||||
|
Vector new_array
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
Lists of 1 third-party dependencies.
|
||||||
|
(Unicode/ICU License) ICU4J (com.ibm.icu:icu4j:67.1 - http://icu-project.org/)
|
@ -0,0 +1,414 @@
|
|||||||
|
COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
|
||||||
|
|
||||||
|
Copyright © 1991-2020 Unicode, Inc. All rights reserved.
|
||||||
|
Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Unicode data files and any associated documentation
|
||||||
|
(the "Data Files") or Unicode software and any associated documentation
|
||||||
|
(the "Software") to deal in the Data Files or Software
|
||||||
|
without restriction, including without limitation the rights to use,
|
||||||
|
copy, modify, merge, publish, distribute, and/or sell copies of
|
||||||
|
the Data Files or Software, and to permit persons to whom the Data Files
|
||||||
|
or Software are furnished to do so, provided that either
|
||||||
|
(a) this copyright and permission notice appear with all copies
|
||||||
|
of the Data Files or Software, or
|
||||||
|
(b) this copyright and permission notice appear in associated
|
||||||
|
Documentation.
|
||||||
|
|
||||||
|
THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
|
||||||
|
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
|
||||||
|
NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
|
||||||
|
DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THE DATA FILES OR SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of a copyright holder
|
||||||
|
shall not be used in advertising or otherwise to promote the sale,
|
||||||
|
use or other dealings in these Data Files or Software without prior
|
||||||
|
written authorization of the copyright holder.
|
||||||
|
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Third-Party Software Licenses
|
||||||
|
|
||||||
|
This section contains third-party software notices and/or additional
|
||||||
|
terms for licensed third-party software components included within ICU
|
||||||
|
libraries.
|
||||||
|
|
||||||
|
1. ICU License - ICU 1.8.1 to ICU 57.1
|
||||||
|
|
||||||
|
COPYRIGHT AND PERMISSION NOTICE
|
||||||
|
|
||||||
|
Copyright (c) 1995-2016 International Business Machines Corporation and others
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, and/or sell copies of the Software, and to permit persons
|
||||||
|
to whom the Software is furnished to do so, provided that the above
|
||||||
|
copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
the Software and that both the above copyright notice(s) and this
|
||||||
|
permission notice appear in supporting documentation.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||||
|
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
|
||||||
|
SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
|
||||||
|
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||||
|
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of a copyright holder
|
||||||
|
shall not be used in advertising or otherwise to promote the sale, use
|
||||||
|
or other dealings in this Software without prior written authorization
|
||||||
|
of the copyright holder.
|
||||||
|
|
||||||
|
All trademarks and registered trademarks mentioned herein are the
|
||||||
|
property of their respective owners.
|
||||||
|
|
||||||
|
2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
|
||||||
|
|
||||||
|
# The Google Chrome software developed by Google is licensed under
|
||||||
|
# the BSD license. Other software included in this distribution is
|
||||||
|
# provided under other licenses, as set forth below.
|
||||||
|
#
|
||||||
|
# The BSD License
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
# Copyright (C) 2006-2008, Google Inc.
|
||||||
|
#
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
# Redistributions in binary form must reproduce the above
|
||||||
|
# copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer in the documentation and/or other materials provided with
|
||||||
|
# the distribution.
|
||||||
|
# Neither the name of Google Inc. nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived from
|
||||||
|
# this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The word list in cjdict.txt are generated by combining three word lists
|
||||||
|
# listed below with further processing for compound word breaking. The
|
||||||
|
# frequency is generated with an iterative training against Google web
|
||||||
|
# corpora.
|
||||||
|
#
|
||||||
|
# * Libtabe (Chinese)
|
||||||
|
# - https://sourceforge.net/project/?group_id=1519
|
||||||
|
# - Its license terms and conditions are shown below.
|
||||||
|
#
|
||||||
|
# * IPADIC (Japanese)
|
||||||
|
# - http://chasen.aist-nara.ac.jp/chasen/distribution.html
|
||||||
|
# - Its license terms and conditions are shown below.
|
||||||
|
#
|
||||||
|
# ---------COPYING.libtabe ---- BEGIN--------------------
|
||||||
|
#
|
||||||
|
# /*
|
||||||
|
# * Copyright (c) 1999 TaBE Project.
|
||||||
|
# * Copyright (c) 1999 Pai-Hsiang Hsiao.
|
||||||
|
# * All rights reserved.
|
||||||
|
# *
|
||||||
|
# * Redistribution and use in source and binary forms, with or without
|
||||||
|
# * modification, are permitted provided that the following conditions
|
||||||
|
# * are met:
|
||||||
|
# *
|
||||||
|
# * . Redistributions of source code must retain the above copyright
|
||||||
|
# * notice, this list of conditions and the following disclaimer.
|
||||||
|
# * . Redistributions in binary form must reproduce the above copyright
|
||||||
|
# * notice, this list of conditions and the following disclaimer in
|
||||||
|
# * the documentation and/or other materials provided with the
|
||||||
|
# * distribution.
|
||||||
|
# * . Neither the name of the TaBE Project nor the names of its
|
||||||
|
# * contributors may be used to endorse or promote products derived
|
||||||
|
# * from this software without specific prior written permission.
|
||||||
|
# *
|
||||||
|
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
# * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
# * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# */
|
||||||
|
#
|
||||||
|
# /*
|
||||||
|
# * Copyright (c) 1999 Computer Systems and Communication Lab,
|
||||||
|
# * Institute of Information Science, Academia
|
||||||
|
# * Sinica. All rights reserved.
|
||||||
|
# *
|
||||||
|
# * Redistribution and use in source and binary forms, with or without
|
||||||
|
# * modification, are permitted provided that the following conditions
|
||||||
|
# * are met:
|
||||||
|
# *
|
||||||
|
# * . Redistributions of source code must retain the above copyright
|
||||||
|
# * notice, this list of conditions and the following disclaimer.
|
||||||
|
# * . Redistributions in binary form must reproduce the above copyright
|
||||||
|
# * notice, this list of conditions and the following disclaimer in
|
||||||
|
# * the documentation and/or other materials provided with the
|
||||||
|
# * distribution.
|
||||||
|
# * . Neither the name of the Computer Systems and Communication Lab
|
||||||
|
# * nor the names of its contributors may be used to endorse or
|
||||||
|
# * promote products derived from this software without specific
|
||||||
|
# * prior written permission.
|
||||||
|
# *
|
||||||
|
# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
# * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
# * OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# */
|
||||||
|
#
|
||||||
|
# Copyright 1996 Chih-Hao Tsai @ Beckman Institute,
|
||||||
|
# University of Illinois
|
||||||
|
# c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4
|
||||||
|
#
|
||||||
|
# ---------------COPYING.libtabe-----END--------------------------------
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ---------------COPYING.ipadic-----BEGIN-------------------------------
|
||||||
|
#
|
||||||
|
# Copyright 2000, 2001, 2002, 2003 Nara Institute of Science
|
||||||
|
# and Technology. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Use, reproduction, and distribution of this software is permitted.
|
||||||
|
# Any copy of this software, whether in its original form or modified,
|
||||||
|
# must include both the above copyright notice and the following
|
||||||
|
# paragraphs.
|
||||||
|
#
|
||||||
|
# Nara Institute of Science and Technology (NAIST),
|
||||||
|
# the copyright holders, disclaims all warranties with regard to this
|
||||||
|
# software, including all implied warranties of merchantability and
|
||||||
|
# fitness, in no event shall NAIST be liable for
|
||||||
|
# any special, indirect or consequential damages or any damages
|
||||||
|
# whatsoever resulting from loss of use, data or profits, whether in an
|
||||||
|
# action of contract, negligence or other tortuous action, arising out
|
||||||
|
# of or in connection with the use or performance of this software.
|
||||||
|
#
|
||||||
|
# A large portion of the dictionary entries
|
||||||
|
# originate from ICOT Free Software. The following conditions for ICOT
|
||||||
|
# Free Software applies to the current dictionary as well.
|
||||||
|
#
|
||||||
|
# Each User may also freely distribute the Program, whether in its
|
||||||
|
# original form or modified, to any third party or parties, PROVIDED
|
||||||
|
# that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear
|
||||||
|
# on, or be attached to, the Program, which is distributed substantially
|
||||||
|
# in the same form as set out herein and that such intended
|
||||||
|
# distribution, if actually made, will neither violate or otherwise
|
||||||
|
# contravene any of the laws and regulations of the countries having
|
||||||
|
# jurisdiction over the User or the intended distribution itself.
|
||||||
|
#
|
||||||
|
# NO WARRANTY
|
||||||
|
#
|
||||||
|
# The program was produced on an experimental basis in the course of the
|
||||||
|
# research and development conducted during the project and is provided
|
||||||
|
# to users as so produced on an experimental basis. Accordingly, the
|
||||||
|
# program is provided without any warranty whatsoever, whether express,
|
||||||
|
# implied, statutory or otherwise. The term "warranty" used herein
|
||||||
|
# includes, but is not limited to, any warranty of the quality,
|
||||||
|
# performance, merchantability and fitness for a particular purpose of
|
||||||
|
# the program and the nonexistence of any infringement or violation of
|
||||||
|
# any right of any third party.
|
||||||
|
#
|
||||||
|
# Each user of the program will agree and understand, and be deemed to
|
||||||
|
# have agreed and understood, that there is no warranty whatsoever for
|
||||||
|
# the program and, accordingly, the entire risk arising from or
|
||||||
|
# otherwise connected with the program is assumed by the user.
|
||||||
|
#
|
||||||
|
# Therefore, neither ICOT, the copyright holder, or any other
|
||||||
|
# organization that participated in or was otherwise related to the
|
||||||
|
# development of the program and their respective officials, directors,
|
||||||
|
# officers and other employees shall be held liable for any and all
|
||||||
|
# damages, including, without limitation, general, special, incidental
|
||||||
|
# and consequential damages, arising out of or otherwise in connection
|
||||||
|
# with the use or inability to use the program or any product, material
|
||||||
|
# or result produced or otherwise obtained by using the program,
|
||||||
|
# regardless of whether they have been advised of, or otherwise had
|
||||||
|
# knowledge of, the possibility of such damages at any time during the
|
||||||
|
# project or thereafter. Each user will be deemed to have agreed to the
|
||||||
|
# foregoing by his or her commencement of use of the program. The term
|
||||||
|
# "use" as used herein includes, but is not limited to, the use,
|
||||||
|
# modification, copying and distribution of the program and the
|
||||||
|
# production of secondary products from the program.
|
||||||
|
#
|
||||||
|
# In the case where the program, whether in its original form or
|
||||||
|
# modified, was distributed or delivered to or received by a user from
|
||||||
|
# any person, organization or entity other than ICOT, unless it makes or
|
||||||
|
# grants independently of ICOT any specific warranty to the user in
|
||||||
|
# writing, such person, organization or entity, will also be exempted
|
||||||
|
# from and not be held liable to the user for any such damages as noted
|
||||||
|
# above as far as the program is concerned.
|
||||||
|
#
|
||||||
|
# ---------------COPYING.ipadic-----END----------------------------------
|
||||||
|
|
||||||
|
3. Lao Word Break Dictionary Data (laodict.txt)
|
||||||
|
|
||||||
|
# Copyright (c) 2013 International Business Machines Corporation
|
||||||
|
# and others. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Project: https://github.com/veer66/lao-dictionary
|
||||||
|
# Dictionary: https://github.com/veer66/lao-dictionary/blob/master/Lao-Dictionary.txt
|
||||||
|
# License: https://github.com/veer66/lao-dictionary/blob/master/Lao-Dictionary-LICENSE.txt
|
||||||
|
# (copied below)
|
||||||
|
#
|
||||||
|
# This file is derived from the above dictionary, with slight
|
||||||
|
# modifications.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer. Redistributions in
|
||||||
|
# binary form must reproduce the above copyright notice, this list of
|
||||||
|
# conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
# OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
4. Burmese Word Break Dictionary Data (burmesedict.txt)
|
||||||
|
|
||||||
|
# Copyright (c) 2014 International Business Machines Corporation
|
||||||
|
# and others. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# This list is part of a project hosted at:
|
||||||
|
# github.com/kanyawtech/myanmar-karen-word-lists
|
||||||
|
#
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2013, LeRoy Benjamin Sharon
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met: Redistributions of source code must retain the above
|
||||||
|
# copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer. Redistributions in binary form must reproduce the
|
||||||
|
# above copyright notice, this list of conditions and the following
|
||||||
|
# disclaimer in the documentation and/or other materials provided
|
||||||
|
# with the distribution.
|
||||||
|
#
|
||||||
|
# Neither the name Myanmar Karen Word Lists, nor the names of its
|
||||||
|
# contributors may be used to endorse or promote products derived
|
||||||
|
# from this software without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
||||||
|
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||||
|
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
# SUCH DAMAGE.
|
||||||
|
# --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
5. Time Zone Database
|
||||||
|
|
||||||
|
ICU uses the public domain data and code derived from Time Zone
|
||||||
|
Database for its time zone support. The ownership of the TZ database
|
||||||
|
is explained in BCP 175: Procedure for Maintaining the Time Zone
|
||||||
|
Database section 7.
|
||||||
|
|
||||||
|
# 7. Database Ownership
|
||||||
|
#
|
||||||
|
# The TZ database itself is not an IETF Contribution or an IETF
|
||||||
|
# document. Rather it is a pre-existing and regularly updated work
|
||||||
|
# that is in the public domain, and is intended to remain in the
|
||||||
|
# public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do
|
||||||
|
# not apply to the TZ Database or contributions that individuals make
|
||||||
|
# to it. Should any claims be made and substantiated against the TZ
|
||||||
|
# Database, the organization that is providing the IANA
|
||||||
|
# Considerations defined in this RFC, under the memorandum of
|
||||||
|
# understanding with the IETF, currently ICANN, may act in accordance
|
||||||
|
# with all competent court orders. No ownership claims will be made
|
||||||
|
# by ICANN or the IETF Trust on the database or the code. Any person
|
||||||
|
# making a contribution to the database or code waives all rights to
|
||||||
|
# future claims in that contribution or in the TZ Database.
|
||||||
|
|
||||||
|
6. Google double-conversion
|
||||||
|
|
||||||
|
Copyright 2006-2011, the V8 project authors. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -138,6 +138,7 @@ In order to build and run Enso you will need the following tools:
|
|||||||
|
|
||||||
- [sbt](https://www.scala-sbt.org/) with the same version as specified in
|
- [sbt](https://www.scala-sbt.org/) with the same version as specified in
|
||||||
[`project/build.properties`](../project/build.properties).
|
[`project/build.properties`](../project/build.properties).
|
||||||
|
- [Maven](https://maven.apache.org/) with version at least 3.6.3.
|
||||||
- [GraalVM](https://www.graalvm.org/) with the same version as described in the
|
- [GraalVM](https://www.graalvm.org/) with the same version as described in the
|
||||||
[`build.sbt`](../build.sbt) file, configured as your default JVM. GraalVM is
|
[`build.sbt`](../build.sbt) file, configured as your default JVM. GraalVM is
|
||||||
distributed for different Java versions, so you need a GraalVM distribution
|
distributed for different Java versions, so you need a GraalVM distribution
|
||||||
|
@ -92,6 +92,13 @@ files are included by the CI build within the built artifacts.
|
|||||||
|
|
||||||
### Engine Components
|
### Engine Components
|
||||||
|
|
||||||
|
#### Standard Library
|
||||||
|
|
||||||
|
The third-party licenses for Java extensions of the standard library are
|
||||||
|
gathered in the `third-party-licenses` directory in the `Base` library. The
|
||||||
|
gathering process is automatic, triggered by the `package` goal of the
|
||||||
|
associated Maven configuration file.
|
||||||
|
|
||||||
> The actionables for this section are:
|
> The actionables for this section are:
|
||||||
>
|
>
|
||||||
> - The engine components as distributed as a JAR archive that everyone can
|
> - The engine components as distributed as a JAR archive that everyone can
|
||||||
|
@ -4,6 +4,7 @@ import java.io.{InputStream, OutputStream, PrintStream, PrintWriter, Writer}
|
|||||||
import java.util.Scanner
|
import java.util.Scanner
|
||||||
|
|
||||||
import org.enso.polyglot.debugger.{ReplExecutor, SessionManager}
|
import org.enso.polyglot.debugger.{ReplExecutor, SessionManager}
|
||||||
|
import org.jline.reader.impl.DefaultParser
|
||||||
import org.jline.reader.{LineReader, LineReaderBuilder}
|
import org.jline.reader.{LineReader, LineReaderBuilder}
|
||||||
import org.jline.terminal.{Terminal, TerminalBuilder}
|
import org.jline.terminal.{Terminal, TerminalBuilder}
|
||||||
|
|
||||||
@ -98,8 +99,10 @@ case class SimpleReplIO(in: InputStream, out: OutputStream) extends ReplIO {
|
|||||||
case class TerminalIO() extends ReplIO {
|
case class TerminalIO() extends ReplIO {
|
||||||
private val terminal: Terminal =
|
private val terminal: Terminal =
|
||||||
TerminalBuilder.builder().system(true).build()
|
TerminalBuilder.builder().system(true).build()
|
||||||
|
private val parser: DefaultParser = new DefaultParser()
|
||||||
|
parser.setEscapeChars(null)
|
||||||
private val lineReader: LineReader =
|
private val lineReader: LineReader =
|
||||||
LineReaderBuilder.builder().terminal(terminal).build()
|
LineReaderBuilder.builder().parser(parser).terminal(terminal).build()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask user for a line of input, using given prompt
|
* Ask user for a line of input, using given prompt
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
package org.enso.interpreter.bench;
|
package org.enso.interpreter.bench;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import org.openjdk.jmh.results.RunResult;
|
import org.openjdk.jmh.results.RunResult;
|
||||||
import org.openjdk.jmh.runner.BenchmarkList;
|
import org.openjdk.jmh.runner.BenchmarkList;
|
||||||
import org.openjdk.jmh.runner.BenchmarkListEntry;
|
import org.openjdk.jmh.runner.BenchmarkListEntry;
|
||||||
@ -14,6 +8,12 @@ import org.openjdk.jmh.runner.RunnerException;
|
|||||||
import org.openjdk.jmh.runner.options.Options;
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/** Runner class for the benchmarks. Discovers, runs and reports benchmark results. */
|
/** Runner class for the benchmarks. Discovers, runs and reports benchmark results. */
|
||||||
public class BenchmarksRunner {
|
public class BenchmarksRunner {
|
||||||
public static final File REPORT_FILE = new File("./bench-report.xml");
|
public static final File REPORT_FILE = new File("./bench-report.xml");
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.enso.interpreter.bench.benchmarks.semantic;
|
package org.enso.interpreter.bench.benchmarks.semantic;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.enso.interpreter.bench.fixtures.semantic.RecursionFixtures;
|
import org.enso.interpreter.bench.fixtures.semantic.RecursionFixtures;
|
||||||
import org.enso.interpreter.test.DefaultInterpreterRunner;
|
import org.enso.interpreter.test.DefaultInterpreterRunner;
|
||||||
|
@ -17,11 +17,13 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.node.expression.debug.CaptureResultScopeNode;
|
import org.enso.interpreter.node.expression.debug.CaptureResultScopeNode;
|
||||||
import org.enso.interpreter.node.expression.debug.EvalNode;
|
import org.enso.interpreter.node.expression.debug.EvalNode;
|
||||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.scope.FramePointer;
|
import org.enso.interpreter.runtime.scope.FramePointer;
|
||||||
import org.enso.interpreter.runtime.state.Stateful;
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
import org.enso.polyglot.debugger.DebugServerInfo;
|
import org.enso.polyglot.debugger.DebugServerInfo;
|
||||||
@ -47,28 +49,28 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Env env) {
|
protected void onCreate(Env env) {
|
||||||
SourceSectionFilter filter =
|
SourceSectionFilter filter =
|
||||||
SourceSectionFilter.newBuilder().tagIs(DebuggerTags.AlwaysHalt.class)
|
SourceSectionFilter.newBuilder().tagIs(DebuggerTags.AlwaysHalt.class).build();
|
||||||
.build();
|
|
||||||
this.env = env;
|
this.env = env;
|
||||||
|
|
||||||
DebuggerMessageHandler handler = new DebuggerMessageHandler();
|
DebuggerMessageHandler handler = new DebuggerMessageHandler();
|
||||||
try {
|
try {
|
||||||
MessageEndpoint client =
|
MessageEndpoint client = env.startServer(URI.create(DebugServerInfo.URI), handler);
|
||||||
env.startServer(URI.create(DebugServerInfo.URI), handler);
|
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
handler.setClient(client);
|
handler.setClient(client);
|
||||||
Instrumenter instrumenter = env.getInstrumenter();
|
Instrumenter instrumenter = env.getInstrumenter();
|
||||||
instrumenter.attachExecutionEventFactory(filter, ctx ->
|
instrumenter.attachExecutionEventFactory(
|
||||||
new ReplExecutionEventNode(ctx, handler, env.getLogger(ReplExecutionEventNode.class)));
|
filter,
|
||||||
|
ctx ->
|
||||||
|
new ReplExecutionEventNode(
|
||||||
|
ctx, handler, env.getLogger(ReplExecutionEventNode.class)));
|
||||||
} else {
|
} else {
|
||||||
env.getLogger(ReplDebuggerInstrument.class)
|
env.getLogger(ReplDebuggerInstrument.class)
|
||||||
.warning("ReplDebuggerInstrument was initialized, " +
|
.warning("ReplDebuggerInstrument was initialized, " + "but no client connected");
|
||||||
"but no client connected");
|
|
||||||
}
|
}
|
||||||
} catch (MessageTransport.VetoException e) {
|
} catch (MessageTransport.VetoException e) {
|
||||||
env.getLogger(ReplDebuggerInstrument.class)
|
env.getLogger(ReplDebuggerInstrument.class)
|
||||||
.warning("ReplDebuggerInstrument was initialized, " +
|
.warning(
|
||||||
"but client connection has been vetoed");
|
"ReplDebuggerInstrument was initialized, " + "but client connection has been vetoed");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@ -85,6 +87,7 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
/** The actual node that's installed as a probe on any node the instrument was launched for. */
|
/** The actual node that's installed as a probe on any node the instrument was launched for. */
|
||||||
public static class ReplExecutionEventNode extends ExecutionEventNode {
|
public static class ReplExecutionEventNode extends ExecutionEventNode {
|
||||||
private @Child EvalNode evalNode = EvalNode.buildWithResultScopeCapture();
|
private @Child EvalNode evalNode = EvalNode.buildWithResultScopeCapture();
|
||||||
|
private @Child ToJavaStringNode toJavaStringNode = ToJavaStringNode.build();
|
||||||
|
|
||||||
private ReplExecutionEventNodeState nodeState;
|
private ReplExecutionEventNodeState nodeState;
|
||||||
|
|
||||||
@ -92,7 +95,8 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
private DebuggerMessageHandler handler;
|
private DebuggerMessageHandler handler;
|
||||||
private TruffleLogger logger;
|
private TruffleLogger logger;
|
||||||
|
|
||||||
private ReplExecutionEventNode(EventContext eventContext, DebuggerMessageHandler handler, TruffleLogger logger) {
|
private ReplExecutionEventNode(
|
||||||
|
EventContext eventContext, DebuggerMessageHandler handler, TruffleLogger logger) {
|
||||||
this.eventContext = eventContext;
|
this.eventContext = eventContext;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
@ -116,7 +120,8 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
* @return a map, where keys are variable names and values are current values of variables.
|
* @return a map, where keys are variable names and values are current values of variables.
|
||||||
*/
|
*/
|
||||||
public Map<String, Object> listBindings() {
|
public Map<String, Object> listBindings() {
|
||||||
Map<String, FramePointer> flatScope = nodeState.getLastScope().getLocalScope().flattenBindings();
|
Map<String, FramePointer> flatScope =
|
||||||
|
nodeState.getLastScope().getLocalScope().flattenBindings();
|
||||||
Map<String, Object> result = new HashMap<>();
|
Map<String, Object> result = new HashMap<>();
|
||||||
for (Map.Entry<String, FramePointer> entry : flatScope.entrySet()) {
|
for (Map.Entry<String, FramePointer> entry : flatScope.entrySet()) {
|
||||||
result.put(entry.getKey(), getValue(nodeState.getLastScope().getFrame(), entry.getValue()));
|
result.put(entry.getKey(), getValue(nodeState.getLastScope().getFrame(), entry.getValue()));
|
||||||
@ -128,20 +133,21 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
* Evaluates an arbitrary expression in the current execution context.
|
* Evaluates an arbitrary expression in the current execution context.
|
||||||
*
|
*
|
||||||
* @param expression the expression to evaluate
|
* @param expression the expression to evaluate
|
||||||
* @return the result of evaluating the expression or an exception that
|
* @return the result of evaluating the expression or an exception that caused failure
|
||||||
* caused failure
|
|
||||||
*/
|
*/
|
||||||
public Either<Exception, Object> evaluate(String expression) {
|
public Either<Exception, Object> evaluate(String expression) {
|
||||||
ReplExecutionEventNodeState savedState = nodeState;
|
ReplExecutionEventNodeState savedState = nodeState;
|
||||||
try {
|
try {
|
||||||
Stateful result = evalNode.execute(nodeState.getLastScope(), nodeState.getLastState(), expression);
|
Stateful result =
|
||||||
|
evalNode.execute(
|
||||||
|
nodeState.getLastScope(), nodeState.getLastState(), Text.create(expression));
|
||||||
Object lastState = result.getState();
|
Object lastState = result.getState();
|
||||||
CaptureResultScopeNode.WithCallerInfo payload =
|
CaptureResultScopeNode.WithCallerInfo payload =
|
||||||
(CaptureResultScopeNode.WithCallerInfo) result.getValue();
|
(CaptureResultScopeNode.WithCallerInfo) result.getValue();
|
||||||
CallerInfo lastScope = payload.getCallerInfo();
|
CallerInfo lastScope = payload.getCallerInfo();
|
||||||
Object lastReturn = payload.getResult();
|
Object lastReturn = payload.getResult();
|
||||||
nodeState = new ReplExecutionEventNodeState(lastReturn, lastState, lastScope);
|
nodeState = new ReplExecutionEventNodeState(lastReturn, lastState, lastScope);
|
||||||
return new Right<>(lastReturn);
|
return new Right<>(formatObject(lastReturn));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
nodeState = savedState;
|
nodeState = savedState;
|
||||||
TruffleStackTrace.fillIn(e);
|
TruffleStackTrace.fillIn(e);
|
||||||
@ -149,6 +155,14 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object formatObject(Object o) {
|
||||||
|
if (o instanceof Text) {
|
||||||
|
return toJavaStringNode.execute((Text) o);
|
||||||
|
} else {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminates this REPL session.
|
* Terminates this REPL session.
|
||||||
*
|
*
|
||||||
@ -202,8 +216,9 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
if (handler.hasClient()) {
|
if (handler.hasClient()) {
|
||||||
handler.startSession(this);
|
handler.startSession(this);
|
||||||
} else {
|
} else {
|
||||||
logger.warning("Debugger session starting, " +
|
logger.warning(
|
||||||
"but no client connected, will terminate the session immediately");
|
"Debugger session starting, "
|
||||||
|
+ "but no client connected, will terminate the session immediately");
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,9 +226,9 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
/**
|
/**
|
||||||
* State of the execution node.
|
* State of the execution node.
|
||||||
*
|
*
|
||||||
* As the execution nodes are reused by Truffle, the nested nodes share
|
* <p>As the execution nodes are reused by Truffle, the nested nodes share state. If execution
|
||||||
* state. If execution of a nested node fails, to ensure consistent state of
|
* of a nested node fails, to ensure consistent state of the parent node, its state has to be
|
||||||
* the parent node, its state has to be restored.
|
* restored.
|
||||||
*/
|
*/
|
||||||
private static class ReplExecutionEventNodeState {
|
private static class ReplExecutionEventNodeState {
|
||||||
private final Object lastReturn;
|
private final Object lastReturn;
|
||||||
@ -239,5 +254,4 @@ public class ReplDebuggerInstrument extends TruffleInstrument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import org.enso.interpreter.Constants;
|
|||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.callable.dispatch.IndirectInvokeFunctionNode;
|
import org.enso.interpreter.node.callable.dispatch.IndirectInvokeFunctionNode;
|
||||||
import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode;
|
import org.enso.interpreter.node.callable.dispatch.InvokeFunctionNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
@ -66,8 +67,13 @@ public abstract class InteropApplicationNode extends Node {
|
|||||||
Object[] arguments,
|
Object[] arguments,
|
||||||
@CachedContext(Language.class) Context context,
|
@CachedContext(Language.class) Context context,
|
||||||
@Cached("arguments.length") int cachedArgsLength,
|
@Cached("arguments.length") int cachedArgsLength,
|
||||||
@Cached("buildSorter(cachedArgsLength)") InvokeFunctionNode sorterNode) {
|
@Cached("buildSorter(cachedArgsLength)") InvokeFunctionNode sorterNode,
|
||||||
return sorterNode.execute(function, null, state, arguments).getValue();
|
@Cached("build()") HostValueToEnsoNode hostValueToEnsoNode) {
|
||||||
|
Object[] args = new Object[cachedArgsLength];
|
||||||
|
for (int i = 0; i < cachedArgsLength; i++) {
|
||||||
|
args[i] = hostValueToEnsoNode.execute(arguments[i]);
|
||||||
|
}
|
||||||
|
return sorterNode.execute(function, null, state, args).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Specialization(replaces = "callCached")
|
@Specialization(replaces = "callCached")
|
||||||
@ -75,13 +81,18 @@ public abstract class InteropApplicationNode extends Node {
|
|||||||
Function function,
|
Function function,
|
||||||
Object state,
|
Object state,
|
||||||
Object[] arguments,
|
Object[] arguments,
|
||||||
@Cached IndirectInvokeFunctionNode indirectInvokeFunctionNode) {
|
@Cached IndirectInvokeFunctionNode indirectInvokeFunctionNode,
|
||||||
|
@Cached("build()") HostValueToEnsoNode hostValueToEnsoNode) {
|
||||||
|
Object[] args = new Object[arguments.length];
|
||||||
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
|
args[i] = hostValueToEnsoNode.execute(arguments[i]);
|
||||||
|
}
|
||||||
return indirectInvokeFunctionNode
|
return indirectInvokeFunctionNode
|
||||||
.execute(
|
.execute(
|
||||||
function,
|
function,
|
||||||
null,
|
null,
|
||||||
state,
|
state,
|
||||||
arguments,
|
args,
|
||||||
buildSchema(arguments.length),
|
buildSchema(arguments.length),
|
||||||
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
||||||
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED,
|
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED,
|
||||||
|
@ -6,6 +6,8 @@ import com.oracle.truffle.api.dsl.Cached;
|
|||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.GenerateUncached;
|
import com.oracle.truffle.api.dsl.GenerateUncached;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
@ -18,6 +20,7 @@ import org.enso.interpreter.runtime.callable.atom.Atom;
|
|||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.MethodDoesNotExistException;
|
import org.enso.interpreter.runtime.error.MethodDoesNotExistException;
|
||||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||||
@ -153,7 +156,7 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
@Specialization(guards = "cachedSymbol == symbol")
|
@Specialization(guards = "cachedSymbol == symbol")
|
||||||
Function resolveString(
|
Function resolveString(
|
||||||
UnresolvedSymbol symbol,
|
UnresolvedSymbol symbol,
|
||||||
String self,
|
Text self,
|
||||||
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
||||||
@Cached(value = "resolveMethodOnString(cachedSymbol)", allowUncached = true)
|
@Cached(value = "resolveMethodOnString(cachedSymbol)", allowUncached = true)
|
||||||
Function function) {
|
Function function) {
|
||||||
@ -190,6 +193,19 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Specialization(
|
||||||
|
guards = {"isPolyglotArrayMethod(cachedSymbol)", "arrays.hasArrayElements(array)"})
|
||||||
|
Function resolvePolyglotArray(
|
||||||
|
UnresolvedSymbol symbol,
|
||||||
|
Object array,
|
||||||
|
@CachedLibrary(limit = "3") InteropLibrary arrays,
|
||||||
|
@Cached(value = "symbol", allowUncached = true) UnresolvedSymbol cachedSymbol,
|
||||||
|
@CachedContext(Language.class) Context ctx,
|
||||||
|
@Cached(value = "resolveMethodOnPolyglotArray(cachedSymbol, ctx)", allowUncached = true)
|
||||||
|
Function function) {
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
@Specialization(guards = {"cachedSymbol == symbol", "ctx.getEnvironment().isHostObject(target)"})
|
@Specialization(guards = {"cachedSymbol == symbol", "ctx.getEnvironment().isHostObject(target)"})
|
||||||
Function resolveHost(
|
Function resolveHost(
|
||||||
UnresolvedSymbol symbol,
|
UnresolvedSymbol symbol,
|
||||||
@ -262,7 +278,7 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
|
|
||||||
Function resolveMethodOnString(UnresolvedSymbol symbol) {
|
Function resolveMethodOnString(UnresolvedSymbol symbol) {
|
||||||
return ensureMethodExists(
|
return ensureMethodExists(
|
||||||
symbol.resolveFor(getBuiltins().text(), getBuiltins().any()), "Text", symbol);
|
symbol.resolveFor(getBuiltins().text().getText(), getBuiltins().any()), "Text", symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
Function resolveMethodOnFunction(UnresolvedSymbol symbol) {
|
Function resolveMethodOnFunction(UnresolvedSymbol symbol) {
|
||||||
@ -283,9 +299,23 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
|
|
||||||
Function buildHostResolver(UnresolvedSymbol symbol, Context context) {
|
Function buildHostResolver(UnresolvedSymbol symbol, Context context) {
|
||||||
if (symbol.getName().equals("new")) {
|
if (symbol.getName().equals("new")) {
|
||||||
return context.getBuiltins().getConstructorDispatch();
|
return context.getBuiltins().polyglot().getConstructorDispatch();
|
||||||
|
} else if (symbol.getName().equals("to_text")) {
|
||||||
|
return context.getBuiltins().polyglot().getPolyglotToTextFunction();
|
||||||
} else {
|
} else {
|
||||||
return context.getBuiltins().buildPolyglotMethodDispatch(symbol);
|
return context.getBuiltins().polyglot().buildPolyglotMethodDispatch(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isPolyglotArrayMethod(UnresolvedSymbol symbol) {
|
||||||
|
return symbol.getName().equals("at") || symbol.getName().equals("length");
|
||||||
|
}
|
||||||
|
|
||||||
|
Function resolveMethodOnPolyglotArray(UnresolvedSymbol symbol, Context context) {
|
||||||
|
if (symbol.getName().equals("length")) {
|
||||||
|
return context.getBuiltins().polyglot().getPolyglotArrayLengthFunction();
|
||||||
|
} else {
|
||||||
|
return context.getBuiltins().polyglot().getPolyglotArrayAtFunction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,13 @@ package org.enso.interpreter.node.expression.builtin.bool;
|
|||||||
|
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
@BuiltinMethod(type = "Boolean", name = "to_text", description = "Boolean to text conversion.")
|
@BuiltinMethod(type = "Boolean", name = "to_text", description = "Boolean to text conversion.")
|
||||||
public class ToTextNode extends Node {
|
public class ToTextNode extends Node {
|
||||||
String execute(boolean _this) {
|
Text t = Text.create("True");
|
||||||
return _this ? "True" : "False";
|
Text f = Text.create("False");
|
||||||
|
Text execute(boolean _this) {
|
||||||
|
return _this ? t : f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
|||||||
import org.enso.interpreter.dsl.MonadicState;
|
import org.enso.interpreter.dsl.MonadicState;
|
||||||
import org.enso.interpreter.node.expression.debug.EvalNode;
|
import org.enso.interpreter.node.expression.debug.EvalNode;
|
||||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.state.Stateful;
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
|
||||||
/** Root node for the builtin Debug.eval function. */
|
/** Root node for the builtin Debug.eval function. */
|
||||||
@ -21,7 +22,7 @@ public class DebugEvalNode extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Stateful execute(
|
Stateful execute(
|
||||||
CallerInfo callerInfo, @MonadicState Object state, Object _this, String expression) {
|
CallerInfo callerInfo, @MonadicState Object state, Object _this, Text expression) {
|
||||||
return evalNode.execute(callerInfo, state, expression);
|
return evalNode.execute(callerInfo, state, expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import com.oracle.truffle.api.nodes.Node;
|
|||||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||||
import org.enso.interpreter.Constants;
|
import org.enso.interpreter.Constants;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
@ -16,11 +18,12 @@ import org.enso.interpreter.runtime.error.PanicException;
|
|||||||
public class GetMemberNode extends Node {
|
public class GetMemberNode extends Node {
|
||||||
private @Child InteropLibrary library =
|
private @Child InteropLibrary library =
|
||||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
|
private @Child ToJavaStringNode toJavaStringNode = ToJavaStringNode.build();
|
||||||
private final BranchProfile err = BranchProfile.create();
|
private final BranchProfile err = BranchProfile.create();
|
||||||
|
|
||||||
Object execute(Object _this, Object object, String member_name) {
|
Object execute(Object _this, Object object, Text member_name) {
|
||||||
try {
|
try {
|
||||||
return library.readMember(object, member_name);
|
return library.readMember(object, toJavaStringNode.execute(member_name));
|
||||||
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
|
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
|
||||||
err.enter();
|
err.enter();
|
||||||
throw new PanicException(e.getMessage(), this);
|
throw new PanicException(e.getMessage(), this);
|
||||||
|
@ -5,7 +5,9 @@ import com.oracle.truffle.api.nodes.Node;
|
|||||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||||
import org.enso.interpreter.Constants;
|
import org.enso.interpreter.Constants;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
@ -15,11 +17,12 @@ import org.enso.interpreter.runtime.error.PanicException;
|
|||||||
public class InvokeNode extends Node {
|
public class InvokeNode extends Node {
|
||||||
private @Child InteropLibrary library =
|
private @Child InteropLibrary library =
|
||||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
|
private @Child ToJavaStringNode toJavaStringNode = ToJavaStringNode.build();
|
||||||
private final BranchProfile err = BranchProfile.create();
|
private final BranchProfile err = BranchProfile.create();
|
||||||
|
|
||||||
Object execute(Object _this, Object target, String name, Array arguments) {
|
Object execute(Object _this, Object target, Text name, Array arguments) {
|
||||||
try {
|
try {
|
||||||
return library.invokeMember(target, name, arguments.getItems());
|
return library.invokeMember(target, toJavaStringNode.execute(name), arguments.getItems());
|
||||||
} catch (UnsupportedMessageException
|
} catch (UnsupportedMessageException
|
||||||
| ArityException
|
| ArityException
|
||||||
| UnsupportedTypeException
|
| UnsupportedTypeException
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.interop.java;
|
package org.enso.interpreter.node.expression.builtin.interop.java;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@ -20,10 +23,16 @@ public abstract class AddToClassPathNode extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Specialization
|
@Specialization
|
||||||
Object doExecute(Object _this, String path, @CachedContext(Language.class) Context context) {
|
Object doExecute(
|
||||||
context.getEnvironment().addToHostClassPath(context.getTruffleFile(new File(path)));
|
Object _this,
|
||||||
|
Text path,
|
||||||
|
@CachedContext(Language.class) Context context,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
|
context
|
||||||
|
.getEnvironment()
|
||||||
|
.addToHostClassPath(context.getTruffleFile(new File(toJavaStringNode.execute(path))));
|
||||||
return context.getBuiltins().unit();
|
return context.getBuiltins().unit();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Object execute(Object _this, String path);
|
abstract Object execute(Object _this, Text path);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.interop.java;
|
package org.enso.interpreter.node.expression.builtin.interop.java;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
@BuiltinMethod(type = "Java", name = "lookup_class", description = "Looks up a Java symbol.")
|
@BuiltinMethod(type = "Java", name = "lookup_class", description = "Looks up a Java symbol.")
|
||||||
public abstract class LookupClassNode extends Node {
|
public abstract class LookupClassNode extends Node {
|
||||||
@ -14,9 +17,13 @@ public abstract class LookupClassNode extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Specialization
|
@Specialization
|
||||||
Object doExecute(Object _this, String name, @CachedContext(Language.class) Context ctx) {
|
Object doExecute(
|
||||||
return ctx.getEnvironment().lookupHostSymbol(name);
|
Object _this,
|
||||||
|
Text name,
|
||||||
|
@CachedContext(Language.class) Context ctx,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
|
return ctx.getEnvironment().lookupHostSymbol(toJavaStringNode.execute(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Object execute(Object _this, String name);
|
abstract Object execute(Object _this, Text name);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
|
import com.oracle.truffle.api.interop.ArityException;
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||||
|
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||||
|
import org.enso.interpreter.Constants;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Any",
|
||||||
|
name = "<polyglot_array_length>",
|
||||||
|
description = "Returns the length of a polyglot array.")
|
||||||
|
public class ArrayLengthNode extends Node {
|
||||||
|
private @Child InteropLibrary library =
|
||||||
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
|
private final BranchProfile err = BranchProfile.create();
|
||||||
|
|
||||||
|
public Object execute(Object _this) {
|
||||||
|
try {
|
||||||
|
return library.getArraySize(_this);
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
err.enter();
|
||||||
|
throw new PanicException(e.getMessage(), this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||||
|
|
||||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
||||||
@ -10,17 +10,18 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
|||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
type = "Polyglot",
|
type = "Any",
|
||||||
name = "get_array_element",
|
name = "<polyglot_array_at>",
|
||||||
description = "Gets an element by index from a polyglot array.")
|
description = "Returns the element of a polyglot array at a given index.")
|
||||||
public class GetArrayElementNode extends Node {
|
public class GetArrayElementNode extends Node {
|
||||||
private @Child InteropLibrary library =
|
private @Child InteropLibrary library =
|
||||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
|
private @Child HostValueToEnsoNode hostValueToEnsoNode = HostValueToEnsoNode.build();
|
||||||
private final BranchProfile err = BranchProfile.create();
|
private final BranchProfile err = BranchProfile.create();
|
||||||
|
|
||||||
Object execute(Object _this, Object array, long index) {
|
public Object execute(Object _this, long index) {
|
||||||
try {
|
try {
|
||||||
return library.readArrayElement(array, index);
|
return hostValueToEnsoNode.execute(library.readArrayElement(_this, index));
|
||||||
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
||||||
err.enter();
|
err.enter();
|
||||||
throw new PanicException(e.getMessage(), this);
|
throw new PanicException(e.getMessage(), this);
|
@ -1,15 +1,18 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||||
|
|
||||||
import com.oracle.truffle.api.dsl.Fallback;
|
import com.oracle.truffle.api.dsl.Fallback;
|
||||||
|
import com.oracle.truffle.api.dsl.GenerateUncached;
|
||||||
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a value returned by a polyglot call back to a value that can be further used within Enso
|
* Converts a value returned by a polyglot call back to a value that can be further used within Enso
|
||||||
* programs.
|
* programs.
|
||||||
*/
|
*/
|
||||||
@ReportPolymorphism
|
@ReportPolymorphism
|
||||||
|
@GenerateUncached
|
||||||
public abstract class HostValueToEnsoNode extends Node {
|
public abstract class HostValueToEnsoNode extends Node {
|
||||||
public static HostValueToEnsoNode build() {
|
public static HostValueToEnsoNode build() {
|
||||||
return HostValueToEnsoNodeGen.create();
|
return HostValueToEnsoNodeGen.create();
|
||||||
@ -48,6 +51,11 @@ public abstract class HostValueToEnsoNode extends Node {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Text doString(String txt) {
|
||||||
|
return Text.create(txt);
|
||||||
|
}
|
||||||
|
|
||||||
@Fallback
|
@Fallback
|
||||||
Object doOther(Object o) {
|
Object doOther(Object o) {
|
||||||
return o;
|
return o;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
package org.enso.interpreter.node.expression.builtin.interop.syntax;
|
||||||
|
|
||||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
@ -6,20 +6,23 @@ import com.oracle.truffle.api.nodes.Node;
|
|||||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||||
import org.enso.interpreter.Constants;
|
import org.enso.interpreter.Constants;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
type = "Polyglot",
|
type = "Any",
|
||||||
name = "get_array_size",
|
name = "<to_text>",
|
||||||
description = "Gets the size of a polyglot array.")
|
description = "Returns human-readable representation of a polyglot object.")
|
||||||
public class GetArraySizeNode extends Node {
|
public class PolyglotToTextNode extends Node {
|
||||||
private @Child InteropLibrary library =
|
private @Child InteropLibrary library =
|
||||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
|
private @Child InteropLibrary strings =
|
||||||
|
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||||
private final BranchProfile err = BranchProfile.create();
|
private final BranchProfile err = BranchProfile.create();
|
||||||
|
|
||||||
Object execute(Object _this, Object array) {
|
public Text execute(Object _this) {
|
||||||
try {
|
try {
|
||||||
return library.getArraySize(array);
|
return Text.create(strings.asString(library.toDisplayString(_this)));
|
||||||
} catch (UnsupportedMessageException e) {
|
} catch (UnsupportedMessageException e) {
|
||||||
err.enter();
|
err.enter();
|
||||||
throw new PanicException(e.getMessage(), this);
|
throw new PanicException(e.getMessage(), this);
|
@ -1,12 +1,25 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.io;
|
package org.enso.interpreter.node.expression.builtin.io;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.dsl.MonadicState;
|
||||||
|
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
type = "IO",
|
type = "IO",
|
||||||
@ -17,12 +30,53 @@ public abstract class PrintErrNode extends Node {
|
|||||||
return PrintErrNodeGen.create();
|
return PrintErrNodeGen.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract Object execute(Object _this, Object message);
|
abstract Stateful execute(
|
||||||
|
VirtualFrame frame, @MonadicState Object state, Object _this, Object message);
|
||||||
|
|
||||||
@Specialization
|
@Specialization
|
||||||
@TruffleBoundary
|
Stateful doPrintText(
|
||||||
Object doPrint(Object self, Object message, @CachedContext(Language.class) Context ctx) {
|
VirtualFrame frame,
|
||||||
ctx.getErr().println(message);
|
Object state,
|
||||||
return ctx.getUnit().newInstance();
|
Object self,
|
||||||
|
Text message,
|
||||||
|
@CachedContext(Language.class) Context ctx,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
|
print(ctx.getErr(), toJavaStringNode.execute(message));
|
||||||
|
return new Stateful(state, ctx.getUnit().newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "!isText(message)")
|
||||||
|
Stateful doPrint(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Object state,
|
||||||
|
Object self,
|
||||||
|
Object message,
|
||||||
|
@CachedContext(Language.class) Context ctx,
|
||||||
|
@Cached("buildSymbol(ctx)") UnresolvedSymbol symbol,
|
||||||
|
@Cached("buildInvokeCallableNode()") InvokeCallableNode invokeCallableNode,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
|
Stateful str = invokeCallableNode.execute(symbol, frame, state, new Object[] {message});
|
||||||
|
print(ctx.getErr(), toJavaStringNode.execute((Text) str.getValue()));
|
||||||
|
return new Stateful(str.getState(), ctx.getUnit().newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
private void print(PrintStream err, Object str) {
|
||||||
|
err.println(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isText(Object o) {
|
||||||
|
return TypesGen.isText(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
InvokeCallableNode buildInvokeCallableNode() {
|
||||||
|
return InvokeCallableNode.build(
|
||||||
|
new CallArgumentInfo[] {new CallArgumentInfo()},
|
||||||
|
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
||||||
|
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnresolvedSymbol buildSymbol(Context ctx) {
|
||||||
|
return UnresolvedSymbol.build("to_text", ctx.getBuiltins().getScope());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package org.enso.interpreter.node.expression.builtin.io;
|
|||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
import com.oracle.truffle.api.dsl.Cached;
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Fallback;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
@ -11,10 +12,13 @@ import org.enso.interpreter.Language;
|
|||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
import org.enso.interpreter.dsl.MonadicState;
|
import org.enso.interpreter.dsl.MonadicState;
|
||||||
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
import org.enso.interpreter.node.callable.InvokeCallableNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.state.Stateful;
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
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.")
|
||||||
public abstract class PrintlnNode extends Node {
|
public abstract class PrintlnNode extends Node {
|
||||||
@ -28,18 +32,37 @@ public abstract class PrintlnNode extends Node {
|
|||||||
VirtualFrame frame, @MonadicState Object state, Object _this, Object message);
|
VirtualFrame frame, @MonadicState Object state, Object _this, Object message);
|
||||||
|
|
||||||
@Specialization
|
@Specialization
|
||||||
|
Stateful doPrintText(
|
||||||
|
VirtualFrame frame,
|
||||||
|
Object state,
|
||||||
|
Object self,
|
||||||
|
Text message,
|
||||||
|
@CachedContext(Language.class) Context ctx,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
|
print(ctx.getOut(), toJavaStringNode.execute(message));
|
||||||
|
return new Stateful(state, ctx.getUnit().newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(guards = "!isText(message)")
|
||||||
Stateful doPrint(
|
Stateful doPrint(
|
||||||
VirtualFrame frame,
|
VirtualFrame frame,
|
||||||
Object state,
|
Object state,
|
||||||
Object self,
|
Object self,
|
||||||
Object message,
|
Object message,
|
||||||
@CachedContext(Language.class) Context ctx,
|
@CachedContext(Language.class) Context ctx,
|
||||||
@Cached("buildSymbol(ctx)") UnresolvedSymbol symbol) {
|
@Cached("buildSymbol(ctx)") UnresolvedSymbol symbol,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode,
|
||||||
|
@Cached("buildInvokeCallableNode()") InvokeCallableNode invokeCallableNode) {
|
||||||
Stateful str = invokeCallableNode.execute(symbol, frame, state, new Object[] {message});
|
Stateful str = invokeCallableNode.execute(symbol, frame, state, new Object[] {message});
|
||||||
print(ctx.getOut(), str.getValue());
|
String strr = toJavaStringNode.execute((Text) str.getValue());
|
||||||
|
print(ctx.getOut(), strr);
|
||||||
return new Stateful(str.getState(), ctx.getUnit().newInstance());
|
return new Stateful(str.getState(), ctx.getUnit().newInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isText(Object o) {
|
||||||
|
return TypesGen.isText(o);
|
||||||
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
private void print(PrintStream out, Object str) {
|
private void print(PrintStream out, Object str) {
|
||||||
out.println(str);
|
out.println(str);
|
||||||
@ -49,6 +72,13 @@ public abstract class PrintlnNode extends Node {
|
|||||||
return UnresolvedSymbol.build("to_text", ctx.getBuiltins().getScope());
|
return UnresolvedSymbol.build("to_text", ctx.getBuiltins().getScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InvokeCallableNode buildInvokeCallableNode() {
|
||||||
|
return InvokeCallableNode.build(
|
||||||
|
new CallArgumentInfo[] {new CallArgumentInfo()},
|
||||||
|
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
||||||
|
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED);
|
||||||
|
}
|
||||||
|
|
||||||
static PrintlnNode build() {
|
static PrintlnNode build() {
|
||||||
return PrintlnNodeGen.create();
|
return PrintlnNodeGen.create();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import java.io.IOException;
|
|||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||||
|
|
||||||
@BuiltinMethod(type = "IO", name = "readln", description = "Reads a line from standard in.")
|
@BuiltinMethod(type = "IO", name = "readln", description = "Reads a line from standard in.")
|
||||||
@ -21,11 +23,11 @@ public abstract class ReadlnNode extends Node {
|
|||||||
|
|
||||||
@Specialization
|
@Specialization
|
||||||
@TruffleBoundary
|
@TruffleBoundary
|
||||||
Object doRead(Object _this, @CachedContext(Language.class) Context ctx) {
|
Text doRead(Object _this, @CachedContext(Language.class) Context ctx) {
|
||||||
try {
|
try {
|
||||||
return ctx.getInReader().readLine();
|
return Text.create(ctx.getInReader().readLine());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
return new RuntimeError("Empty input stream.");
|
throw new PanicException("Empty input stream", this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.system;
|
package org.enso.interpreter.node.expression.builtin.system;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.dsl.CachedContext;
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.io.TruffleProcessBuilder;
|
import com.oracle.truffle.api.io.TruffleProcessBuilder;
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -25,9 +28,9 @@ public abstract class CreateProcessNode extends Node {
|
|||||||
|
|
||||||
abstract Object execute(
|
abstract Object execute(
|
||||||
Object _this,
|
Object _this,
|
||||||
String command,
|
Text command,
|
||||||
Array arguments,
|
Array arguments,
|
||||||
String input,
|
Text input,
|
||||||
boolean redirectIn,
|
boolean redirectIn,
|
||||||
boolean redirectOut,
|
boolean redirectOut,
|
||||||
boolean redirectErr);
|
boolean redirectErr);
|
||||||
@ -36,21 +39,25 @@ public abstract class CreateProcessNode extends Node {
|
|||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
Object doCreate(
|
Object doCreate(
|
||||||
Object _this,
|
Object _this,
|
||||||
String command,
|
Text command,
|
||||||
Array arguments,
|
Array arguments,
|
||||||
String input,
|
Text input,
|
||||||
boolean redirectIn,
|
boolean redirectIn,
|
||||||
boolean redirectOut,
|
boolean redirectOut,
|
||||||
boolean redirectErr,
|
boolean redirectErr,
|
||||||
@CachedContext(Language.class) Context ctx) {
|
@CachedContext(Language.class) Context ctx,
|
||||||
String[] cmd = new String[(int) arguments.getItems().length + 1];
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
cmd[0] = command;
|
String[] cmd = new String[arguments.getItems().length + 1];
|
||||||
System.arraycopy(arguments.getItems(), 0, cmd, 1, (int) arguments.getItems().length);
|
cmd[0] = toJavaStringNode.execute(command);
|
||||||
|
for (int i = 1; i <= arguments.getItems().length; i++) {
|
||||||
|
cmd[i] = toJavaStringNode.execute((Text) arguments.getItems()[i - 1]);
|
||||||
|
}
|
||||||
TruffleProcessBuilder pb = ctx.getEnvironment().newProcessBuilder(cmd);
|
TruffleProcessBuilder pb = ctx.getEnvironment().newProcessBuilder(cmd);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Process p = pb.start();
|
Process p = pb.start();
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(input.getBytes());
|
ByteArrayInputStream in =
|
||||||
|
new ByteArrayInputStream(toJavaStringNode.execute(input).getBytes());
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
|
||||||
@ -106,8 +113,8 @@ public abstract class CreateProcessNode extends Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long exitCode = p.exitValue();
|
long exitCode = p.exitValue();
|
||||||
String returnOut = new String(out.toByteArray());
|
Text returnOut = Text.create(new String(out.toByteArray()));
|
||||||
String returnErr = new String(err.toByteArray());
|
Text returnErr = Text.create(new String(err.toByteArray()));
|
||||||
|
|
||||||
return ctx.getBuiltins()
|
return ctx.getBuiltins()
|
||||||
.system()
|
.system()
|
||||||
|
@ -3,6 +3,7 @@ package org.enso.interpreter.node.expression.builtin.system;
|
|||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.apache.commons.lang3.SystemUtils;
|
import org.apache.commons.lang3.SystemUtils;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
@BuiltinMethod(
|
@BuiltinMethod(
|
||||||
type = "System",
|
type = "System",
|
||||||
@ -10,12 +11,12 @@ import org.enso.interpreter.dsl.BuiltinMethod;
|
|||||||
description = "Get the type of operating system.")
|
description = "Get the type of operating system.")
|
||||||
public final class OsNode extends Node {
|
public final class OsNode extends Node {
|
||||||
|
|
||||||
private final String LINUX = "linux";
|
private final Text LINUX = Text.create("linux");
|
||||||
private final String MACOS = "macos";
|
private final Text MACOS = Text.create("macos");
|
||||||
private final String WINDOWS = "windows";
|
private final Text WINDOWS = Text.create("windows");
|
||||||
private final String UNKNOWN = "unknown";
|
private final Text UNKNOWN = Text.create("unknown");
|
||||||
|
|
||||||
String execute(Object _this) {
|
Text execute(Object _this) {
|
||||||
if (SystemUtils.IS_OS_LINUX) return LINUX;
|
if (SystemUtils.IS_OS_LINUX) return LINUX;
|
||||||
if (SystemUtils.IS_OS_MAC_OSX) return MACOS;
|
if (SystemUtils.IS_OS_MAC_OSX) return MACOS;
|
||||||
if (SystemUtils.IS_OS_WINDOWS) return WINDOWS;
|
if (SystemUtils.IS_OS_WINDOWS) return WINDOWS;
|
||||||
|
@ -1,13 +1,67 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.text;
|
package org.enso.interpreter.node.expression.builtin.text;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.Fallback;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
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 com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
|
|
||||||
@BuiltinMethod(type = "Any", name = "to_text", description = "Generic text conversion.")
|
@BuiltinMethod(type = "Any", name = "to_text", description = "Generic text conversion.")
|
||||||
public class AnyToTextNode extends Node {
|
public abstract class AnyToTextNode extends Node {
|
||||||
|
private static final int DISPATCH_CACHE = 3;
|
||||||
|
private @Child InteropLibrary displays =
|
||||||
|
InteropLibrary.getFactory().createDispatched(DISPATCH_CACHE);
|
||||||
|
private @Child InteropLibrary strings =
|
||||||
|
InteropLibrary.getFactory().createDispatched(DISPATCH_CACHE);
|
||||||
|
|
||||||
|
static AnyToTextNode build() {
|
||||||
|
return AnyToTextNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract Text execute(Object _this);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Text doAtom(Atom at) {
|
||||||
|
if (at.getFields().length == 0) {
|
||||||
|
return Text.create(at.getConstructor().getName());
|
||||||
|
} else {
|
||||||
|
return doComplexAtom(at, displays, strings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Fallback
|
||||||
|
Text doOther(Object object) {
|
||||||
|
try {
|
||||||
|
return Text.create(strings.asString(displays.toDisplayString(object)));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
return Text.create(object.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
String execute(Object _this) {
|
private Text doComplexAtom(Atom atom, InteropLibrary displays, InteropLibrary strings) {
|
||||||
return _this.toString();
|
Text res = Text.create("(" + atom.getConstructor().getName() + " ");
|
||||||
|
try {
|
||||||
|
res = Text.create(res, strings.asString(displays.toDisplayString(atom.getFields()[0])));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
res = Text.create(res, atom.getFields()[0].toString());
|
||||||
|
}
|
||||||
|
for (int i = 1; i < atom.getFields().length; i++) {
|
||||||
|
res = Text.create(res, " ");
|
||||||
|
try {
|
||||||
|
res = Text.create(res, strings.asString(displays.toDisplayString(atom.getFields()[i])));
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
res = Text.create(res, atom.getFields()[i].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = Text.create(res, ")");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@ package org.enso.interpreter.node.expression.builtin.text;
|
|||||||
|
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
@BuiltinMethod(type = "Text", name = "+", description = "Text concatenation.")
|
@BuiltinMethod(type = "Text", name = "+", description = "Text concatenation.")
|
||||||
public class ConcatNode extends Node {
|
public class ConcatNode extends Node {
|
||||||
String execute(String _this, String that) {
|
Text execute(Text _this, Text that) {
|
||||||
return _this + that;
|
return Text.create(_this, that);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@ import com.oracle.truffle.api.CompilerDirectives;
|
|||||||
import com.oracle.truffle.api.nodes.Node;
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
import org.enso.interpreter.runtime.builtin.LanguageEntitySerializer;
|
import org.enso.interpreter.runtime.builtin.LanguageEntitySerializer;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
@BuiltinMethod(type = "Any", name = "json_serialize", description = "Generic JSON serialization.")
|
@BuiltinMethod(type = "Any", name = "json_serialize", description = "Generic JSON serialization.")
|
||||||
public class JsonSerializeNode extends Node {
|
public class JsonSerializeNode extends Node {
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
String execute(Object _this) {
|
Text execute(Object _this) {
|
||||||
return LanguageEntitySerializer.serialize(_this);
|
return Text.create(LanguageEntitySerializer.serialize(_this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.text;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Prim_Text_Helpers",
|
||||||
|
name = "optimize",
|
||||||
|
description = "Forces flattening of a text value, for testing or purposes.")
|
||||||
|
public class OptimizeNode extends Node {
|
||||||
|
private @Child ToJavaStringNode toJavaStringNode = ToJavaStringNode.build();
|
||||||
|
|
||||||
|
Text execute(Object _this, Text text) {
|
||||||
|
toJavaStringNode.execute(text);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package org.enso.interpreter.node.expression.builtin.text;
|
|
||||||
|
|
||||||
import com.oracle.truffle.api.nodes.Node;
|
|
||||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
|
||||||
|
|
||||||
@BuiltinMethod(type = "Text", name = "==", description = "Equality on text.")
|
|
||||||
public class TextEqualsNode extends Node {
|
|
||||||
boolean execute(String _this, String that) {
|
|
||||||
return _this.equals(that);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,91 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.text.util;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
|
import org.enso.interpreter.runtime.data.text.ConcatRope;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
|
@NodeInfo(description = "Converts Enso Text to a Java String.")
|
||||||
|
public class ToJavaStringNode extends Node {
|
||||||
|
private static ToJavaStringNode UNCACHED = new ToJavaStringNode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the uncached version of this node.
|
||||||
|
*
|
||||||
|
* @return the uncached version of this node.
|
||||||
|
*/
|
||||||
|
public static ToJavaStringNode getUncached() {
|
||||||
|
return UNCACHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of this node.
|
||||||
|
*
|
||||||
|
* @return a new instance of this node.
|
||||||
|
*/
|
||||||
|
public static ToJavaStringNode build() {
|
||||||
|
return new ToJavaStringNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the conversion of Enso Text to a Java String.
|
||||||
|
*
|
||||||
|
* @param text the text to convert.
|
||||||
|
* @return the result of conversion.
|
||||||
|
*/
|
||||||
|
public String execute(Text text) {
|
||||||
|
if (text.isFlat()) {
|
||||||
|
return (String) text.getContents();
|
||||||
|
} else {
|
||||||
|
return inplaceFlatten(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts text to a Java String. For use outside of Truffle Nodes.
|
||||||
|
*
|
||||||
|
* @param text the text to convert.
|
||||||
|
* @return the result of conversion.
|
||||||
|
*/
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public static String inplaceFlatten(Text text) {
|
||||||
|
Lock lock = text.getLock();
|
||||||
|
lock.lock();
|
||||||
|
String result;
|
||||||
|
try {
|
||||||
|
if (text.isFlat()) {
|
||||||
|
result = (String) text.getContents();
|
||||||
|
} else {
|
||||||
|
result = doFlatten(text);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String doFlatten(Text text) {
|
||||||
|
Deque<Object> workStack = new ArrayDeque<>();
|
||||||
|
StringBuilder bldr = new StringBuilder();
|
||||||
|
workStack.push(text.getContents());
|
||||||
|
while (!workStack.isEmpty()) {
|
||||||
|
Object item = workStack.pop();
|
||||||
|
if (item instanceof String) {
|
||||||
|
bldr.append((String) item);
|
||||||
|
} else {
|
||||||
|
ConcatRope rope = (ConcatRope) item;
|
||||||
|
workStack.push(rope.getRight());
|
||||||
|
workStack.push(rope.getLeft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String res = bldr.toString();
|
||||||
|
text.setContents(res);
|
||||||
|
text.setFlat(true);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package org.enso.interpreter.node.expression.debug;
|
|||||||
import com.oracle.truffle.api.RootCallTarget;
|
import com.oracle.truffle.api.RootCallTarget;
|
||||||
import com.oracle.truffle.api.Truffle;
|
import com.oracle.truffle.api.Truffle;
|
||||||
import com.oracle.truffle.api.dsl.Cached;
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.ReportPolymorphism;
|
||||||
import com.oracle.truffle.api.dsl.Specialization;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
import org.enso.compiler.context.InlineContext;
|
import org.enso.compiler.context.InlineContext;
|
||||||
@ -12,15 +13,18 @@ import org.enso.interpreter.node.BaseNode;
|
|||||||
import org.enso.interpreter.node.ClosureRootNode;
|
import org.enso.interpreter.node.ClosureRootNode;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.scope.LocalScope;
|
import org.enso.interpreter.runtime.scope.LocalScope;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
import org.enso.interpreter.runtime.state.Stateful;
|
import org.enso.interpreter.runtime.state.Stateful;
|
||||||
|
|
||||||
/** Node running Enso expressions passed to it as strings. */
|
/** Node running Enso expressions passed to it as strings. */
|
||||||
@NodeInfo(shortName = "Eval", description = "Evaluates code passed to it as string")
|
@NodeInfo(shortName = "Eval", description = "Evaluates code passed to it as string")
|
||||||
|
@ReportPolymorphism
|
||||||
public abstract class EvalNode extends BaseNode {
|
public abstract class EvalNode extends BaseNode {
|
||||||
private final boolean shouldCaptureResultScope;
|
private final boolean shouldCaptureResultScope;
|
||||||
|
|
||||||
@ -54,7 +58,7 @@ public abstract class EvalNode extends BaseNode {
|
|||||||
* @param expression the string containing expression to evaluate
|
* @param expression the string containing expression to evaluate
|
||||||
* @return the result of evaluating {@code expression} in the {@code callerInfo} context
|
* @return the result of evaluating {@code expression} in the {@code callerInfo} context
|
||||||
*/
|
*/
|
||||||
public abstract Stateful execute(CallerInfo callerInfo, Object state, String expression);
|
public abstract Stateful execute(CallerInfo callerInfo, Object state, Text expression);
|
||||||
|
|
||||||
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
|
RootCallTarget parseExpression(LocalScope scope, ModuleScope moduleScope, String expression) {
|
||||||
LocalScope localScope = scope.createChild();
|
LocalScope localScope = scope.createChild();
|
||||||
@ -93,11 +97,13 @@ public abstract class EvalNode extends BaseNode {
|
|||||||
Stateful doCached(
|
Stateful doCached(
|
||||||
CallerInfo callerInfo,
|
CallerInfo callerInfo,
|
||||||
Object state,
|
Object state,
|
||||||
String expression,
|
Text expression,
|
||||||
@Cached("expression") String cachedExpression,
|
@Cached("expression") Text cachedExpression,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode,
|
||||||
|
@Cached("toJavaStringNode.execute(expression)") String expressionStr,
|
||||||
@Cached("callerInfo") CallerInfo cachedCallerInfo,
|
@Cached("callerInfo") CallerInfo cachedCallerInfo,
|
||||||
@Cached(
|
@Cached(
|
||||||
"parseExpression(callerInfo.getLocalScope(), callerInfo.getModuleScope(), expression)")
|
"parseExpression(callerInfo.getLocalScope(), callerInfo.getModuleScope(), expressionStr)")
|
||||||
RootCallTarget cachedCallTarget,
|
RootCallTarget cachedCallTarget,
|
||||||
@Cached("build()") ThunkExecutorNode thunkExecutorNode) {
|
@Cached("build()") ThunkExecutorNode thunkExecutorNode) {
|
||||||
Thunk thunk = new Thunk(cachedCallTarget, callerInfo.getFrame());
|
Thunk thunk = new Thunk(cachedCallTarget, callerInfo.getFrame());
|
||||||
@ -108,10 +114,14 @@ public abstract class EvalNode extends BaseNode {
|
|||||||
Stateful doUncached(
|
Stateful doUncached(
|
||||||
CallerInfo callerInfo,
|
CallerInfo callerInfo,
|
||||||
Object state,
|
Object state,
|
||||||
String expression,
|
Text expression,
|
||||||
@Cached("build()") ThunkExecutorNode thunkExecutorNode) {
|
@Cached("build()") ThunkExecutorNode thunkExecutorNode,
|
||||||
|
@Cached("build()") ToJavaStringNode toJavaStringNode) {
|
||||||
RootCallTarget callTarget =
|
RootCallTarget callTarget =
|
||||||
parseExpression(callerInfo.getLocalScope(), callerInfo.getModuleScope(), expression);
|
parseExpression(
|
||||||
|
callerInfo.getLocalScope(),
|
||||||
|
callerInfo.getModuleScope(),
|
||||||
|
toJavaStringNode.execute(expression));
|
||||||
Thunk thunk = new Thunk(callTarget, callerInfo.getFrame());
|
Thunk thunk = new Thunk(callTarget, callerInfo.getFrame());
|
||||||
return thunkExecutorNode.executeThunk(thunk, state, isTail());
|
return thunkExecutorNode.executeThunk(thunk, state, isTail());
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,15 @@ package org.enso.interpreter.node.expression.literal;
|
|||||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||||
import org.enso.interpreter.node.ExpressionNode;
|
import org.enso.interpreter.node.ExpressionNode;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
/** Node representing a constant String value. */
|
/** Node representing a constant String value. */
|
||||||
@NodeInfo(shortName = "StringLiteral", description = "Constant string literal expression")
|
@NodeInfo(shortName = "StringLiteral", description = "Constant string literal expression")
|
||||||
public class TextLiteralNode extends ExpressionNode {
|
public class TextLiteralNode extends ExpressionNode {
|
||||||
private final String value;
|
private final Text value;
|
||||||
|
|
||||||
private TextLiteralNode(String value) {
|
private TextLiteralNode(String value) {
|
||||||
this.value = value;
|
this.value = Text.create(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +31,7 @@ public class TextLiteralNode extends ExpressionNode {
|
|||||||
* @return the string value this node was created with
|
* @return the string value this node was created with
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object executeGeneric(VirtualFrame frame) {
|
public Text executeGeneric(VirtualFrame frame) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import org.enso.interpreter.runtime.callable.CallerInfo;
|
|||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.scope.LocalScope;
|
import org.enso.interpreter.runtime.scope.LocalScope;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
import org.enso.interpreter.runtime.type.Types;
|
import org.enso.interpreter.runtime.type.Types;
|
||||||
@ -205,10 +206,7 @@ public class Module implements TruffleObject {
|
|||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Create scope if it does not exist. */
|
||||||
* Create scope if it does not exist.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void ensureScopeExists() {
|
public void ensureScopeExists() {
|
||||||
if (scope == null) {
|
if (scope == null) {
|
||||||
scope = new ModuleScope(this);
|
scope = new ModuleScope(this);
|
||||||
@ -387,7 +385,7 @@ public class Module implements TruffleObject {
|
|||||||
CallerInfo callerInfo = new CallerInfo(null, LocalScope.root(), scope);
|
CallerInfo callerInfo = new CallerInfo(null, LocalScope.root(), scope);
|
||||||
Object state = context.getBuiltins().unit().newInstance();
|
Object state = context.getBuiltins().unit().newInstance();
|
||||||
return callOptimiserNode
|
return callOptimiserNode
|
||||||
.executeDispatch(eval, callerInfo, state, new Object[] {debug, expr})
|
.executeDispatch(eval, callerInfo, state, new Object[] {debug, Text.create(expr)})
|
||||||
.getValue();
|
.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,18 +5,27 @@ import com.oracle.truffle.api.Truffle;
|
|||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointMethodGen;
|
import org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.debug.DebugEvalMethodGen;
|
import org.enso.interpreter.node.expression.builtin.debug.DebugEvalMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.error.*;
|
import org.enso.interpreter.node.expression.builtin.error.CatchErrorMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.error.CatchPanicMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.error.ThrowErrorMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.error.ThrowPanicMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.function.ApplicationOperatorMethodGen;
|
import org.enso.interpreter.node.expression.builtin.function.ApplicationOperatorMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.function.ExplicitCallFunctionMethodGen;
|
import org.enso.interpreter.node.expression.builtin.function.ExplicitCallFunctionMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.interop.generic.*;
|
import org.enso.interpreter.node.expression.builtin.interop.generic.*;
|
||||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.MethodDispatchNode;
|
import org.enso.interpreter.node.expression.builtin.interop.java.AddToClassPathMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.java.LookupClassMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.ConstructorDispatchNode;
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.ConstructorDispatchNode;
|
||||||
import org.enso.interpreter.node.expression.builtin.io.*;
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.MethodDispatchNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.io.PrintErrMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.io.PrintlnMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.io.ReadlnMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.runtime.GCMethodGen;
|
import org.enso.interpreter.node.expression.builtin.runtime.GCMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.runtime.NoInlineMethodGen;
|
import org.enso.interpreter.node.expression.builtin.runtime.NoInlineMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.state.*;
|
import org.enso.interpreter.node.expression.builtin.state.GetStateMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.interop.java.*;
|
import org.enso.interpreter.node.expression.builtin.state.PutStateMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.text.*;
|
import org.enso.interpreter.node.expression.builtin.state.RunStateMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.AnyToTextMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.JsonSerializeMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.thread.WithInterruptHandlerMethodGen;
|
import org.enso.interpreter.node.expression.builtin.thread.WithInterruptHandlerMethodGen;
|
||||||
import org.enso.interpreter.node.expression.builtin.unsafe.SetAtomFieldMethodGen;
|
import org.enso.interpreter.node.expression.builtin.unsafe.SetAtomFieldMethodGen;
|
||||||
import org.enso.interpreter.runtime.Context;
|
import org.enso.interpreter.runtime.Context;
|
||||||
@ -47,16 +56,13 @@ public class Builtins {
|
|||||||
private final AtomConstructor any;
|
private final AtomConstructor any;
|
||||||
private final Number number;
|
private final Number number;
|
||||||
private final AtomConstructor function;
|
private final AtomConstructor function;
|
||||||
private final AtomConstructor text;
|
|
||||||
private final AtomConstructor debug;
|
private final AtomConstructor debug;
|
||||||
|
private final Text text;
|
||||||
private final Error error;
|
private final Error error;
|
||||||
private final Bool bool;
|
private final Bool bool;
|
||||||
private final System system;
|
private final System system;
|
||||||
private final Array array;
|
private final Array array;
|
||||||
|
private final Polyglot polyglot;
|
||||||
private final RootCallTarget interopDispatchRoot;
|
|
||||||
private final FunctionSchema interopDispatchSchema;
|
|
||||||
private final Function newInstanceFunction;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an instance with builtin methods installed.
|
* Creates an instance with builtin methods installed.
|
||||||
@ -74,10 +80,11 @@ public class Builtins {
|
|||||||
error = new Error(language, scope);
|
error = new Error(language, scope);
|
||||||
array = new Array(language, scope);
|
array = new Array(language, scope);
|
||||||
function = new AtomConstructor("Function", scope).initializeFields();
|
function = new AtomConstructor("Function", scope).initializeFields();
|
||||||
text = new AtomConstructor("Text", scope).initializeFields();
|
text = new Text(language, scope);
|
||||||
debug = new AtomConstructor("Debug", scope).initializeFields();
|
debug = new AtomConstructor("Debug", scope).initializeFields();
|
||||||
system = new System(language, scope);
|
system = new System(language, scope);
|
||||||
number = new Number(language, scope);
|
number = new Number(language, scope);
|
||||||
|
polyglot = new Polyglot(language, scope);
|
||||||
|
|
||||||
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
AtomConstructor nil = new AtomConstructor("Nil", scope).initializeFields();
|
||||||
AtomConstructor cons =
|
AtomConstructor cons =
|
||||||
@ -98,7 +105,6 @@ public class Builtins {
|
|||||||
scope.registerConstructor(unit);
|
scope.registerConstructor(unit);
|
||||||
scope.registerConstructor(any);
|
scope.registerConstructor(any);
|
||||||
scope.registerConstructor(function);
|
scope.registerConstructor(function);
|
||||||
scope.registerConstructor(text);
|
|
||||||
|
|
||||||
scope.registerConstructor(cons);
|
scope.registerConstructor(cons);
|
||||||
scope.registerConstructor(nil);
|
scope.registerConstructor(nil);
|
||||||
@ -114,8 +120,6 @@ public class Builtins {
|
|||||||
|
|
||||||
scope.registerConstructor(unsafe);
|
scope.registerConstructor(unsafe);
|
||||||
|
|
||||||
createPolyglot(language);
|
|
||||||
|
|
||||||
scope.registerMethod(io, "println", PrintlnMethodGen.makeFunction(language));
|
scope.registerMethod(io, "println", PrintlnMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(io, "print_err", PrintErrMethodGen.makeFunction(language));
|
scope.registerMethod(io, "print_err", PrintErrMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(io, "readln", ReadlnMethodGen.makeFunction(language));
|
scope.registerMethod(io, "readln", ReadlnMethodGen.makeFunction(language));
|
||||||
@ -138,8 +142,6 @@ public class Builtins {
|
|||||||
scope.registerMethod(function, "call", ExplicitCallFunctionMethodGen.makeFunction(language));
|
scope.registerMethod(function, "call", ExplicitCallFunctionMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(function, "<|", ApplicationOperatorMethodGen.makeFunction(language));
|
scope.registerMethod(function, "<|", ApplicationOperatorMethodGen.makeFunction(language));
|
||||||
|
|
||||||
scope.registerMethod(text, "+", ConcatMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(text, "==", TextEqualsMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(any, "to_text", AnyToTextMethodGen.makeFunction(language));
|
scope.registerMethod(any, "to_text", AnyToTextMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(any, "json_serialize", JsonSerializeMethodGen.makeFunction(language));
|
scope.registerMethod(any, "json_serialize", JsonSerializeMethodGen.makeFunction(language));
|
||||||
|
|
||||||
@ -151,36 +153,9 @@ public class Builtins {
|
|||||||
|
|
||||||
scope.registerMethod(unsafe, "set_atom_field", SetAtomFieldMethodGen.makeFunction(language));
|
scope.registerMethod(unsafe, "set_atom_field", SetAtomFieldMethodGen.makeFunction(language));
|
||||||
|
|
||||||
interopDispatchRoot = Truffle.getRuntime().createCallTarget(MethodDispatchNode.build(language));
|
|
||||||
interopDispatchSchema =
|
|
||||||
new FunctionSchema(
|
|
||||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
|
||||||
FunctionSchema.CallerFrameAccess.NONE,
|
|
||||||
new ArgumentDefinition[] {
|
|
||||||
new ArgumentDefinition(1, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
|
||||||
new ArgumentDefinition(2, "method_name", ArgumentDefinition.ExecutionMode.EXECUTE),
|
|
||||||
new ArgumentDefinition(3, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE)
|
|
||||||
},
|
|
||||||
new boolean[] {false, true, false},
|
|
||||||
new CallArgumentInfo[0]);
|
|
||||||
newInstanceFunction = ConstructorDispatchNode.makeFunction(language);
|
|
||||||
|
|
||||||
module.unsafeBuildIrStub();
|
module.unsafeBuildIrStub();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createPolyglot(Language language) {
|
|
||||||
AtomConstructor polyglot = new AtomConstructor("Polyglot", scope).initializeFields();
|
|
||||||
scope.registerConstructor(polyglot);
|
|
||||||
scope.registerMethod(polyglot, "execute", ExecuteMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(polyglot, "invoke", InvokeMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(polyglot, "new", InstantiateMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(polyglot, "get_member", GetMemberMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(polyglot, "get_members", GetMembersMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(polyglot, "get_array_size", GetArraySizeMethodGen.makeFunction(language));
|
|
||||||
scope.registerMethod(
|
|
||||||
polyglot, "get_array_element", GetArrayElementMethodGen.makeFunction(language));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@code Unit} atom constructor.
|
* Returns the {@code Unit} atom constructor.
|
||||||
*
|
*
|
||||||
@ -191,11 +166,11 @@ public class Builtins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@code Text} atom constructor.
|
* Returns the {@code Text} part of builtins.
|
||||||
*
|
*
|
||||||
* @return the {@code Text} atom constructor
|
* @return the {@code Text} part of builtins.
|
||||||
*/
|
*/
|
||||||
public AtomConstructor text() {
|
public Text text() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +230,11 @@ public class Builtins {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the container for polyglot-related builtins. */
|
||||||
|
public Polyglot polyglot() {
|
||||||
|
return polyglot;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the builtin module scope.
|
* Returns the builtin module scope.
|
||||||
*
|
*
|
||||||
@ -267,20 +247,4 @@ public class Builtins {
|
|||||||
public Module getModule() {
|
public Module getModule() {
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds a function dispatching to a polyglot method call.
|
|
||||||
*
|
|
||||||
* @param method the name and scope of the method this function will dispatch to.
|
|
||||||
* @return a function calling {@code method} with given arguments.
|
|
||||||
*/
|
|
||||||
public Function buildPolyglotMethodDispatch(UnresolvedSymbol method) {
|
|
||||||
Object[] preAppliedArr = new Object[] {null, method, null};
|
|
||||||
return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return a function executing a constructor with given arguments. */
|
|
||||||
public Function getConstructorDispatch() {
|
|
||||||
return newInstanceFunction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
package org.enso.interpreter.runtime.builtin;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.RootCallTarget;
|
||||||
|
import com.oracle.truffle.api.Truffle;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.generic.*;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.*;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.GetArrayElementMethodGen;
|
||||||
|
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
|
/** A container class for all Polyglot-related stdlib builtins. */
|
||||||
|
public class Polyglot {
|
||||||
|
|
||||||
|
private final RootCallTarget interopDispatchRoot;
|
||||||
|
private final FunctionSchema interopDispatchSchema;
|
||||||
|
private final Function newInstanceFunction;
|
||||||
|
private final Function polyglotArrayLengthFunction;
|
||||||
|
private final Function polyglotArrayAtFunction;
|
||||||
|
private final Function polyglotToTextFunction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and registers all polyglot-related functions and types.
|
||||||
|
*
|
||||||
|
* @param language the current language instance.
|
||||||
|
* @param scope the builtin scope.
|
||||||
|
*/
|
||||||
|
public Polyglot(Language language, ModuleScope scope) {
|
||||||
|
|
||||||
|
// Note [Syntactic Functions]
|
||||||
|
interopDispatchRoot = Truffle.getRuntime().createCallTarget(MethodDispatchNode.build(language));
|
||||||
|
interopDispatchSchema =
|
||||||
|
new FunctionSchema(
|
||||||
|
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||||
|
FunctionSchema.CallerFrameAccess.NONE,
|
||||||
|
new ArgumentDefinition[] {
|
||||||
|
new ArgumentDefinition(1, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||||
|
new ArgumentDefinition(2, "method_name", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||||
|
new ArgumentDefinition(3, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE)
|
||||||
|
},
|
||||||
|
new boolean[] {false, true, false},
|
||||||
|
new CallArgumentInfo[0]);
|
||||||
|
newInstanceFunction = ConstructorDispatchNode.makeFunction(language);
|
||||||
|
polyglotArrayAtFunction = GetArrayElementMethodGen.makeFunction(language);
|
||||||
|
polyglotArrayLengthFunction = ArrayLengthMethodGen.makeFunction(language);
|
||||||
|
polyglotToTextFunction = PolyglotToTextMethodGen.makeFunction(language);
|
||||||
|
|
||||||
|
createPolyglot(language, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note [Syntactic Functions]
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
* Certain functions in this module (ones that are not being directly registered in the scope)
|
||||||
|
* are not parts of the standard library. Instead, they are used by the method dispatch system
|
||||||
|
* to call into functionality of polyglot objects. As such, they are represented as Enso-level
|
||||||
|
* functions, but they are not directly accessible through the standard library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private void createPolyglot(Language language, ModuleScope scope) {
|
||||||
|
AtomConstructor polyglot = new AtomConstructor("Polyglot", scope).initializeFields();
|
||||||
|
scope.registerConstructor(polyglot);
|
||||||
|
scope.registerMethod(polyglot, "execute", ExecuteMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(polyglot, "invoke", InvokeMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(polyglot, "new", InstantiateMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(polyglot, "get_member", GetMemberMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(polyglot, "get_members", GetMembersMethodGen.makeFunction(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Builds a function dispatching to a polyglot method call.
|
||||||
|
*
|
||||||
|
* @param method the name and scope of the method this function will dispatch to.
|
||||||
|
* @return a function calling {@code method} with given arguments.
|
||||||
|
*/
|
||||||
|
public Function buildPolyglotMethodDispatch(UnresolvedSymbol method) {
|
||||||
|
Object[] preAppliedArr = new Object[] {null, method, null};
|
||||||
|
return new Function(interopDispatchRoot, null, interopDispatchSchema, preAppliedArr, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a function taking a polyglot array and returning its length. */
|
||||||
|
public Function getPolyglotArrayLengthFunction() {
|
||||||
|
return polyglotArrayLengthFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a function taking a polyglot array and an index and accessing the item at the given
|
||||||
|
* index.
|
||||||
|
*/
|
||||||
|
public Function getPolyglotArrayAtFunction() {
|
||||||
|
return polyglotArrayAtFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a function taking a polyglot object and displaying it as a human-readable string. */
|
||||||
|
public Function getPolyglotToTextFunction() {
|
||||||
|
return polyglotToTextFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a function executing a constructor with given arguments. */
|
||||||
|
public Function getConstructorDispatch() {
|
||||||
|
return newInstanceFunction;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.enso.interpreter.runtime.builtin;
|
||||||
|
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.ConcatMethodGen;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.OptimizeMethodGen;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
|
/** A container class for all Text-related stdlib builtins. */
|
||||||
|
public class Text {
|
||||||
|
private final AtomConstructor text;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and registers all the text constructors and methods.
|
||||||
|
*
|
||||||
|
* @param language the current language instance.
|
||||||
|
* @param scope the scope to register constructors and methods in.
|
||||||
|
*/
|
||||||
|
public Text(Language language, ModuleScope scope) {
|
||||||
|
text = new AtomConstructor("Text", scope).initializeFields();
|
||||||
|
scope.registerConstructor(text);
|
||||||
|
AtomConstructor primTextHelpers =
|
||||||
|
new AtomConstructor("Prim_Text_Helper", scope).initializeFields();
|
||||||
|
scope.registerConstructor(primTextHelpers);
|
||||||
|
|
||||||
|
scope.registerMethod(text, "+", ConcatMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(primTextHelpers, "optimize", OptimizeMethodGen.makeFunction(language));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the Text atom constructor. */
|
||||||
|
public AtomConstructor getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import com.oracle.truffle.api.library.ExportLibrary;
|
|||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
import org.enso.interpreter.Constants;
|
import org.enso.interpreter.Constants;
|
||||||
import org.enso.interpreter.node.callable.MethodResolverNode;
|
import org.enso.interpreter.node.callable.MethodResolverNode;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
|
||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
@ -99,11 +100,16 @@ public class UnresolvedSymbol implements TruffleObject {
|
|||||||
UnresolvedSymbol symbol,
|
UnresolvedSymbol symbol,
|
||||||
Object[] arguments,
|
Object[] arguments,
|
||||||
@Cached MethodResolverNode methodResolverNode,
|
@Cached MethodResolverNode methodResolverNode,
|
||||||
|
@Cached HostValueToEnsoNode hostValueToEnsoNode,
|
||||||
@CachedLibrary(limit = "BUILTIN_INTEROP_DISPATCH") InteropLibrary library)
|
@CachedLibrary(limit = "BUILTIN_INTEROP_DISPATCH") InteropLibrary library)
|
||||||
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
|
throws ArityException, UnsupportedTypeException, UnsupportedMessageException {
|
||||||
|
Object[] args = new Object[arguments.length];
|
||||||
|
for (int i = 0; i < arguments.length; i++) {
|
||||||
|
args[i] = hostValueToEnsoNode.execute(arguments[i]);
|
||||||
|
}
|
||||||
if (arguments.length == 0) throw ArityException.create(1, 0);
|
if (arguments.length == 0) throw ArityException.create(1, 0);
|
||||||
Function function = methodResolverNode.execute(symbol, arguments[0]);
|
Function function = methodResolverNode.execute(symbol, args[0]);
|
||||||
return library.execute(function, arguments);
|
return library.execute(function, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,23 @@ package org.enso.interpreter.runtime.callable.atom;
|
|||||||
|
|
||||||
import com.oracle.truffle.api.CompilerDirectives;
|
import com.oracle.truffle.api.CompilerDirectives;
|
||||||
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
|
||||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
import com.oracle.truffle.api.interop.TruffleObject;
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.interop.*;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportLibrary;
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
import com.oracle.truffle.api.library.ExportMessage;
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
|
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
|
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||||
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/** A runtime representation of an Atom in Enso. */
|
/** A runtime representation of an Atom in Enso. */
|
||||||
@ -84,14 +95,65 @@ public class Atom implements TruffleObject {
|
|||||||
return toString(false);
|
return toString(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a human-readable string representation of this atom.
|
|
||||||
*
|
|
||||||
* @param allowSideEffects whether or not to allow side effects in displaying the string
|
|
||||||
* @return a string representation of this atom
|
|
||||||
*/
|
|
||||||
@ExportMessage
|
@ExportMessage
|
||||||
public Object toDisplayString(boolean allowSideEffects) {
|
public boolean hasMembers() {
|
||||||
return this.toString();
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public Array getMembers(boolean includeInternal) {
|
||||||
|
Map<String, Function> members = constructor.getDefinitionScope().getMethods().get(constructor);
|
||||||
|
if (members == null) {
|
||||||
|
return new Array(0);
|
||||||
|
}
|
||||||
|
Object[] mems = members.keySet().toArray();
|
||||||
|
return new Array(mems);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public boolean isMemberInvocable(String member) {
|
||||||
|
Map<String, ?> members = constructor.getDefinitionScope().getMethods().get(constructor);
|
||||||
|
return members != null && members.containsKey(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
static class InvokeMember {
|
||||||
|
static UnresolvedSymbol buildSym(AtomConstructor cons, String name) {
|
||||||
|
return UnresolvedSymbol.build(name, cons.getDefinitionScope());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Specialization(
|
||||||
|
guards = {"receiver.getConstructor() == cachedConstructor", "member.equals(cachedMember)"})
|
||||||
|
static Object doCached(
|
||||||
|
Atom receiver,
|
||||||
|
String member,
|
||||||
|
Object[] arguments,
|
||||||
|
@Cached(value = "receiver.getConstructor()", allowUncached = true)
|
||||||
|
AtomConstructor cachedConstructor,
|
||||||
|
@Cached(value = "member", allowUncached = true) String cachedMember,
|
||||||
|
@Cached(value = "buildSym(cachedConstructor, cachedMember)", allowUncached = true)
|
||||||
|
UnresolvedSymbol cachedSym,
|
||||||
|
@CachedLibrary("cachedSym") InteropLibrary symbols)
|
||||||
|
throws UnsupportedMessageException, ArityException, UnsupportedTypeException {
|
||||||
|
Object[] args = new Object[arguments.length + 1];
|
||||||
|
args[0] = receiver;
|
||||||
|
System.arraycopy(arguments, 0, args, 1, arguments.length);
|
||||||
|
return symbols.execute(cachedSym, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
Text toDisplayString(boolean allowSideEffects, @CachedLibrary("this") InteropLibrary atoms) {
|
||||||
|
try {
|
||||||
|
return TypesGen.expectText(atoms.invokeMember(this, "to_text"));
|
||||||
|
} catch (UnsupportedMessageException
|
||||||
|
| ArityException
|
||||||
|
| UnknownIdentifierException
|
||||||
|
| UnsupportedTypeException
|
||||||
|
| UnexpectedResultException e) {
|
||||||
|
return Text.create(this.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.enso.interpreter.runtime.data.text;
|
||||||
|
|
||||||
|
/** Represents a concatenation of two text values. */
|
||||||
|
public class ConcatRope {
|
||||||
|
private final Object left;
|
||||||
|
private final Object right;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new rope concatenating the arguments.
|
||||||
|
*
|
||||||
|
* @param left the left operand
|
||||||
|
* @param right the right operand
|
||||||
|
*/
|
||||||
|
public ConcatRope(Object left, Object right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the left operand of this concatenation. */
|
||||||
|
public Object getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the right operand of this concatenation. */
|
||||||
|
public Object getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,128 @@
|
|||||||
|
package org.enso.interpreter.runtime.data.text;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
import com.oracle.truffle.api.interop.TruffleObject;
|
||||||
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
|
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
/** The main runtime type for Enso's Text. */
|
||||||
|
@ExportLibrary(InteropLibrary.class)
|
||||||
|
public class Text implements TruffleObject {
|
||||||
|
private volatile Object contents;
|
||||||
|
private volatile boolean isFlat;
|
||||||
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
private Text(String string) {
|
||||||
|
this.contents = string;
|
||||||
|
this.isFlat = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Text(ConcatRope contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
this.isFlat = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a string in an instance of Text.
|
||||||
|
*
|
||||||
|
* @param string the string to wrap.
|
||||||
|
* @return a Text corresponding to the original string.
|
||||||
|
*/
|
||||||
|
public static Text create(String string) {
|
||||||
|
return new Text(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Text by concatenating two other texts.
|
||||||
|
*
|
||||||
|
* @param t1 the left operand.
|
||||||
|
* @param t2 the right operand.
|
||||||
|
* @return a Text representing concatenation of t1 and t2.
|
||||||
|
*/
|
||||||
|
public static Text create(Text t1, Text t2) {
|
||||||
|
return new Text(new ConcatRope(t1.contents, t2.contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Text by concatenating a text and a string.
|
||||||
|
*
|
||||||
|
* @param t1 the left operand.
|
||||||
|
* @param t2 the right operand.
|
||||||
|
* @return a Text representing concatenation of t1 and t2.
|
||||||
|
*/
|
||||||
|
public static Text create(Text t1, String t2) {
|
||||||
|
return new Text(new ConcatRope(t1.contents, t2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
boolean isString() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
String asString(@Cached("build()") @Cached.Shared("strings") ToJavaStringNode toJavaStringNode) {
|
||||||
|
return toJavaStringNode.execute(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
String toDisplayString(
|
||||||
|
boolean allowSideEffects,
|
||||||
|
@Cached("build()") @Cached.Shared("strings") ToJavaStringNode toJavaStringNode) {
|
||||||
|
String str = toJavaStringNode.execute(this);
|
||||||
|
// TODO This should be more extensible
|
||||||
|
String replaced =
|
||||||
|
str.replace("'", "\\'")
|
||||||
|
.replace("\n", "\\n")
|
||||||
|
.replace("\t", "\\t")
|
||||||
|
.replace("\u0007", "\\a")
|
||||||
|
.replace("\u0008", "\\b")
|
||||||
|
.replace("\u000c", "\\f")
|
||||||
|
.replace("\r", "\\r")
|
||||||
|
.replace("\u000B", "\\v")
|
||||||
|
.replace("\u001B", "\\e");
|
||||||
|
return "'" + replaced + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return true if this text wraps a string literal and does not require any optimization. */
|
||||||
|
public boolean isFlat() {
|
||||||
|
return isFlat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param flat the new value of the isFlat flag. */
|
||||||
|
public void setFlat(boolean flat) {
|
||||||
|
isFlat = flat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the contents of this text. */
|
||||||
|
public Object getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the contents of this text.
|
||||||
|
*
|
||||||
|
* @param contents the new contents.
|
||||||
|
*/
|
||||||
|
public void setContents(Object contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the lock required for modification of this text. */
|
||||||
|
public Lock getLock() {
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (isFlat) {
|
||||||
|
return (String) this.contents;
|
||||||
|
} else {
|
||||||
|
return ToJavaStringNode.inplaceFlatten(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,14 @@
|
|||||||
package org.enso.interpreter.runtime.error;
|
package org.enso.interpreter.runtime.error;
|
||||||
|
|
||||||
import com.oracle.truffle.api.interop.TruffleObject;
|
import com.oracle.truffle.api.interop.TruffleObject;
|
||||||
|
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||||
|
import com.oracle.truffle.api.library.CachedLibrary;
|
||||||
|
import com.oracle.truffle.api.library.ExportLibrary;
|
||||||
|
import com.oracle.truffle.api.library.ExportMessage;
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||||
|
|
||||||
/** A runtime object representing an arbitrary, user-created error. */
|
/** A runtime object representing an arbitrary, user-created error. */
|
||||||
|
@ExportLibrary(InteropLibrary.class)
|
||||||
public class RuntimeError implements TruffleObject {
|
public class RuntimeError implements TruffleObject {
|
||||||
private final Object payload;
|
private final Object payload;
|
||||||
|
|
||||||
@ -33,4 +39,16 @@ public class RuntimeError implements TruffleObject {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Error:" + getPayload().toString();
|
return "Error:" + getPayload().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
public String toDisplayString(
|
||||||
|
boolean allowSideEffects,
|
||||||
|
@CachedLibrary(limit = "3") InteropLibrary displays,
|
||||||
|
@CachedLibrary(limit = "3") InteropLibrary strings) {
|
||||||
|
try {
|
||||||
|
return "(Error: " + strings.asString(displays.toDisplayString(payload)) + ")";
|
||||||
|
} catch (UnsupportedMessageException e) {
|
||||||
|
return "Error";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.enso.interpreter.runtime.callable.atom.Atom;
|
|||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.callable.function.Function;
|
import org.enso.interpreter.runtime.callable.function.Function;
|
||||||
import org.enso.interpreter.runtime.data.Array;
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||||
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ import org.enso.interpreter.runtime.number.EnsoBigInteger;
|
|||||||
long.class,
|
long.class,
|
||||||
boolean.class,
|
boolean.class,
|
||||||
double.class,
|
double.class,
|
||||||
String.class,
|
Text.class,
|
||||||
Function.class,
|
Function.class,
|
||||||
Atom.class,
|
Atom.class,
|
||||||
AtomConstructor.class,
|
AtomConstructor.class,
|
||||||
@ -109,7 +110,7 @@ public class Types {
|
|||||||
return "Number";
|
return "Number";
|
||||||
} else if (TypesGen.isBoolean(value)) {
|
} else if (TypesGen.isBoolean(value)) {
|
||||||
return "Boolean";
|
return "Boolean";
|
||||||
} else if (TypesGen.isString(value)) {
|
} else if (TypesGen.isText(value)) {
|
||||||
return "Text";
|
return "Text";
|
||||||
} else if (TypesGen.isFunction(value)) {
|
} else if (TypesGen.isFunction(value)) {
|
||||||
return "Function";
|
return "Function";
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.enso.compiler.codegen
|
package org.enso.compiler.codegen
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer
|
||||||
|
|
||||||
import cats.Foldable
|
import cats.Foldable
|
||||||
import cats.implicits._
|
import cats.implicits._
|
||||||
import org.enso.compiler.core.IR
|
import org.enso.compiler.core.IR
|
||||||
@ -7,8 +9,17 @@ import org.enso.compiler.core.IR.Name.MethodReference
|
|||||||
import org.enso.compiler.core.IR._
|
import org.enso.compiler.core.IR._
|
||||||
import org.enso.compiler.exception.UnhandledEntity
|
import org.enso.compiler.exception.UnhandledEntity
|
||||||
import org.enso.syntax.text.AST
|
import org.enso.syntax.text.AST
|
||||||
|
import org.enso.syntax.text.Shape.{
|
||||||
|
SegmentEscape,
|
||||||
|
SegmentExpr,
|
||||||
|
SegmentPlain,
|
||||||
|
SegmentRawEscape
|
||||||
|
}
|
||||||
|
import org.enso.syntax.text.ast.text.Escape
|
||||||
|
import org.enso.syntax.text.ast.text.Escape.Unicode
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
|
import scala.util.control.Breaks.{break, breakable}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file contains the functionality that translates from the parser's
|
* This file contains the functionality that translates from the parser's
|
||||||
@ -480,16 +491,22 @@ object AstToIr {
|
|||||||
.mkString("\n")
|
.mkString("\n")
|
||||||
|
|
||||||
Literal.Text(fullString, getIdentifiedLocation(literal))
|
Literal.Text(fullString, getIdentifiedLocation(literal))
|
||||||
case AST.Literal.Text.Block.Fmt(_, _, _) =>
|
case AST.Literal.Text.Block.Fmt(lines, _, _) =>
|
||||||
Error.Syntax(
|
val ls = lines.map(l => parseFmtSegments(literal, l.text))
|
||||||
literal,
|
val err = ls.collectFirst { case Left(e) => e }
|
||||||
Error.Syntax.UnsupportedSyntax("format strings")
|
err match {
|
||||||
)
|
case Some(err) => err
|
||||||
case AST.Literal.Text.Line.Fmt(_) =>
|
case None =>
|
||||||
Error.Syntax(
|
val str = ls.collect { case Right(str) => str }.mkString("\n")
|
||||||
literal,
|
IR.Literal.Text(str, getIdentifiedLocation(literal))
|
||||||
Error.Syntax.UnsupportedSyntax("format strings")
|
}
|
||||||
)
|
case AST.Literal.Text.Line.Fmt(segments) =>
|
||||||
|
parseFmtSegments(literal, segments) match {
|
||||||
|
case Left(err) => err
|
||||||
|
case Right(str) =>
|
||||||
|
IR.Literal.Text(str, getIdentifiedLocation(literal))
|
||||||
|
}
|
||||||
|
|
||||||
case _ =>
|
case _ =>
|
||||||
throw new UnhandledEntity(literal.shape, "translateLiteral")
|
throw new UnhandledEntity(literal.shape, "translateLiteral")
|
||||||
}
|
}
|
||||||
@ -497,6 +514,70 @@ object AstToIr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def parseFmtSegments(
|
||||||
|
literal: AST,
|
||||||
|
segments: Seq[AST.Literal.Text.Segment[AST]]
|
||||||
|
): Either[IR.Error, String] = {
|
||||||
|
val bldr = new StringBuilder
|
||||||
|
var err: Option[IR.Error] = None
|
||||||
|
breakable {
|
||||||
|
segments.foreach {
|
||||||
|
case SegmentEscape(code) =>
|
||||||
|
code match {
|
||||||
|
case Escape.Number(_) =>
|
||||||
|
err = Some(
|
||||||
|
Error.Syntax(
|
||||||
|
literal,
|
||||||
|
Error.Syntax.UnsupportedSyntax("escaped numbers")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break()
|
||||||
|
case unicode: Escape.Unicode =>
|
||||||
|
unicode match {
|
||||||
|
case Unicode.InvalidUnicode(unicode) =>
|
||||||
|
err = Some(
|
||||||
|
Error.Syntax(
|
||||||
|
literal,
|
||||||
|
Error.Syntax.InvalidEscapeSequence(unicode.repr)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break()
|
||||||
|
case Unicode._U16(digits) =>
|
||||||
|
val buffer = ByteBuffer.allocate(2)
|
||||||
|
buffer.putChar(
|
||||||
|
Integer.parseInt(digits, 16).asInstanceOf[Char]
|
||||||
|
)
|
||||||
|
val str = new String(buffer.array(), "UTF-16")
|
||||||
|
bldr.addAll(str)
|
||||||
|
case Unicode._U32(digits) =>
|
||||||
|
val buffer = ByteBuffer.allocate(4)
|
||||||
|
buffer.putInt(Integer.parseInt(digits, 16))
|
||||||
|
val str = new String(buffer.array(), "UTF-32")
|
||||||
|
bldr.addAll(str)
|
||||||
|
case Unicode._U21(digits) =>
|
||||||
|
val buffer = ByteBuffer.allocate(4)
|
||||||
|
buffer.putInt(Integer.parseInt(digits, 16))
|
||||||
|
val str = new String(buffer.array(), "UTF-32")
|
||||||
|
bldr.addAll(str)
|
||||||
|
}
|
||||||
|
case e: Escape.Character => bldr.addOne(e.code)
|
||||||
|
case e: Escape.Control => bldr.addAll(e.repr)
|
||||||
|
}
|
||||||
|
case SegmentPlain(text) => bldr.addAll(text)
|
||||||
|
case SegmentExpr(_) =>
|
||||||
|
err = Some(
|
||||||
|
Error.Syntax(
|
||||||
|
literal,
|
||||||
|
Error.Syntax.UnsupportedSyntax("interpolated expressions")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
break()
|
||||||
|
case SegmentRawEscape(e) => bldr.addAll(e.repr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err.map(Left(_)).getOrElse(Right(bldr.toString))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates a sequence literal into its [[IR]] counterpart.
|
* Translates a sequence literal into its [[IR]] counterpart.
|
||||||
* @param literal the literal to translate
|
* @param literal the literal to translate
|
||||||
|
@ -65,6 +65,7 @@ import org.enso.interpreter.runtime.callable.function.{
|
|||||||
FunctionSchema,
|
FunctionSchema,
|
||||||
Function => RuntimeFunction
|
Function => RuntimeFunction
|
||||||
}
|
}
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text
|
||||||
import org.enso.interpreter.runtime.error.DuplicateArgumentNameException
|
import org.enso.interpreter.runtime.error.DuplicateArgumentNameException
|
||||||
import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope}
|
import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope}
|
||||||
import org.enso.interpreter.{Constants, Language}
|
import org.enso.interpreter.{Constants, Language}
|
||||||
@ -533,7 +534,9 @@ class IrToTruffle(
|
|||||||
.error()
|
.error()
|
||||||
.syntaxError()
|
.syntaxError()
|
||||||
.newInstance(
|
.newInstance(
|
||||||
"Type operators are not currently supported at runtime."
|
Text.create(
|
||||||
|
"Type operators are not currently supported at runtime."
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
value.location
|
value.location
|
||||||
@ -573,7 +576,7 @@ class IrToTruffle(
|
|||||||
val error = context.getBuiltins
|
val error = context.getBuiltins
|
||||||
.error()
|
.error()
|
||||||
.compileError()
|
.compileError()
|
||||||
.newInstance(message)
|
.newInstance(Text.create(message))
|
||||||
|
|
||||||
setLocation(ErrorNode.build(error), caseExpr.location)
|
setLocation(ErrorNode.build(error), caseExpr.location)
|
||||||
}
|
}
|
||||||
@ -884,19 +887,40 @@ class IrToTruffle(
|
|||||||
case Error.InvalidIR(_, _, _) =>
|
case Error.InvalidIR(_, _, _) =>
|
||||||
throw new CompilerError("Unexpected Invalid IR during codegen.")
|
throw new CompilerError("Unexpected Invalid IR during codegen.")
|
||||||
case err: Error.Syntax =>
|
case err: Error.Syntax =>
|
||||||
context.getBuiltins.error().syntaxError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.syntaxError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Redefined.Binding =>
|
case err: Error.Redefined.Binding =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Redefined.Method =>
|
case err: Error.Redefined.Method =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Redefined.Atom =>
|
case err: Error.Redefined.Atom =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Redefined.ThisArg =>
|
case err: Error.Redefined.ThisArg =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Unexpected.TypeSignature =>
|
case err: Error.Unexpected.TypeSignature =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case err: Error.Resolution =>
|
case err: Error.Resolution =>
|
||||||
context.getBuiltins.error().compileError().newInstance(err.message)
|
context.getBuiltins
|
||||||
|
.error()
|
||||||
|
.compileError()
|
||||||
|
.newInstance(Text.create(err.message))
|
||||||
case _: Error.Pattern =>
|
case _: Error.Pattern =>
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
"Impossible here, should be handled in the pattern match."
|
"Impossible here, should be handled in the pattern match."
|
||||||
@ -1064,7 +1088,9 @@ class IrToTruffle(
|
|||||||
.error()
|
.error()
|
||||||
.syntaxError()
|
.syntaxError()
|
||||||
.newInstance(
|
.newInstance(
|
||||||
"Typeset literals are not yet supported at runtime."
|
Text.create(
|
||||||
|
"Typeset literals are not yet supported at runtime."
|
||||||
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
application.location
|
application.location
|
||||||
|
@ -5570,6 +5570,10 @@ object IR {
|
|||||||
def explanation: String
|
def explanation: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case class InvalidEscapeSequence(lit: String) extends Reason {
|
||||||
|
override def explanation: String = s"Invalid escape sequence $lit."
|
||||||
|
}
|
||||||
|
|
||||||
case object InvalidBaseInDecimalLiteral extends Reason {
|
case object InvalidBaseInDecimalLiteral extends Reason {
|
||||||
override def explanation: String =
|
override def explanation: String =
|
||||||
"Cannot change base of the fractional part of a number literal."
|
"Cannot change base of the fractional part of a number literal."
|
||||||
|
@ -99,7 +99,7 @@ case object VectorLiterals extends IRPass {
|
|||||||
case seq: IR.Application.Literal.Sequence =>
|
case seq: IR.Application.Literal.Sequence =>
|
||||||
val trans = seq.mapExpressions(doExpression(_, vec))
|
val trans = seq.mapExpressions(doExpression(_, vec))
|
||||||
IR.Application.Prefix(
|
IR.Application.Prefix(
|
||||||
vec,
|
vec.duplicate(),
|
||||||
List(IR.CallArgument.Specified(None, trans, None, None)),
|
List(IR.CallArgument.Specified(None, trans, None, None)),
|
||||||
false,
|
false,
|
||||||
None
|
None
|
||||||
|
@ -24,6 +24,7 @@ import org.enso.interpreter.instrument.{
|
|||||||
Visualisation
|
Visualisation
|
||||||
}
|
}
|
||||||
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall
|
import org.enso.interpreter.node.callable.FunctionCallInstrumentationNode.FunctionCall
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text
|
||||||
import org.enso.interpreter.service.error.ServiceException
|
import org.enso.interpreter.service.error.ServiceException
|
||||||
import org.enso.polyglot.runtime.Runtime.Api
|
import org.enso.polyglot.runtime.Runtime.Api
|
||||||
import org.enso.polyglot.runtime.Runtime.Api.ContextId
|
import org.enso.polyglot.runtime.Runtime.Api.ContextId
|
||||||
@ -301,6 +302,7 @@ trait ProgramExecutionSupport {
|
|||||||
.leftMap(_.getMessage)
|
.leftMap(_.getMessage)
|
||||||
.flatMap {
|
.flatMap {
|
||||||
case text: String => Right(text.getBytes("UTF-8"))
|
case text: String => Right(text.getBytes("UTF-8"))
|
||||||
|
case text: Text => Right(text.toString.getBytes("UTF-8"))
|
||||||
case bytes: Array[Byte] => Right(bytes)
|
case bytes: Array[Byte] => Right(bytes)
|
||||||
case other =>
|
case other =>
|
||||||
Left(s"Cannot encode ${other.getClass} to byte array")
|
Left(s"Cannot encode ${other.getClass} to byte array")
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.enso.interpreter.runtime.builtin
|
package org.enso.interpreter.runtime.builtin
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.interop.InteropLibrary
|
||||||
import io.circe.Json
|
import io.circe.Json
|
||||||
import org.enso.interpreter.runtime.callable.atom.{Atom, AtomConstructor}
|
import org.enso.interpreter.runtime.callable.atom.{Atom, AtomConstructor}
|
||||||
|
|
||||||
@ -7,6 +8,7 @@ import org.enso.interpreter.runtime.callable.atom.{Atom, AtomConstructor}
|
|||||||
* Helper for JSON-serializing runtime entities of the language.
|
* Helper for JSON-serializing runtime entities of the language.
|
||||||
*/
|
*/
|
||||||
object LanguageEntitySerializer {
|
object LanguageEntitySerializer {
|
||||||
|
private val interopLibrary: InteropLibrary = InteropLibrary.getUncached()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes a language entity into a JSON string. Returns null JSON for
|
* Serializes a language entity into a JSON string. Returns null JSON for
|
||||||
@ -20,7 +22,6 @@ object LanguageEntitySerializer {
|
|||||||
|
|
||||||
private def toJson(obj: Any): Json = obj match {
|
private def toJson(obj: Any): Json = obj match {
|
||||||
case l: Long => Json.fromLong(l)
|
case l: Long => Json.fromLong(l)
|
||||||
case s: String => Json.fromString(s)
|
|
||||||
case cons: AtomConstructor =>
|
case cons: AtomConstructor =>
|
||||||
Json.obj("type" -> Json.fromString(cons.getName), "fields" -> Json.arr())
|
Json.obj("type" -> Json.fromString(cons.getName), "fields" -> Json.arr())
|
||||||
case atom: Atom =>
|
case atom: Atom =>
|
||||||
@ -28,6 +29,11 @@ object LanguageEntitySerializer {
|
|||||||
"type" -> Json.fromString(atom.getConstructor.getName),
|
"type" -> Json.fromString(atom.getConstructor.getName),
|
||||||
"fields" -> Json.arr(atom.getFields.map(toJson).toIndexedSeq: _*)
|
"fields" -> Json.arr(atom.getFields.map(toJson).toIndexedSeq: _*)
|
||||||
)
|
)
|
||||||
case _ => Json.Null
|
case _ =>
|
||||||
|
if (interopLibrary.isString(obj)) {
|
||||||
|
Json.fromString(interopLibrary.asString(obj))
|
||||||
|
} else {
|
||||||
|
Json.Null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
|||||||
| x = Panic.recover @
|
| x = Panic.recover @
|
||||||
| x.catch to_text
|
| x.catch to_text
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code) shouldEqual "Syntax_Error Unrecognized token."
|
eval(code) shouldEqual "(Syntax_Error 'Unrecognized token.')"
|
||||||
}
|
}
|
||||||
|
|
||||||
"surface redefinition errors in the language" in {
|
"surface redefinition errors in the language" in {
|
||||||
@ -42,7 +42,7 @@ class CompileDiagnosticsTest extends InterpreterTest {
|
|||||||
|
|
|
|
||||||
|main = Panic.recover here.foo . catch to_text
|
|main = Panic.recover here.foo . catch to_text
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code) shouldEqual "Compile_Error Variable x is being redefined."
|
eval(code) shouldEqual "(Compile_Error 'Variable x is being redefined.')"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ class ErrorsTest extends InterpreterTest {
|
|||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
|
|
||||||
noException shouldBe thrownBy(eval(code))
|
noException shouldBe thrownBy(eval(code))
|
||||||
consumeOut shouldEqual List("Error:MyError")
|
consumeOut shouldEqual List("(Error: MyError)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"propagate through pattern matches" in {
|
"propagate through pattern matches" in {
|
||||||
@ -64,7 +64,7 @@ class ErrorsTest extends InterpreterTest {
|
|||||||
| IO.println matched
|
| IO.println matched
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
noException shouldBe thrownBy(eval(code))
|
noException shouldBe thrownBy(eval(code))
|
||||||
consumeOut shouldEqual List("Error:MyError")
|
consumeOut shouldEqual List("(Error: MyError)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"propagate through specialized pattern matches" in {
|
"propagate through specialized pattern matches" in {
|
||||||
@ -83,7 +83,7 @@ class ErrorsTest extends InterpreterTest {
|
|||||||
| IO.println (f brokenVal)
|
| IO.println (f brokenVal)
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
noException shouldBe thrownBy(eval(code))
|
noException shouldBe thrownBy(eval(code))
|
||||||
consumeOut shouldEqual List("1", "Error:MyError")
|
consumeOut shouldEqual List("1", "(Error: MyError)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"be catchable by a user-provided special handling function" in {
|
"be catchable by a user-provided special handling function" in {
|
||||||
@ -108,7 +108,7 @@ class ErrorsTest extends InterpreterTest {
|
|||||||
| IO.println (unitErr.catch MyCons)
|
| IO.println (unitErr.catch MyCons)
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
consumeOut shouldEqual List("MyCons Unit")
|
consumeOut shouldEqual List("(MyCons Unit)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"accept a method handle in catch function" in {
|
"accept a method handle in catch function" in {
|
||||||
@ -126,7 +126,7 @@ class ErrorsTest extends InterpreterTest {
|
|||||||
| IO.println(myErr.catch recover)
|
| IO.println(myErr.catch recover)
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
consumeOut shouldEqual List("MyRecovered 20")
|
consumeOut shouldEqual List("(MyRecovered 20)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"make the catch method an identity for non-error values" in {
|
"make the catch method an identity for non-error values" in {
|
||||||
|
@ -46,7 +46,7 @@ class EvalTest extends InterpreterTest {
|
|||||||
| IO.println (MyType x)
|
| IO.println (MyType x)
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
consumeOut shouldEqual List("MyType 10")
|
consumeOut shouldEqual List("(MyType 10)")
|
||||||
}
|
}
|
||||||
|
|
||||||
"return a value usable in the caller scope" in {
|
"return a value usable in the caller scope" in {
|
||||||
|
@ -74,7 +74,7 @@ class InteropTest extends InterpreterTest {
|
|||||||
val code = "main = to_text"
|
val code = "main = to_text"
|
||||||
val symbol = eval(code)
|
val symbol = eval(code)
|
||||||
symbol.call(1) shouldEqual "1"
|
symbol.call(1) shouldEqual "1"
|
||||||
symbol.execute("Foo") shouldEqual "Foo"
|
symbol.execute("Foo") shouldEqual "'Foo'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
|||||||
|main = Cons2 5
|
|main = Cons2 5
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
|
|
||||||
eval(code).toString shouldEqual "Cons2 5 Nil2"
|
eval(code).toString shouldEqual "(Cons2 5 Nil2)"
|
||||||
}
|
}
|
||||||
|
|
||||||
"work with constructors" in {
|
"work with constructors" in {
|
||||||
|
@ -42,10 +42,10 @@ class PolyglotTest extends InterpreterTest {
|
|||||||
| class = Java.lookup_class "org.enso.example.TestClass"
|
| class = Java.lookup_class "org.enso.example.TestClass"
|
||||||
| instance = Polyglot.new class Array.empty
|
| instance = Polyglot.new class Array.empty
|
||||||
| members = Polyglot.get_members instance
|
| members = Polyglot.get_members instance
|
||||||
| IO.println (Polyglot.get_array_size members)
|
| IO.println members.length
|
||||||
| IO.println (Polyglot.get_array_element members 0)
|
| IO.println (members.at 0)
|
||||||
| IO.println (Polyglot.get_array_element members 1)
|
| IO.println (members.at 1)
|
||||||
| IO.println (Polyglot.get_array_element members 2)
|
| IO.println (members.at 2)
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
val count :: methods = consumeOut
|
val count :: methods = consumeOut
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package org.enso.interpreter.test.semantic
|
package org.enso.interpreter.test.semantic
|
||||||
|
|
||||||
import org.enso.interpreter.test.{InterpreterTest, InterpreterContext}
|
import org.enso.interpreter.test.{InterpreterContext, InterpreterTest}
|
||||||
|
|
||||||
class TextTest extends InterpreterTest {
|
class TextTest extends InterpreterTest {
|
||||||
override def subject = "Text Library"
|
override def subject = "Text Library"
|
||||||
|
|
||||||
override def specify(
|
override def specify(implicit
|
||||||
implicit interpreterContext: InterpreterContext
|
interpreterContext: InterpreterContext
|
||||||
): Unit = {
|
): Unit = {
|
||||||
|
|
||||||
"support text creation with single-line literals" in {
|
"support text creation with single-line literals" in {
|
||||||
@ -40,12 +40,12 @@ class TextTest extends InterpreterTest {
|
|||||||
|type My_Type a
|
|type My_Type a
|
||||||
|
|
|
|
||||||
|main =
|
|main =
|
||||||
| IO.println 5.to_text
|
| IO.println 5
|
||||||
| IO.println (My_Type (My_Type 10)).to_text
|
| IO.println (My_Type (My_Type 10))
|
||||||
| IO.println "123".to_text
|
| IO.println "123"
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
eval(code)
|
eval(code)
|
||||||
consumeOut shouldEqual List("5", "My_Type (My_Type 10)", "123")
|
consumeOut shouldEqual List("5", "(My_Type (My_Type 10))", "123")
|
||||||
}
|
}
|
||||||
|
|
||||||
"support text creation with raw block literals" in {
|
"support text creation with raw block literals" in {
|
||||||
@ -77,17 +77,14 @@ class TextTest extends InterpreterTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
"support printing to standard error" in {
|
"support printing to standard error" in {
|
||||||
val errString = "\"My error string\""
|
|
||||||
val resultStr = errString.drop(1).dropRight(1)
|
|
||||||
|
|
||||||
val code =
|
val code =
|
||||||
s"""from Builtins import all
|
s"""from Builtins import all
|
||||||
|
|
|
|
||||||
|main = IO.print_err $errString
|
|main = IO.print_err "My error string"
|
||||||
|""".stripMargin
|
|""".stripMargin
|
||||||
|
|
||||||
eval(code)
|
eval(code)
|
||||||
consumeErr shouldEqual List(resultStr)
|
consumeErr shouldEqual List("My error string")
|
||||||
}
|
}
|
||||||
|
|
||||||
"support reading from standard input" in {
|
"support reading from standard input" in {
|
||||||
|
@ -128,47 +128,49 @@ object Escape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reference: https://en.wikipedia.org/wiki/String_literal
|
// Reference: https://en.wikipedia.org/wiki/String_literal
|
||||||
sealed trait Character extends Escape
|
sealed trait Character extends Escape {
|
||||||
|
def code: Char
|
||||||
|
}
|
||||||
object Character {
|
object Character {
|
||||||
case object a extends Character {
|
case object a extends Character {
|
||||||
val code: Int = '\u0007'
|
override val code: Char = '\u0007'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object b extends Character {
|
case object b extends Character {
|
||||||
val code: Int = '\u0008'
|
override val code: Char = '\u0008'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object f extends Character {
|
case object f extends Character {
|
||||||
val code: Int = '\u000C'
|
override val code: Char = '\u000C'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object n extends Character {
|
case object n extends Character {
|
||||||
val code: Int = '\n'
|
override val code: Char = '\n'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object r extends Character {
|
case object r extends Character {
|
||||||
val code: Int = '\r'
|
override val code: Char = '\r'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object t extends Character {
|
case object t extends Character {
|
||||||
val code: Int = '\u0009'
|
override val code: Char = '\u0009'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object v extends Character {
|
case object v extends Character {
|
||||||
val code: Int = '\u000B'
|
override val code: Char = '\u000B'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object e extends Character {
|
case object e extends Character {
|
||||||
val code: Int = '\u001B'
|
override val code: Char = '\u001B'
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
val codes = ADT.constructors[Character]
|
val codes = ADT.constructors[Character]
|
||||||
}
|
}
|
||||||
@ -229,32 +231,32 @@ object Escape {
|
|||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object LF extends Control {
|
case object LF extends Control {
|
||||||
val code: Int = 0x0A
|
val code: Int = 0x0a
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object VT extends Control {
|
case object VT extends Control {
|
||||||
val code: Int = 0x0B
|
val code: Int = 0x0b
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object FF extends Control {
|
case object FF extends Control {
|
||||||
val code: Int = 0x0C
|
val code: Int = 0x0c
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object CR extends Control {
|
case object CR extends Control {
|
||||||
val code: Int = 0x0D
|
val code: Int = 0x0d
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object SO extends Control {
|
case object SO extends Control {
|
||||||
val code: Int = 0x0E
|
val code: Int = 0x0e
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object SI extends Control {
|
case object SI extends Control {
|
||||||
val code: Int = 0x0F
|
val code: Int = 0x0f
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
@ -309,37 +311,37 @@ object Escape {
|
|||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object SUB extends Control {
|
case object SUB extends Control {
|
||||||
val code: Int = 0x1A
|
val code: Int = 0x1a
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object ESC extends Control {
|
case object ESC extends Control {
|
||||||
val code: Int = 0x1B
|
val code: Int = 0x1b
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object FS extends Control {
|
case object FS extends Control {
|
||||||
val code: Int = 0x1C
|
val code: Int = 0x1c
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object GS extends Control {
|
case object GS extends Control {
|
||||||
val code: Int = 0x1D
|
val code: Int = 0x1d
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object RS extends Control {
|
case object RS extends Control {
|
||||||
val code: Int = 0x1E
|
val code: Int = 0x1e
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object US extends Control {
|
case object US extends Control {
|
||||||
val code: Int = 0x1F
|
val code: Int = 0x1f
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
case object DEL extends Control {
|
case object DEL extends Control {
|
||||||
val code: Int = 0x7F
|
val code: Int = 0x7f
|
||||||
def name: String = toString
|
def name: String = toString
|
||||||
override val repr = name
|
override val repr = name
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
106
std-bits/pom.xml
Normal file
106
std-bits/pom.xml
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.enso</groupId>
|
||||||
|
<artifactId>base</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>base</name>
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ibm.icu</groupId>
|
||||||
|
<artifactId>icu4j</artifactId>
|
||||||
|
<version>67.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>2.3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>
|
||||||
|
${project.build.directory}/../../distribution/std-lib/Base/polyglot/java
|
||||||
|
</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>license-maven-plugin</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-third-party-licenses</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>download-licenses</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<licensesOutputDirectory>
|
||||||
|
${project.build.directory}/../../distribution/std-lib/Base/third-party-licenses
|
||||||
|
</licensesOutputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>add-third-party-licenses-list</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-third-party</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>
|
||||||
|
${project.build.directory}/../../distribution/std-lib/Base/third-party-licenses
|
||||||
|
</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.10</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>copy</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>copy</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<artifactItems>
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>com.ibm.icu</groupId>
|
||||||
|
<artifactId>icu4j</artifactId>
|
||||||
|
<version>67.1</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<destFileName>icu4j.jar</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
</artifactItems>
|
||||||
|
<outputDirectory>
|
||||||
|
${project.build.directory}/../../distribution/std-lib/Base/polyglot/java
|
||||||
|
</outputDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
87
std-bits/src/main/java/org/enso/base/Text_Utils.java
Normal file
87
std-bits/src/main/java/org/enso/base/Text_Utils.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package org.enso.base;
|
||||||
|
|
||||||
|
import com.ibm.icu.text.Normalizer2;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** Utils for standard library operations on Text. */
|
||||||
|
public class Text_Utils {
|
||||||
|
/**
|
||||||
|
* Creates a substring of the given string, indexing using the Java standard (UTF-16) indexing
|
||||||
|
* mechanism.
|
||||||
|
*
|
||||||
|
* @param string the string to substring
|
||||||
|
* @param from starting index
|
||||||
|
* @param to index one past the end of the desired substring
|
||||||
|
* @return a suitable substring
|
||||||
|
*/
|
||||||
|
public static String substring(String string, int from, int to) {
|
||||||
|
return string.substring(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string into an array of UTF-8 bytes.
|
||||||
|
*
|
||||||
|
* @param str the string to convert
|
||||||
|
* @return the UTF-8 representation of the string.
|
||||||
|
*/
|
||||||
|
public static byte[] get_bytes(String str) {
|
||||||
|
return str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string into an array of Unicode codepoints.
|
||||||
|
*
|
||||||
|
* @param str the string to convert
|
||||||
|
* @return the codepoints of the original string.
|
||||||
|
*/
|
||||||
|
public static int[] get_codepoints(String str) {
|
||||||
|
return str.codePoints().toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits the string on each occurrence of {@code sep}, returning the resulting substrings in an
|
||||||
|
* array.
|
||||||
|
*
|
||||||
|
* @param str the string to split
|
||||||
|
* @param sep the separator string
|
||||||
|
* @return array of substrings of {@code str} contained between occurences of {@code sep}
|
||||||
|
*/
|
||||||
|
public static String[] split_at(String str, String sep) {
|
||||||
|
return str.split(Pattern.quote(sep));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether two strings are equal up to Unicode canonicalization.
|
||||||
|
*
|
||||||
|
* @param str1 the first string
|
||||||
|
* @param str2 the second string
|
||||||
|
* @return the result of comparison
|
||||||
|
*/
|
||||||
|
public static boolean equals(String str1, String str2) {
|
||||||
|
return Normalizer2.getNFDInstance()
|
||||||
|
.normalize(str1)
|
||||||
|
.equals(Normalizer2.getNFDInstance().normalize(str2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an array of codepoints into a string.
|
||||||
|
*
|
||||||
|
* @param codepoints the codepoints to convert
|
||||||
|
* @return the resulting string
|
||||||
|
*/
|
||||||
|
public static String from_codepoints(int[] codepoints) {
|
||||||
|
return new String(codepoints, 0, codepoints.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an array of UTF-8 bytes into a string.
|
||||||
|
*
|
||||||
|
* @param bytes the bytes to convert
|
||||||
|
* @return the resulting string
|
||||||
|
*/
|
||||||
|
public static String from_utf_8(byte[] bytes) {
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,12 @@ sum_tco_decimal = sum_to ->
|
|||||||
res = summator 0.0 0.0
|
res = summator 0.0 0.0
|
||||||
res
|
res
|
||||||
|
|
||||||
|
sum_tco_eval = sumTo ->
|
||||||
|
summator = acc -> current ->
|
||||||
|
if current == 0 then acc else Debug.eval "summator (acc + current) (current - 1)"
|
||||||
|
|
||||||
|
res = summator 0 sumTo
|
||||||
|
res
|
||||||
|
|
||||||
sum_tco_java = sum_to ->
|
sum_tco_java = sum_to ->
|
||||||
summator = acc -> current ->
|
summator = acc -> current ->
|
||||||
@ -49,11 +55,13 @@ sum_state = sum_to ->
|
|||||||
main =
|
main =
|
||||||
hundred_mil = 100000000
|
hundred_mil = 100000000
|
||||||
IO.println "Measuring Sum TCO Decimal"
|
IO.println "Measuring Sum TCO Decimal"
|
||||||
Bench_Utils.measure (here.sum_tco_decimal hundred_mil) "sum_tco" 100 10
|
Bench_Utils.measure (here.sum_tco_decimal hundred_mil) "sum_tco_float" 100 10
|
||||||
IO.println "Measuring SumTCO"
|
IO.println "Measuring SumTCO"
|
||||||
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10
|
Bench_Utils.measure (here.sum_tco hundred_mil) "sum_tco" 100 10
|
||||||
IO.println "Measuring SumTCO Java"
|
IO.println "Measuring SumTCO Java"
|
||||||
Bench_Utils.measure (here.sum_tco_java hundred_mil) "sum_tco" 100 10
|
Bench_Utils.measure (here.sum_tco_java hundred_mil) "sum_tco_java" 100 10
|
||||||
|
IO.println "Measuring SumTCO Eval"
|
||||||
|
Bench_Utils.measure (here.sum_tco_eval hundred_mil) "sum_tco_eval" 100 10
|
||||||
IO.println "Measuring State"
|
IO.println "Measuring State"
|
||||||
Bench_Utils.measure (here.sum_state hundred_mil) "sum_state" 100 10
|
Bench_Utils.measure (here.sum_state hundred_mil) "sum_state" 100 10
|
||||||
IO.println "Measuring Co-State"
|
IO.println "Measuring Co-State"
|
||||||
|
21
test/Benchmarks/src/Text.enso
Normal file
21
test/Benchmarks/src/Text.enso
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
from Base import all
|
||||||
|
from Builtins import Prim_Text_Helper
|
||||||
|
import Base.Bench_Utils
|
||||||
|
|
||||||
|
polyglot java import java.lang.StringBuilder
|
||||||
|
|
||||||
|
build_long n =
|
||||||
|
res = 1.upto n . fold "" acc-> n-> acc + n.to_text
|
||||||
|
Prim_Text_Helper.optimize res
|
||||||
|
res
|
||||||
|
|
||||||
|
build_long_bldr n =
|
||||||
|
bldr = new StringBuilder [].to_array
|
||||||
|
1.upto n . each n-> bldr.append [n]
|
||||||
|
res = bldr.toString []
|
||||||
|
res
|
||||||
|
|
||||||
|
main =
|
||||||
|
Bench_Utils.measure (here.build_long_bldr 1000000) "string append bldr" 100 10
|
||||||
|
Bench_Utils.measure (here.build_long 1000000) "string append" 100 10
|
||||||
|
IO.println "Bye"
|
@ -4,11 +4,22 @@ import Base.Test
|
|||||||
polyglot java import java.lang.Long
|
polyglot java import java.lang.Long
|
||||||
polyglot java import java.lang.Integer
|
polyglot java import java.lang.Integer
|
||||||
polyglot java import java.lang.Float
|
polyglot java import java.lang.Float
|
||||||
|
polyglot java import java.lang.String
|
||||||
|
polyglot java import java.util.ArrayList
|
||||||
|
|
||||||
spec = describe "Java FFI" <|
|
spec = describe "Java FFI" <|
|
||||||
it "should call methods imported from Java" <|
|
it "should call methods imported from Java" <|
|
||||||
Long.sum [1, 2] . should_equal 3
|
Long.sum [1, 2] . should_equal 3
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
https://github.com/enso-org/enso/issues/1163
|
||||||
|
it "should call constructors imported from Java" pending=True <|
|
||||||
|
list = ArrayList.new []
|
||||||
|
list.add 432
|
||||||
|
list.get [0] . should_equal 432
|
||||||
it "should auto-convert numeric types across the polyglot boundary" <|
|
it "should auto-convert numeric types across the polyglot boundary" <|
|
||||||
(Float.valueOf ["123.3"] + 5).should_equal 128.3 epsilon=0.0001
|
(Float.valueOf ["123.3"] + 5).should_equal 128.3 epsilon=0.0001
|
||||||
(Integer.sum [1, 2] + 3) . should_equal 6
|
(Integer.sum [1, 2] + 3) . should_equal 6
|
||||||
|
it "should auto-convert strings across the polyglot boundary" <|
|
||||||
|
(String.format ["%s bar %s", "baz", "quux"] + " foo").should_equal "baz bar quux foo"
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import Test.Process_Spec
|
|||||||
import Test.Java_Interop.Spec as Java_Spec
|
import Test.Java_Interop.Spec as Java_Spec
|
||||||
import Test.Vector.Spec as Vector_Spec
|
import Test.Vector.Spec as Vector_Spec
|
||||||
import Test.Numbers.Spec as Numbers_Spec
|
import Test.Numbers.Spec as Numbers_Spec
|
||||||
|
import Test.Text.Spec as Text_Spec
|
||||||
|
|
||||||
main = Test.Suite.runMain <|
|
main = Test.Suite.runMain <|
|
||||||
List_Spec.spec
|
List_Spec.spec
|
||||||
@ -19,3 +20,4 @@ main = Test.Suite.runMain <|
|
|||||||
Java_Spec.spec
|
Java_Spec.spec
|
||||||
Vector_Spec.spec
|
Vector_Spec.spec
|
||||||
Numbers_Spec.spec
|
Numbers_Spec.spec
|
||||||
|
Text_Spec.spec
|
||||||
|
42
test/Test/src/Text/Spec.enso
Normal file
42
test/Test/src/Text/Spec.enso
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
from Base import all
|
||||||
|
import Base.Test
|
||||||
|
|
||||||
|
type Auto a
|
||||||
|
|
||||||
|
type Manual b
|
||||||
|
|
||||||
|
Manual.to_text = "[[[MyREP " + this.b.to_text + "]]]"
|
||||||
|
|
||||||
|
spec = describe "Text" <|
|
||||||
|
kshi = '\u0915\u094D\u0937\u093F'
|
||||||
|
kshi_utf_8 = [-32, -92, -107, -32, -91, -115, -32, -92, -73, -32, -92, -65]
|
||||||
|
facepalm = '\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F'
|
||||||
|
facepalm_codes = [129318, 127996, 8205, 9794, 65039]
|
||||||
|
accent_1 = '\u00E9'
|
||||||
|
accent_2 = '\u0065\u{301}'
|
||||||
|
it "should compare strings using utf normalization" <|
|
||||||
|
"abc".equals "def" . should_be_false
|
||||||
|
accent_1 . should_equal accent_2
|
||||||
|
it "should split the text into grapheme clusters" <|
|
||||||
|
str = kshi + facepalm + accent_1 + accent_2
|
||||||
|
str.characters . should_equal [kshi, facepalm, accent_1, accent_2]
|
||||||
|
it "should split the text on arbitrary sequence" <|
|
||||||
|
"foo, bar, baz" . split_at ", " . should_equal ["foo", "bar", "baz"]
|
||||||
|
it "should dump utf-8 bytes to a vector" <|
|
||||||
|
kshi.utf_8.should_equal kshi_utf_8
|
||||||
|
it "should convert an array of bytes to text" <|
|
||||||
|
Text.from_utf_8 kshi_utf_8 . should_equal kshi
|
||||||
|
it "should dump utf codepoints to a vector" <|
|
||||||
|
facepalm.codepoints.should_equal facepalm_codes
|
||||||
|
it "should convert an array of codepoints to text" <|
|
||||||
|
Text.from_codepoints facepalm_codes . should_equal facepalm
|
||||||
|
it "should convert any type to text automatically and using provided methods" <|
|
||||||
|
t = Auto (Manual 123) . to_text
|
||||||
|
t.should_equal "(Auto [[[MyREP 123]]])"
|
||||||
|
it "should escape special characters when debug-printing text" <|
|
||||||
|
text_1 = '''
|
||||||
|
foo
|
||||||
|
bar\r\tbaz
|
||||||
|
text_1.to_text.should_equal "'foo\\nbar\\r\\tbaz'"
|
||||||
|
text_2 = '\n\t\a\b\f\r\v\e\''
|
||||||
|
text_2.to_text.should_equal "'\\n\\t\\a\\b\\f\\r\\v\\e\\''"
|
@ -19,4 +19,8 @@ spec = describe "Vectors" <|
|
|||||||
mapped = vec.map x-> x * x
|
mapped = vec.map x-> x * x
|
||||||
vec.to_text.should_equal "[1, 2, 3, 4]"
|
vec.to_text.should_equal "[1, 2, 3, 4]"
|
||||||
mapped.to_text.should_equal "[1, 4, 9, 16]"
|
mapped.to_text.should_equal "[1, 4, 9, 16]"
|
||||||
|
it "should define equality" <|
|
||||||
|
[1,2,3].equals [1,2] . should_be_false
|
||||||
|
[1,2,3].equals [1,2,3] . should_be_true
|
||||||
|
[1,2,3].equals [3,4,5] . should_be_false
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user