mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 22:10:15 +03:00
Standard Library Nodes DSL (#932)
This commit is contained in:
parent
5101840dae
commit
0b9558d962
451
build.sbt
451
build.sbt
@ -27,50 +27,50 @@ Global / onChangedBuildSource := ReloadOnSourceChanges
|
||||
// ============================================================================
|
||||
|
||||
javacOptions in ThisBuild ++= Seq(
|
||||
"-encoding", // Provide explicit encoding (the next line)
|
||||
"UTF-8", // Specify character encoding used by Java source files.
|
||||
"-deprecation" // Shows a description of each use or override of a deprecated member or class.
|
||||
)
|
||||
"-encoding", // Provide explicit encoding (the next line)
|
||||
"UTF-8", // Specify character encoding used by Java source files.
|
||||
"-deprecation" // Shows a description of each use or override of a deprecated member or class.
|
||||
)
|
||||
|
||||
scalacOptions in ThisBuild ++= Seq(
|
||||
"-deprecation", // Emit warning and location for usages of deprecated APIs.
|
||||
"-encoding", // Provide explicit encoding (the next line)
|
||||
"utf-8", // Specify character encoding used by Scala source files.
|
||||
"-explaintypes", // Explain type errors in more detail.
|
||||
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
|
||||
"-language:existentials", // Existential types (besides wildcard types) can be written and inferred
|
||||
"-language:experimental.macros", // Allow macro definition (besides implementation and application)
|
||||
"-language:higherKinds", // Allow higher-kinded types
|
||||
"-language:implicitConversions", // Allow definition of implicit functions called views
|
||||
"-unchecked", // Enable additional warnings where generated code depends on assumptions.
|
||||
"-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
|
||||
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
|
||||
"-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
|
||||
"-Xlint:delayedinit-select", // Selecting member of DelayedInit.
|
||||
"-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element.
|
||||
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
|
||||
"-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
|
||||
"-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
|
||||
"-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
|
||||
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
|
||||
"-Xlint:option-implicit", // Option.apply used implicit view.
|
||||
"-Xlint:package-object-classes", // Class or object defined in package object.
|
||||
"-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds.
|
||||
"-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field.
|
||||
"-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component.
|
||||
"-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope.
|
||||
"-Xmacro-settings:-logging@org.enso", // Disable the debug logging globally.
|
||||
"-Ywarn-dead-code", // Warn when dead code is identified.
|
||||
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
|
||||
"-Ywarn-numeric-widen", // Warn when numerics are widened.
|
||||
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
|
||||
"-Ywarn-unused:implicits", // Warn if an implicit parameter is unused.
|
||||
"-Ywarn-unused:locals", // Warn if a local definition is unused.
|
||||
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
|
||||
"-Ywarn-unused:privates", // Warn if a private member is unused.
|
||||
"-Ywarn-unused:params", // Warn if a value parameter is unused.
|
||||
"-Xfatal-warnings" // Make warnings fatal so they don't make it onto main (use @nowarn for local suppression)
|
||||
)
|
||||
"-deprecation", // Emit warning and location for usages of deprecated APIs.
|
||||
"-encoding", // Provide explicit encoding (the next line)
|
||||
"utf-8", // Specify character encoding used by Scala source files.
|
||||
"-explaintypes", // Explain type errors in more detail.
|
||||
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
|
||||
"-language:existentials", // Existential types (besides wildcard types) can be written and inferred
|
||||
"-language:experimental.macros", // Allow macro definition (besides implementation and application)
|
||||
"-language:higherKinds", // Allow higher-kinded types
|
||||
"-language:implicitConversions", // Allow definition of implicit functions called views
|
||||
"-unchecked", // Enable additional warnings where generated code depends on assumptions.
|
||||
"-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
|
||||
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
|
||||
"-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
|
||||
"-Xlint:delayedinit-select", // Selecting member of DelayedInit.
|
||||
"-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element.
|
||||
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
|
||||
"-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
|
||||
"-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
|
||||
"-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
|
||||
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
|
||||
"-Xlint:option-implicit", // Option.apply used implicit view.
|
||||
"-Xlint:package-object-classes", // Class or object defined in package object.
|
||||
"-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds.
|
||||
"-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field.
|
||||
"-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component.
|
||||
"-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope.
|
||||
"-Xmacro-settings:-logging@org.enso", // Disable the debug logging globally.
|
||||
"-Ywarn-dead-code", // Warn when dead code is identified.
|
||||
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
|
||||
"-Ywarn-numeric-widen", // Warn when numerics are widened.
|
||||
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
|
||||
"-Ywarn-unused:implicits", // Warn if an implicit parameter is unused.
|
||||
"-Ywarn-unused:locals", // Warn if a local definition is unused.
|
||||
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
|
||||
"-Ywarn-unused:privates", // Warn if a private member is unused.
|
||||
"-Ywarn-unused:params", // Warn if a value parameter is unused.
|
||||
"-Xfatal-warnings" // Make warnings fatal so they don't make it onto main (use @nowarn for local suppression)
|
||||
)
|
||||
|
||||
val jsSettings = Seq(
|
||||
scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) }
|
||||
@ -136,8 +136,8 @@ lazy val enso = (project in file("."))
|
||||
|
||||
// === Akka ===================================================================
|
||||
|
||||
def akkaPkg(name: String) = akkaURL %% s"akka-$name" % akkaVersion
|
||||
def akkaHTTPPkg(name: String) = akkaURL %% s"akka-$name" % akkaHTTPVersion
|
||||
def akkaPkg(name: String) = akkaURL %% s"akka-$name" % akkaVersion
|
||||
def akkaHTTPPkg(name: String) = akkaURL %% s"akka-$name" % akkaHTTPVersion
|
||||
val akkaURL = "com.typesafe.akka"
|
||||
val akkaVersion = "2.6.4"
|
||||
val akkaHTTPVersion = "10.2.0-M1"
|
||||
@ -199,7 +199,7 @@ val jacksonVersion = "2.10.3"
|
||||
val jackson = Seq(
|
||||
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-cbor" % jacksonVersion,
|
||||
"com.fasterxml.jackson.core" % "jackson-databind" % jacksonVersion,
|
||||
"com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion
|
||||
"com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonVersion
|
||||
)
|
||||
|
||||
// === JMH ====================================================================
|
||||
@ -296,10 +296,10 @@ lazy val flexer = crossProject(JVMPlatform, JSPlatform)
|
||||
version := "0.1",
|
||||
resolvers += Resolver.sonatypeRepo("releases"),
|
||||
libraryDependencies ++= scalaCompiler ++ Seq(
|
||||
"com.google.guava" % "guava" % guavaVersion,
|
||||
"org.typelevel" %%% "cats-core" % catsVersion,
|
||||
"org.typelevel" %%% "kittens" % kittensVersion
|
||||
)
|
||||
"com.google.guava" % "guava" % guavaVersion,
|
||||
"org.typelevel" %%% "cats-core" % catsVersion,
|
||||
"org.typelevel" %%% "kittens" % kittensVersion
|
||||
)
|
||||
)
|
||||
.jsSettings(jsSettings)
|
||||
|
||||
@ -311,13 +311,13 @@ lazy val `syntax-definition` = crossProject(JVMPlatform, JSPlatform)
|
||||
.settings(
|
||||
scalacOptions ++= Seq("-Ypatmat-exhaust-depth", "off"),
|
||||
libraryDependencies ++= monocle ++ scalaCompiler ++ Seq(
|
||||
"org.typelevel" %%% "cats-core" % catsVersion,
|
||||
"org.typelevel" %%% "kittens" % kittensVersion,
|
||||
"com.lihaoyi" %%% "scalatags" % scalatagsVersion,
|
||||
"io.circe" %%% "circe-core" % circeVersion,
|
||||
"io.circe" %%% "circe-generic" % circeVersion,
|
||||
"io.circe" %%% "circe-parser" % circeVersion
|
||||
)
|
||||
"org.typelevel" %%% "cats-core" % catsVersion,
|
||||
"org.typelevel" %%% "kittens" % kittensVersion,
|
||||
"com.lihaoyi" %%% "scalatags" % scalatagsVersion,
|
||||
"io.circe" %%% "circe-core" % circeVersion,
|
||||
"io.circe" %%% "circe-generic" % circeVersion,
|
||||
"io.circe" %%% "circe-parser" % circeVersion
|
||||
)
|
||||
)
|
||||
.jsSettings(jsSettings)
|
||||
|
||||
@ -335,35 +335,35 @@ lazy val syntax = crossProject(JVMPlatform, JSPlatform)
|
||||
version := "0.1",
|
||||
logBuffered := false,
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scalatest" %%% "scalatest" % scalatestVersion % Test,
|
||||
"com.lihaoyi" %%% "pprint" % pprintVersion,
|
||||
"io.circe" %%% "circe-core" % circeVersion,
|
||||
"io.circe" %%% "circe-generic" % circeVersion,
|
||||
"io.circe" %%% "circe-parser" % circeVersion
|
||||
),
|
||||
"org.scalatest" %%% "scalatest" % scalatestVersion % Test,
|
||||
"com.lihaoyi" %%% "pprint" % pprintVersion,
|
||||
"io.circe" %%% "circe-core" % circeVersion,
|
||||
"io.circe" %%% "circe-generic" % circeVersion,
|
||||
"io.circe" %%% "circe-parser" % circeVersion
|
||||
),
|
||||
compile := (Compile / compile)
|
||||
.dependsOn(Def.taskDyn {
|
||||
val parserCompile =
|
||||
(`syntax-definition`.jvm / Compile / compileIncremental).value
|
||||
if (parserCompile.hasModified) {
|
||||
Def.task {
|
||||
streams.value.log.info("Parser changed, forcing recompilation.")
|
||||
clean.value
|
||||
}
|
||||
} else Def.task {}
|
||||
})
|
||||
.value
|
||||
.dependsOn(Def.taskDyn {
|
||||
val parserCompile =
|
||||
(`syntax-definition`.jvm / Compile / compileIncremental).value
|
||||
if (parserCompile.hasModified) {
|
||||
Def.task {
|
||||
streams.value.log.info("Parser changed, forcing recompilation.")
|
||||
clean.value
|
||||
}
|
||||
} else Def.task {}
|
||||
})
|
||||
.value
|
||||
)
|
||||
.jvmSettings(
|
||||
inConfig(Benchmark)(Defaults.testSettings),
|
||||
unmanagedSourceDirectories in Benchmark +=
|
||||
baseDirectory.value.getParentFile / "shared/src/bench/scala",
|
||||
baseDirectory.value.getParentFile / "shared/src/bench/scala",
|
||||
libraryDependencies +=
|
||||
"com.storm-enroute" %% "scalameter" % scalameterVersion % "bench",
|
||||
"com.storm-enroute" %% "scalameter" % scalameterVersion % "bench",
|
||||
testFrameworks := List(
|
||||
new TestFramework("org.scalatest.tools.Framework"),
|
||||
new TestFramework("org.scalameter.ScalaMeterFramework")
|
||||
),
|
||||
new TestFramework("org.scalatest.tools.Framework"),
|
||||
new TestFramework("org.scalameter.ScalaMeterFramework")
|
||||
),
|
||||
bench := (test in Benchmark).tag(Exclusive).value
|
||||
)
|
||||
.jsSettings(
|
||||
@ -385,10 +385,10 @@ lazy val `text-buffer` = project
|
||||
.configs(Test)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||
)
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||
)
|
||||
)
|
||||
|
||||
lazy val graph = (project in file("lib/graph/"))
|
||||
@ -397,18 +397,18 @@ lazy val graph = (project in file("lib/graph/"))
|
||||
.settings(
|
||||
version := "0.1",
|
||||
resolvers ++= Seq(
|
||||
Resolver.sonatypeRepo("releases"),
|
||||
Resolver.sonatypeRepo("snapshots")
|
||||
),
|
||||
Resolver.sonatypeRepo("releases"),
|
||||
Resolver.sonatypeRepo("snapshots")
|
||||
),
|
||||
scalacOptions += "-Ymacro-annotations",
|
||||
libraryDependencies ++= scalaCompiler ++ Seq(
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"io.estatico" %% "newtype" % newtypeVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"com.github.julien-truffaut" %% "monocle-core" % monocleVersion,
|
||||
"org.apache.commons" % "commons-lang3" % commonsLangVersion
|
||||
),
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"io.estatico" %% "newtype" % newtypeVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"com.github.julien-truffaut" %% "monocle-core" % monocleVersion,
|
||||
"org.apache.commons" % "commons-lang3" % commonsLangVersion
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
),
|
||||
@ -423,9 +423,9 @@ lazy val pkg = (project in file("lib/pkg"))
|
||||
mainClass in (Compile, run) := Some("org.enso.pkg.Main"),
|
||||
version := "0.1",
|
||||
libraryDependencies ++= circe ++ Seq(
|
||||
"io.circe" %% "circe-yaml" % circeYamlVersion, // separate from other circe deps because its independent project with its own versioning
|
||||
"commons-io" % "commons-io" % commonsIoVersion
|
||||
)
|
||||
"io.circe" %% "circe-yaml" % circeYamlVersion, // separate from other circe deps because its independent project with its own versioning
|
||||
"commons-io" % "commons-io" % commonsIoVersion
|
||||
)
|
||||
)
|
||||
|
||||
lazy val `project-manager` = (project in file("lib/project-manager"))
|
||||
@ -447,17 +447,17 @@ lazy val `project-manager` = (project in file("lib/project-manager"))
|
||||
libraryDependencies ++= akka,
|
||||
libraryDependencies ++= circe,
|
||||
libraryDependencies ++= Seq(
|
||||
"com.typesafe" % "config" % typesafeConfigVersion,
|
||||
"com.github.pureconfig" %% "pureconfig" % pureconfigVersion,
|
||||
"ch.qos.logback" % "logback-classic" % logbackClassicVersion,
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
|
||||
"dev.zio" %% "zio" % zioVersion,
|
||||
"dev.zio" %% "zio-interop-cats" % zioInteropCatsVersion,
|
||||
"commons-io" % "commons-io" % commonsIoVersion,
|
||||
"com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion,
|
||||
"com.miguno.akka" %% "akka-mock-scheduler" % akkaMockSchedulerVersion % Test,
|
||||
"org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test
|
||||
),
|
||||
"com.typesafe" % "config" % typesafeConfigVersion,
|
||||
"com.github.pureconfig" %% "pureconfig" % pureconfigVersion,
|
||||
"ch.qos.logback" % "logback-classic" % logbackClassicVersion,
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
|
||||
"dev.zio" %% "zio" % zioVersion,
|
||||
"dev.zio" %% "zio-interop-cats" % zioInteropCatsVersion,
|
||||
"commons-io" % "commons-io" % commonsIoVersion,
|
||||
"com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion,
|
||||
"com.miguno.akka" %% "akka-mock-scheduler" % akkaMockSchedulerVersion % Test,
|
||||
"org.mockito" %% "mockito-scala" % mockitoScalaVersion % Test
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
)
|
||||
@ -478,17 +478,17 @@ lazy val `project-manager` = (project in file("lib/project-manager"))
|
||||
case _ => MergeStrategy.first
|
||||
},
|
||||
assemblyOption in assembly := (assemblyOption in assembly).value
|
||||
.copy(
|
||||
prependShellScript = Some(
|
||||
defaultUniversalScript(
|
||||
shebang = false,
|
||||
javaOpts = Seq("-Dtruffle.class.path.append=runtime.jar")
|
||||
.copy(
|
||||
prependShellScript = Some(
|
||||
defaultUniversalScript(
|
||||
shebang = false,
|
||||
javaOpts = Seq("-Dtruffle.class.path.append=runtime.jar")
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
assembly := assembly
|
||||
.dependsOn(runtime / assembly)
|
||||
.value
|
||||
.dependsOn(runtime / assembly)
|
||||
.value
|
||||
)
|
||||
.dependsOn(pkg)
|
||||
.dependsOn(`language-server`)
|
||||
@ -523,10 +523,10 @@ lazy val `json-rpc-server` = project
|
||||
libraryDependencies ++= akka,
|
||||
libraryDependencies ++= circe,
|
||||
libraryDependencies ++= Seq(
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
akkaTestkit % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test
|
||||
)
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
akkaTestkit % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test
|
||||
)
|
||||
)
|
||||
|
||||
lazy val `json-rpc-server-test` = project
|
||||
@ -535,10 +535,10 @@ lazy val `json-rpc-server-test` = project
|
||||
libraryDependencies ++= akka,
|
||||
libraryDependencies ++= circe,
|
||||
libraryDependencies ++= Seq(
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
akkaTestkit,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion
|
||||
)
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
akkaTestkit,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion
|
||||
)
|
||||
)
|
||||
.dependsOn(`json-rpc-server`)
|
||||
|
||||
@ -552,13 +552,13 @@ lazy val `core-definition` = (project in file("lib/core-definition"))
|
||||
logBuffered in Test := false,
|
||||
scalacOptions += "-Ymacro-annotations",
|
||||
libraryDependencies ++= jmh ++ Seq(
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.scalactic" %% "scalactic" % scalacticVersion % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"com.github.julien-truffaut" %% "monocle-core" % monocleVersion
|
||||
),
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.scalactic" %% "scalactic" % scalacticVersion % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"com.github.julien-truffaut" %% "monocle-core" % monocleVersion
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
),
|
||||
@ -608,11 +608,11 @@ lazy val `polyglot-api` = project
|
||||
Seq(s"-Dtruffle.class.path.append=$runtimeClasspath")
|
||||
},
|
||||
libraryDependencies ++= Seq(
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||
),
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test
|
||||
),
|
||||
libraryDependencies ++= jackson,
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
@ -630,23 +630,23 @@ lazy val `polyglot-api` = project
|
||||
lazy val `language-server` = (project in file("engine/language-server"))
|
||||
.settings(
|
||||
libraryDependencies ++= akka ++ circe ++ Seq(
|
||||
"ch.qos.logback" % "logback-classic" % logbackClassicVersion,
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
|
||||
"io.circe" %% "circe-generic-extras" % circeVersion,
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
"org.bouncycastle" % "bcpkix-jdk15on" % bcpkixJdk15Version,
|
||||
"dev.zio" %% "zio" % zioVersion,
|
||||
"io.methvin" % "directory-watcher" % directoryWatcherVersion,
|
||||
"com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion,
|
||||
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
|
||||
akkaTestkit % Test,
|
||||
"commons-io" % "commons-io" % commonsIoVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided"
|
||||
),
|
||||
"ch.qos.logback" % "logback-classic" % logbackClassicVersion,
|
||||
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
|
||||
"io.circe" %% "circe-generic-extras" % circeVersion,
|
||||
"io.circe" %% "circe-literal" % circeVersion,
|
||||
"org.bouncycastle" % "bcpkix-jdk15on" % bcpkixJdk15Version,
|
||||
"dev.zio" %% "zio" % zioVersion,
|
||||
"io.methvin" % "directory-watcher" % directoryWatcherVersion,
|
||||
"com.beachape" %% "enumeratum-circe" % enumeratumCirceVersion,
|
||||
"com.google.flatbuffers" % "flatbuffers-java" % flatbuffersVersion,
|
||||
akkaTestkit % Test,
|
||||
"commons-io" % "commons-io" % commonsIoVersion,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided"
|
||||
),
|
||||
testOptions in Test += Tests
|
||||
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
|
||||
.Argument(TestFrameworks.ScalaCheck, "-minSuccessfulTests", "1000"),
|
||||
GenerateFlatbuffers.flatcVersion := flatbuffersVersion,
|
||||
sourceGenerators in Compile += GenerateFlatbuffers.task
|
||||
)
|
||||
@ -656,8 +656,8 @@ lazy val `language-server` = (project in file("engine/language-server"))
|
||||
bench := (test in Benchmark).value,
|
||||
libraryDependencies += "com.storm-enroute" %% "scalameter" % scalameterVersion % "bench",
|
||||
testFrameworks ++= List(
|
||||
new TestFramework("org.scalameter.ScalaMeterFramework")
|
||||
)
|
||||
new TestFramework("org.scalameter.ScalaMeterFramework")
|
||||
)
|
||||
)
|
||||
.dependsOn(`polyglot-api`)
|
||||
.dependsOn(`json-rpc-server`)
|
||||
@ -676,40 +676,40 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
scalacOptions += "-Ymacro-annotations",
|
||||
scalacOptions ++= Seq("-Ypatmat-exhaust-depth", "off"),
|
||||
libraryDependencies ++= circe ++ jmh ++ Seq(
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"org.apache.commons" % "commons-lang3" % commonsLangVersion,
|
||||
"org.apache.tika" % "tika-core" % tikaVersion,
|
||||
"org.graalvm.sdk" % "graal-sdk" % graalVersion % "provided",
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-dsl-processor" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalVersion % "provided",
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.scalactic" %% "scalactic" % scalacticVersion % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % Benchmark,
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"eu.timepit" %% "refined" % refinedVersion
|
||||
),
|
||||
"com.chuusai" %% "shapeless" % shapelessVersion,
|
||||
"org.apache.commons" % "commons-lang3" % commonsLangVersion,
|
||||
"org.apache.tika" % "tika-core" % tikaVersion,
|
||||
"org.graalvm.sdk" % "graal-sdk" % graalVersion % "provided",
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-dsl-processor" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-tck-common" % graalVersion % "provided",
|
||||
"org.scalacheck" %% "scalacheck" % scalacheckVersion % Test,
|
||||
"org.scalactic" %% "scalactic" % scalacticVersion % Test,
|
||||
"org.scalatest" %% "scalatest" % scalatestVersion % Test,
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % Benchmark,
|
||||
"org.typelevel" %% "cats-core" % catsVersion,
|
||||
"eu.timepit" %% "refined" % refinedVersion
|
||||
),
|
||||
// Note [Unmanaged Classpath]
|
||||
Compile / unmanagedClasspath += (`core-definition` / Compile / packageBin).value,
|
||||
Test / unmanagedClasspath += (`core-definition` / Compile / packageBin).value,
|
||||
Compile / compile := FixInstrumentsGeneration.patchedCompile
|
||||
.dependsOn(`core-definition` / Compile / packageBin)
|
||||
.dependsOn(FixInstrumentsGeneration.preCompileTask)
|
||||
.value,
|
||||
.dependsOn(`core-definition` / Compile / packageBin)
|
||||
.dependsOn(FixInstrumentsGeneration.preCompileTask)
|
||||
.value,
|
||||
// Note [Classpath Separation]
|
||||
Test / javaOptions ++= Seq(
|
||||
"-XX:-UseJVMCIClassLoader",
|
||||
"-Dgraalvm.locatorDisabled=true"
|
||||
)
|
||||
"-XX:-UseJVMCIClassLoader",
|
||||
"-Dgraalvm.locatorDisabled=true"
|
||||
)
|
||||
)
|
||||
.settings(
|
||||
(Compile / javacOptions) ++= Seq(
|
||||
"-s",
|
||||
(Compile / sourceManaged).value.getAbsolutePath
|
||||
),
|
||||
"-s",
|
||||
(Compile / sourceManaged).value.getAbsolutePath
|
||||
),
|
||||
addCompilerPlugin(
|
||||
"org.typelevel" %% "kind-projector" % kindProjectorVersion cross CrossVersion.full
|
||||
),
|
||||
@ -720,22 +720,22 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
)
|
||||
.settings(
|
||||
(Compile / compile) := (Compile / compile)
|
||||
.dependsOn(Def.task { (Compile / sourceManaged).value.mkdirs })
|
||||
.value
|
||||
.dependsOn(Def.task { (Compile / sourceManaged).value.mkdirs })
|
||||
.value
|
||||
)
|
||||
.settings(
|
||||
logBuffered := false,
|
||||
bench := (test in Benchmark).tag(Exclusive).value,
|
||||
benchOnly := Def.inputTaskDyn {
|
||||
import complete.Parsers.spaceDelimited
|
||||
val name = spaceDelimited("<name>").parsed match {
|
||||
case List(name) => name
|
||||
case _ => throw new IllegalArgumentException("Expected one argument.")
|
||||
}
|
||||
Def.task {
|
||||
(testOnly in Benchmark).toTask(" -- -z " + name).value
|
||||
}
|
||||
}.evaluated,
|
||||
import complete.Parsers.spaceDelimited
|
||||
val name = spaceDelimited("<name>").parsed match {
|
||||
case List(name) => name
|
||||
case _ => throw new IllegalArgumentException("Expected one argument.")
|
||||
}
|
||||
Def.task {
|
||||
(testOnly in Benchmark).toTask(" -- -z " + name).value
|
||||
}
|
||||
}.evaluated,
|
||||
parallelExecution in Benchmark := false
|
||||
)
|
||||
.settings(
|
||||
@ -753,6 +753,7 @@ lazy val runtime = (project in file("engine/runtime"))
|
||||
}
|
||||
)
|
||||
.dependsOn(pkg)
|
||||
.dependsOn(`interpreter-dsl`)
|
||||
.dependsOn(syntax.jvm)
|
||||
.dependsOn(graph)
|
||||
.dependsOn(`polyglot-api`)
|
||||
@ -804,52 +805,58 @@ lazy val runner = project
|
||||
MergeStrategy.first
|
||||
},
|
||||
assemblyOption in assembly := (assemblyOption in assembly).value
|
||||
.copy(
|
||||
prependShellScript = Some(
|
||||
defaultUniversalScript(
|
||||
shebang = false,
|
||||
javaOpts = truffleRunOptions ++
|
||||
Seq("-Dtruffle.class.path.append=runtime.jar")
|
||||
.copy(
|
||||
prependShellScript = Some(
|
||||
defaultUniversalScript(
|
||||
shebang = false,
|
||||
javaOpts = truffleRunOptions ++
|
||||
Seq("-Dtruffle.class.path.append=runtime.jar")
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
commands += WithDebugCommand.withDebug,
|
||||
inConfig(Compile)(truffleRunOptionsSettings),
|
||||
libraryDependencies ++= Seq(
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||
"commons-cli" % "commons-cli" % commonsCliVersion,
|
||||
"com.monovore" %% "decline" % declineVersion,
|
||||
"io.github.spencerpark" % "jupyter-jvm-basekernel" % jupyterJvmBasekernelVersion,
|
||||
"org.jline" % "jline" % jlineVersion,
|
||||
"org.typelevel" %% "cats-core" % catsVersion
|
||||
),
|
||||
"org.graalvm.sdk" % "polyglot-tck" % graalVersion % "provided",
|
||||
"org.graalvm.truffle" % "truffle-api" % graalVersion % "provided",
|
||||
"commons-cli" % "commons-cli" % commonsCliVersion,
|
||||
"com.monovore" %% "decline" % declineVersion,
|
||||
"io.github.spencerpark" % "jupyter-jvm-basekernel" % jupyterJvmBasekernelVersion,
|
||||
"org.jline" % "jline" % jlineVersion,
|
||||
"org.typelevel" %% "cats-core" % catsVersion
|
||||
),
|
||||
connectInput in run := true
|
||||
)
|
||||
.settings(
|
||||
buildNativeImage := Def
|
||||
.task {
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val nativeImagePath = s"$javaHome/bin/native-image"
|
||||
val classPath = (Runtime / fullClasspath).value.files.mkString(":")
|
||||
val resourcesGlobOpt = "-H:IncludeResources=.*Main.enso$"
|
||||
val cmd =
|
||||
s"$nativeImagePath $resourcesGlobOpt --macro:truffle --no-fallback --initialize-at-build-time -cp $classPath ${(Compile / mainClass).value.get} enso"
|
||||
cmd !
|
||||
}
|
||||
.dependsOn(Compile / compile)
|
||||
.value
|
||||
.task {
|
||||
val javaHome = System.getProperty("java.home")
|
||||
val nativeImagePath = s"$javaHome/bin/native-image"
|
||||
val classPath = (Runtime / fullClasspath).value.files.mkString(":")
|
||||
val resourcesGlobOpt = "-H:IncludeResources=.*Main.enso$"
|
||||
val cmd =
|
||||
s"$nativeImagePath $resourcesGlobOpt --macro:truffle --no-fallback --initialize-at-build-time -cp $classPath ${(Compile / mainClass).value.get} enso"
|
||||
cmd !
|
||||
}
|
||||
.dependsOn(Compile / compile)
|
||||
.value
|
||||
)
|
||||
.settings(
|
||||
Compile / sourceGenerators += Def.task {
|
||||
val file = (Compile / sourceManaged).value / "buildinfo" / "Info.scala"
|
||||
BuildInfo
|
||||
.writeBuildInfoFile(file, ensoVersion, scalacVersion, graalVersion)
|
||||
}.taskValue,
|
||||
val file = (Compile / sourceManaged).value / "buildinfo" / "Info.scala"
|
||||
BuildInfo
|
||||
.writeBuildInfoFile(file, ensoVersion, scalacVersion, graalVersion)
|
||||
}.taskValue,
|
||||
assembly := assembly
|
||||
.dependsOn(runtime / assembly)
|
||||
.value
|
||||
.dependsOn(runtime / assembly)
|
||||
.value
|
||||
)
|
||||
.dependsOn(pkg)
|
||||
.dependsOn(`language-server`)
|
||||
.dependsOn(`polyglot-api`)
|
||||
|
||||
lazy val `interpreter-dsl` = (project in file("lib/interpreter-dsl"))
|
||||
.settings(
|
||||
version := "0.1",
|
||||
libraryDependencies += "com.google.auto.service" % "auto-service" % "1.0-rc7"
|
||||
)
|
||||
|
97
docs/runtime/builtin-base-methods.md
Normal file
97
docs/runtime/builtin-base-methods.md
Normal file
@ -0,0 +1,97 @@
|
||||
---
|
||||
layout: developer-doc
|
||||
title: Builtin Base Methods
|
||||
category: runtime
|
||||
tags: [runtime, base, standard, library]
|
||||
order: 7
|
||||
---
|
||||
|
||||
# Builtin Base Methods
|
||||
While we strive to implement most of the Enso standard library in Enso itself,
|
||||
it is necessary for certain methods, particularly ones involving operations out
|
||||
of reach for the standard language semantics, or primitive system calls, to be
|
||||
implemented in Java.
|
||||
|
||||
To facilitate this process, we have created an annotation-based DSL for easier
|
||||
generation of such methods' boilerplate.
|
||||
|
||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||
|
||||
- [DSL Overview](#dsl-overview)
|
||||
- [`@BuiltinMethod` Annotation](#builtinmethod-annotation)
|
||||
- [Structural Requirements](#structural-requirements)
|
||||
- [`Execute` Method Semantics](#execute-method-semantics)
|
||||
- [Generated Node](#generated-node)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## DSL Overview
|
||||
The Enso Base DSL exposes certain annotations that allow to generate
|
||||
boilerplate transforming standard Truffle nodes into a shape that can easily
|
||||
be exported to the Base library. This DSL facilitates automatic parsing
|
||||
and typechecking of method arguments and wrapping the node in an actual
|
||||
`Function` object.
|
||||
|
||||
## `@BuiltinMethod` Annotation
|
||||
The `@BuiltinMethod` annotation is applied to a Truffle `Node` subclass that
|
||||
should be treated as a builtin method. It takes the following arguments:
|
||||
|
||||
1. `type` **String** the name of the type the method will be registered on.
|
||||
2. `name` **String** the method name.
|
||||
3. `description` **String** a summary of the method's behavior, for
|
||||
documentation purposes.
|
||||
4. `alwaysDirect` **Boolean = `true`** describes whether the function can always
|
||||
be safely called directly. It should be set to `false` for methods that
|
||||
evaluate user code in a tail position (e.g. `if_then_else`). If the method
|
||||
does not take functions or thunks as parameters, or it only evaluates these
|
||||
in a non-tail position, this parameter should be left defaulted.
|
||||
|
||||
The annotation will generate a `RootNode` subclass in the same package as the
|
||||
declaring node, with a name basing on the declaring node's name. The name of
|
||||
the generated node is the name of the original node, with the `Node` suffix
|
||||
stripped and the `MethodGen` suffix appended. E.g. `AndOperatorNode` will
|
||||
generate a `AndOperatorMethodGen` root node.
|
||||
|
||||
## Structural Requirements
|
||||
The DSL places certain structural requirements on the declaring node.
|
||||
|
||||
1. **Construction:** The node must be constructible using either
|
||||
a paremeterless, static `build` method or a parameterless constructor.
|
||||
If a suitable `build` method is defined, it will be preferred over the
|
||||
constructor.
|
||||
2. **Execution:** The node must declare a single, accessible (i.e. at least
|
||||
package-private), non-void method named `execute`.
|
||||
|
||||
## `Execute` Method Semantics
|
||||
The `execute` method defined by the declaring node has the following semantics.
|
||||
|
||||
1. Return type. If the return type is `Stateful`, the method is assumed to
|
||||
modify the monadic state. For any other return type, the method cannot
|
||||
modify the monadic state.
|
||||
2. Arguments. The method may take any number of arguments, though at least
|
||||
an argument named `self` must be present. The arguments have following
|
||||
semantics:
|
||||
1. An `Object` argument may be annotated with `@MonadicState`. This tells
|
||||
the DSL to substitute it for the current value of monadic state. Note
|
||||
that this value is read-only. In order to modify state, the method
|
||||
must return a `Stateful`.
|
||||
2. Any `VirtualFrame` argument will be passed the current execution frame.
|
||||
3. Any `CallerInfo` argument will be passed the current `CallerInfo` and
|
||||
mark the method as requiring the caller info at runtime.
|
||||
4. All other arguments are treated as positional arguments to the method.
|
||||
Note that according to the language specification, any method must take
|
||||
an argument named `this`. Because of a naming conflict with Java, this
|
||||
argument is called `_this` in the DSL. Please note that it is mandatory
|
||||
to take an argument called `_this`, even if it is unused.
|
||||
5. The positional arguments can be of any typed specified by the runtime
|
||||
type system (see `org.enso.interpreter.runtime.Types`) or `Object`.
|
||||
Arguments typed as `Thunk` mark the argument as suspended in the
|
||||
generated function header.
|
||||
|
||||
## Generated Node
|
||||
The DSL generates a single root node per annotated class. This node handles
|
||||
reading the arguments from the execution frame and typechecking them, before
|
||||
delegating to the declaring node.
|
||||
|
||||
The generated node also defines a static `makeFunction(Language)` method,
|
||||
wrapping the node in a runtime function object.
|
@ -3,7 +3,7 @@ layout: developer-doc
|
||||
title: Searcher
|
||||
category: runtime
|
||||
tags: [runtime, search, execution]
|
||||
order: 7
|
||||
order: 8
|
||||
---
|
||||
|
||||
# Searcher
|
||||
|
@ -1,76 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** The root node for the basic control flow structure of the language. */
|
||||
@NodeInfo(shortName = "Number.ifZero", description = "Root node of the Number.ifZero method.")
|
||||
public class IfZeroNode extends BuiltinRootNode {
|
||||
private @Child ThunkExecutorNode leftThunkExecutorNode = ThunkExecutorNode.build();
|
||||
private @Child ThunkExecutorNode rightThunkExecutorNode = ThunkExecutorNode.build();
|
||||
private final ConditionProfile condProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private IfZeroNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a number and two thunks and executes the first thunk if the number was 0 and second
|
||||
* otherwise.
|
||||
*
|
||||
* <p>Assumes the number is the first argument in the current execution frame, while the first and
|
||||
* second thunks are respectively the second and third arguments.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of executing the proper thunk
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
long self =
|
||||
TypesGen.asLong(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
Thunk ifT =
|
||||
TypesGen.asThunk(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||
Thunk ifF =
|
||||
TypesGen.asThunk(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
if (condProfile.profile(self == 0)) {
|
||||
return leftThunkExecutorNode.executeThunk(ifT, state, true);
|
||||
} else {
|
||||
return rightThunkExecutorNode.executeThunk(ifF, state, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a three-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new IfZeroNode(language),
|
||||
FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "ifTrue", ArgumentDefinition.ExecutionMode.PASS_THUNK),
|
||||
new ArgumentDefinition(2, "ifFalse", ArgumentDefinition.ExecutionMode.PASS_THUNK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.ifZero";
|
||||
}
|
||||
}
|
@ -1,72 +1,14 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.node.expression.builtin.number.ModNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Boolean.&&", description = "Computes the logical AND of two booleans")
|
||||
public class AndNode extends BuiltinRootNode {
|
||||
private final BranchProfile thatOpBadTypeProfile = BranchProfile.create();
|
||||
|
||||
private AndNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new AndNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of performing `op` on the operands
|
||||
*/
|
||||
@Override
|
||||
public final Stateful execute(VirtualFrame frame) {
|
||||
boolean thisArg =
|
||||
TypesGen.asBoolean(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object thatArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
|
||||
if (TypesGen.isBoolean(thatArg)) {
|
||||
boolean thatArgBool = TypesGen.asBoolean(thatArg);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, thisArg && thatArgBool);
|
||||
} else {
|
||||
thatOpBadTypeProfile.enter();
|
||||
throw new TypeError("Unexpected type for `that` operand in " + getName(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Boolean.||";
|
||||
@BuiltinMethod(
|
||||
type = "Boolean",
|
||||
name = "&&",
|
||||
description = "Computes the logical conjunction of two booleans")
|
||||
public class AndNode extends Node {
|
||||
boolean execute(boolean _this, boolean that) {
|
||||
return _this && that;
|
||||
}
|
||||
}
|
||||
|
@ -1,80 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** The root node for the basic control flow structure of the language. */
|
||||
@NodeInfo(
|
||||
shortName = "Boolean.if_then_else",
|
||||
@BuiltinMethod(
|
||||
type = "Boolean",
|
||||
name = "if_then_else",
|
||||
alwaysDirect = false,
|
||||
description = "Performs the standard if-then-else control flow operation.")
|
||||
public class IfThenElseNode extends BuiltinRootNode {
|
||||
public class IfThenElseNode extends Node {
|
||||
private @Child ThunkExecutorNode leftThunkExecutorNode = ThunkExecutorNode.build();
|
||||
private @Child ThunkExecutorNode rightThunkExecutorNode = ThunkExecutorNode.build();
|
||||
private final ConditionProfile condProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private IfThenElseNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a number and two thunks and executes the first thunk if the number was 0 and second
|
||||
* otherwise.
|
||||
*
|
||||
* <p>Assumes the number is the first argument in the current execution frame, while the first and
|
||||
* second thunks are respectively the second and third arguments.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of executing the proper thunk
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
boolean self =
|
||||
TypesGen.asBoolean(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
Thunk ifT =
|
||||
TypesGen.asThunk(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||
Thunk ifF =
|
||||
TypesGen.asThunk(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
if (condProfile.profile(self)) {
|
||||
return leftThunkExecutorNode.executeThunk(ifT, state, true);
|
||||
Stateful execute(@MonadicState Object state, boolean _this, Thunk if_true, Thunk if_false) {
|
||||
if (condProfile.profile(_this)) {
|
||||
return leftThunkExecutorNode.executeThunk(if_true, state, true);
|
||||
} else {
|
||||
return rightThunkExecutorNode.executeThunk(ifF, state, true);
|
||||
return rightThunkExecutorNode.executeThunk(if_false, state, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a three-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new IfThenElseNode(language),
|
||||
FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "if_true", ArgumentDefinition.ExecutionMode.PASS_THUNK),
|
||||
new ArgumentDefinition(2, "if_false", ArgumentDefinition.ExecutionMode.PASS_THUNK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Boolean.if_then_else";
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +1,14 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Boolean.not", description = "Logical negation.")
|
||||
public class NotNode extends BuiltinRootNode {
|
||||
private NotNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a one-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new NotNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of negating the function argument
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
boolean thisArg =
|
||||
TypesGen.asBoolean(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, !thisArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Boolean.not";
|
||||
@BuiltinMethod(
|
||||
type = "Boolean",
|
||||
name = "not",
|
||||
description = "Computes the logical negation of a boolean value")
|
||||
public class NotNode extends Node {
|
||||
boolean execute(boolean _this) {
|
||||
return !_this;
|
||||
}
|
||||
}
|
||||
|
@ -1,71 +1,14 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Boolean.||", description = "Computes the logical OR of two booleans")
|
||||
public class OrNode extends BuiltinRootNode {
|
||||
private final BranchProfile thatOpBadTypeProfile = BranchProfile.create();
|
||||
|
||||
private OrNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new OrNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of performing `op` on the operands
|
||||
*/
|
||||
@Override
|
||||
public final Stateful execute(VirtualFrame frame) {
|
||||
boolean thisArg =
|
||||
TypesGen.asBoolean(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object thatArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
|
||||
if (TypesGen.isBoolean(thatArg)) {
|
||||
boolean thatArgBool = TypesGen.asBoolean(thatArg);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, thisArg || thatArgBool);
|
||||
} else {
|
||||
thatOpBadTypeProfile.enter();
|
||||
throw new TypeError("Unexpected type for `that` operand in " + getName(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Boolean.||";
|
||||
@BuiltinMethod(
|
||||
type = "Boolean",
|
||||
name = "||",
|
||||
description = "Computes the logical disjunction of two booleans")
|
||||
public class OrNode extends Node {
|
||||
boolean execute(boolean _this, boolean that) {
|
||||
return _this || that;
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.bool;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Boolean.to_text", description = "Boolean to text conversion.")
|
||||
public class ToTextNode extends BuiltinRootNode {
|
||||
private ToTextNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ToTextNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
boolean thisArg =
|
||||
TypesGen.asBoolean(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, thisArg ? "True" : "False");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Boolean.to_text";
|
||||
@BuiltinMethod(type = "Boolean", name = "to_text", description = "Boolean to text conversion.")
|
||||
public class ToTextNode extends Node {
|
||||
String execute(boolean _this) {
|
||||
return _this ? "True" : "False";
|
||||
}
|
||||
}
|
||||
|
@ -1,60 +1,77 @@
|
||||
package org.enso.interpreter.node.expression.builtin.debug;
|
||||
|
||||
import com.oracle.truffle.api.debug.DebuggerTags;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Constants;
|
||||
import com.oracle.truffle.api.instrumentation.GenerateWrapper;
|
||||
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
|
||||
import com.oracle.truffle.api.instrumentation.ProbeNode;
|
||||
import com.oracle.truffle.api.instrumentation.Tag;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.node.expression.debug.BreakpointNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Root of the builtin Debug.breakpoint function. */
|
||||
@NodeInfo(
|
||||
shortName = "Debug.breakpoint",
|
||||
description = "Root of the builtin Debug.breakpoint function.")
|
||||
public class DebugBreakpointNode extends BuiltinRootNode {
|
||||
private @Child BreakpointNode instrumentableNode = BreakpointNode.build();
|
||||
|
||||
private DebugBreakpointNode(Language language) {
|
||||
super(language);
|
||||
@BuiltinMethod(type = "Debug", name = "breakpoint", description = "Instrumentation marker node.")
|
||||
@GenerateWrapper
|
||||
public abstract class DebugBreakpointNode extends Node implements InstrumentableNode {
|
||||
/**
|
||||
* Creates a new instance of this node.
|
||||
*
|
||||
* @return a new instance of this node
|
||||
*/
|
||||
public static DebugBreakpointNode build() {
|
||||
return DebugBreakpointNodeGen.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node by delegating to its instrumentable child.
|
||||
* Tells Truffle this node is instrumentable.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of running the instrumentable node
|
||||
* @return {@code true} – this node is always instrumentable.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return instrumentableNode.execute(frame, state);
|
||||
public boolean isInstrumentable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract Stateful execute(
|
||||
VirtualFrame frame, CallerInfo callerInfo, @MonadicState Object state, Object _this);
|
||||
|
||||
@Specialization
|
||||
Stateful doExecute(
|
||||
VirtualFrame frame,
|
||||
CallerInfo callerInfo,
|
||||
Object state,
|
||||
Object _this,
|
||||
@CachedContext(Language.class) Context context) {
|
||||
return new Stateful(state, context.getUnit().newInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps this node in a 1-argument function.
|
||||
* Informs Truffle about the provided tags.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return the function wrapper for this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNodeWithCallerFrameAccess(
|
||||
new DebugBreakpointNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(
|
||||
0, Constants.Names.THIS_ARGUMENT, ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
* <p>This node only provides the {@link DebuggerTags.AlwaysHalt} tag.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
* @param tag the tag to verify
|
||||
* @return {@code true} if the tag is {@link DebuggerTags.AlwaysHalt}, {@code false} otherwise
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Debug.breakpoint";
|
||||
public boolean hasTag(Class<? extends Tag> tag) {
|
||||
return tag == DebuggerTags.AlwaysHalt.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instrumentable wrapper node for this node.
|
||||
*
|
||||
* @param probeNode the probe node to wrap
|
||||
* @return the wrapper instance wrapping both this and the probe node
|
||||
*/
|
||||
@Override
|
||||
public WrapperNode createWrapper(ProbeNode probeNode) {
|
||||
return new DebugBreakpointNodeWrapper(this, probeNode);
|
||||
}
|
||||
}
|
||||
|
@ -1,65 +1,27 @@
|
||||
package org.enso.interpreter.node.expression.builtin.debug;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.node.expression.debug.EvalNode;
|
||||
import org.enso.interpreter.runtime.callable.CallerInfo;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Root node for the builtin Debug.eval function. */
|
||||
@NodeInfo(shortName = "Debug.eval", description = "Root node for the builtin Debug.eval function")
|
||||
public class DebugEvalNode extends BuiltinRootNode {
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Debug",
|
||||
name = "eval",
|
||||
description = "Evaluates an expression passed as a Text argument, in the caller frame.",
|
||||
alwaysDirect = false)
|
||||
public class DebugEvalNode extends Node {
|
||||
private @Child EvalNode evalNode = EvalNode.build();
|
||||
|
||||
private DebugEvalNode(Language language) {
|
||||
super(language);
|
||||
DebugEvalNode() {
|
||||
evalNode.markTail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the function in the given execution frame.
|
||||
*
|
||||
* <p>Requires a non-null {@link CallerInfo} passed to it. The string argument containing code to
|
||||
* evaluate is this function's second (non-this) argument.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
CallerInfo callerInfo = Function.ArgumentsHelper.getCallerInfo(frame.getArguments());
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
String code = (String) Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
return evalNode.execute(callerInfo, state, code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a two argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node's logic
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNodeWithCallerFrameAccess(
|
||||
new DebugEvalNode(language),
|
||||
FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "expression", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Debug.eval";
|
||||
Stateful execute(
|
||||
CallerInfo callerInfo, @MonadicState Object state, Object _this, String expression) {
|
||||
return evalNode.execute(callerInfo, state, expression);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,26 @@
|
||||
package org.enso.interpreter.node.expression.builtin.error;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
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.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** Root node for the {@code catch} function. */
|
||||
@NodeInfo(shortName = "Error.catch", description = "Root node for the catch function.")
|
||||
public class CatchErrorNode extends BuiltinRootNode {
|
||||
@BuiltinMethod(
|
||||
type = "Any",
|
||||
name = "catch",
|
||||
description =
|
||||
"If called on an error, executes the provided handler on the error's payload. Otherwise acts as identity.",
|
||||
alwaysDirect = false)
|
||||
public class CatchErrorNode extends Node {
|
||||
private @Child InvokeCallableNode invokeCallableNode;
|
||||
private final ConditionProfile executionProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private CatchErrorNode(Language language) {
|
||||
super(language);
|
||||
CatchErrorNode() {
|
||||
this.invokeCallableNode =
|
||||
InvokeCallableNode.build(
|
||||
new CallArgumentInfo[] {new CallArgumentInfo()},
|
||||
@ -29,49 +29,12 @@ public class CatchErrorNode extends BuiltinRootNode {
|
||||
this.invokeCallableNode.markTail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the logic. Assumes the scrutinee is the first argument to the enclosing function and
|
||||
* the handler is the second. If the scrutinee is an error, the function is called with the error
|
||||
* payload. Otherwise, it's a no-op.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of calling the handler function
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object[] arguments = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object scrutinee = arguments[0];
|
||||
Object handler = arguments[1];
|
||||
if (executionProfile.profile(TypesGen.isRuntimeError(scrutinee))) {
|
||||
Stateful execute(VirtualFrame frame, @MonadicState Object state, Object _this, Object handler) {
|
||||
if (executionProfile.profile(TypesGen.isRuntimeError(_this))) {
|
||||
return invokeCallableNode.execute(
|
||||
handler, frame, state, new Object[] {TypesGen.asRuntimeError(scrutinee).getPayload()});
|
||||
handler, frame, state, new Object[] {TypesGen.asRuntimeError(_this).getPayload()});
|
||||
} else {
|
||||
return new Stateful(state, scrutinee);
|
||||
return new Stateful(state, _this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new CatchErrorNode(language),
|
||||
FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "handler", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Error.catch";
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +1,26 @@
|
||||
package org.enso.interpreter.node.expression.builtin.error;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
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;
|
||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** Root node for the builtin catch panic function. */
|
||||
@NodeInfo(
|
||||
shortName = "Panic.catch",
|
||||
description = "Root node for the builtin catch panic function.")
|
||||
public class CatchPanicNode extends BuiltinRootNode {
|
||||
@BuiltinMethod(
|
||||
type = "Panic",
|
||||
name = "catch",
|
||||
description = "Executes an action and converts any Panic thrown by it into an Error")
|
||||
public class CatchPanicNode extends Node {
|
||||
private @Child ThunkExecutorNode thunkExecutorNode = ThunkExecutorNode.build();
|
||||
|
||||
private CatchPanicNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* <p>Assumes the suspended, possibly-panicking computation is passed as the second argument and
|
||||
* executes it, catching any {@link PanicException}s.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of the computation if it didn't throw, or a {@link RuntimeError} containing
|
||||
* the thrown panic's payload.
|
||||
*/
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object maybeThunk = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
if (TypesGen.isThunk(maybeThunk)) {
|
||||
try {
|
||||
return thunkExecutorNode.executeThunk(TypesGen.asThunk(maybeThunk), state, false);
|
||||
} catch (PanicException e) {
|
||||
return new Stateful(state, new RuntimeError(e.getExceptionObject()));
|
||||
}
|
||||
} else {
|
||||
return new Stateful(state, maybeThunk);
|
||||
Stateful execute(@MonadicState Object state, Object _this, Thunk action) {
|
||||
try {
|
||||
return thunkExecutorNode.executeThunk(action, state, false);
|
||||
} catch (PanicException e) {
|
||||
return new Stateful(state, new RuntimeError(e.getExceptionObject()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new CatchPanicNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "value", ArgumentDefinition.ExecutionMode.PASS_THUNK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Panic.catch";
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.error;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Root node for the builtin panic function. */
|
||||
@NodeInfo(shortName = "Panic.throw", description = "Root node for the builtin panic function.")
|
||||
public class PanicNode extends BuiltinRootNode {
|
||||
private PanicNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* <p>Assumes the panic payload is passed as the second argument of the enclosing function and
|
||||
* throws it as an exception.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return never returns, always throws an exception
|
||||
*/
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object payload = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
throw new PanicException(payload, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new PanicNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "value", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language specific name of this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Panic.throw";
|
||||
}
|
||||
}
|
@ -1,62 +1,15 @@
|
||||
package org.enso.interpreter.node.expression.builtin.error;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Root node for the builtin throw error function. */
|
||||
@NodeInfo(
|
||||
shortName = "Error.throw",
|
||||
description = "Root node for the builtin throw error function.")
|
||||
public class ThrowErrorNode extends BuiltinRootNode {
|
||||
|
||||
private ThrowErrorNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* <p>Assumes the error payload is provided as the second argument of the enclosing function and
|
||||
* wraps it in a {@link RuntimeError}.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return a runtime error wrapped argument
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object errorPayload = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, new RuntimeError(errorPayload));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ThrowErrorNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "payload", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Error.throw";
|
||||
@BuiltinMethod(
|
||||
type = "Error",
|
||||
name = "throw",
|
||||
description = "Returns a new value error with given payload.")
|
||||
public class ThrowErrorNode extends Node {
|
||||
public Object execute(Object _this, Object payload) {
|
||||
return new RuntimeError(payload);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.error;
|
||||
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Panic",
|
||||
name = "throw",
|
||||
description = "Throws a new Panic with given payload.")
|
||||
public class ThrowPanicNode extends Node {
|
||||
Stateful execute(Object _this, Object payload) {
|
||||
throw new PanicException(payload, this);
|
||||
}
|
||||
}
|
@ -1,76 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.function;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
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.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/**
|
||||
* This node implements the built-in functionality for the explicit {@code call} operator on
|
||||
* functions.
|
||||
*
|
||||
* <p>It is a standard builtin node, and hence conforms to the interface for these.
|
||||
*/
|
||||
@NodeInfo(shortName = "Function.call", description = "Allows function calls to be made explicitly")
|
||||
public class ExplicitCallFunctionNode extends BuiltinRootNode {
|
||||
@BuiltinMethod(
|
||||
type = "Function",
|
||||
name = "call",
|
||||
description = "Allows function calls to be made explicitly",
|
||||
alwaysDirect = false)
|
||||
public class ExplicitCallFunctionNode extends Node {
|
||||
private @Child InvokeCallableNode invokeCallableNode;
|
||||
private final ConditionProfile isFunctionProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
private ExplicitCallFunctionNode(Language language) {
|
||||
super(language);
|
||||
this.invokeCallableNode =
|
||||
ExplicitCallFunctionNode() {
|
||||
invokeCallableNode =
|
||||
InvokeCallableNode.build(
|
||||
new CallArgumentInfo[0],
|
||||
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
||||
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED);
|
||||
this.invokeCallableNode.markTail();
|
||||
invokeCallableNode.markTail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces execution of a function.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the value of executing the function.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object[] arguments = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object thisArg = arguments[0];
|
||||
|
||||
if (isFunctionProfile.profile(TypesGen.isFunction(thisArg))) {
|
||||
return invokeCallableNode.execute(thisArg, frame, state, new Object[0]);
|
||||
} else {
|
||||
throw new RuntimeException("Object not callable: " + thisArg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Function} object that forces the execution of the object it is applied to.
|
||||
*
|
||||
* <p>This behaves in a curried manner, so for some function {@code f} you can call it with
|
||||
* arguments where necessary (e.g. {@code f.call a b}.
|
||||
*
|
||||
* @param language the current {@link Language} instance
|
||||
* @return a {@link Function} object wrapping the behavior of this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ExplicitCallFunctionNode(language),
|
||||
FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Function.call";
|
||||
Stateful execute(VirtualFrame frame, @MonadicState Object state, Function _this) {
|
||||
return invokeCallableNode.execute(_this, frame, state, new Object[0]);
|
||||
}
|
||||
}
|
||||
|
@ -5,77 +5,37 @@ import com.oracle.truffle.api.interop.ArityException;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
||||
import com.oracle.truffle.api.nodes.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.data.Vector;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Polyglot.execute",
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "execute",
|
||||
description = "Executes a polyglot function object (e.g. a lambda).")
|
||||
public class ExecuteNode extends BuiltinRootNode {
|
||||
private ExecuteNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class ExecuteNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ExecuteNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "callable", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(2, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object callable = args[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object callable, Vector arguments) {
|
||||
try {
|
||||
Object[] arguments = TypesGen.expectVector(args[2]).getItems();
|
||||
Object res = library.execute(callable, arguments);
|
||||
return new Stateful(state, res);
|
||||
} catch (UnsupportedMessageException
|
||||
| ArityException
|
||||
| UnsupportedTypeException
|
||||
| UnexpectedResultException e) {
|
||||
return library.execute(callable, arguments.getItems());
|
||||
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.execute";
|
||||
}
|
||||
}
|
||||
|
@ -1,82 +1,29 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Polyglot.get_array_element",
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_array_element",
|
||||
description = "Gets an element by index from a polyglot array.")
|
||||
public class GetArrayElementNode extends BuiltinRootNode {
|
||||
private GetArrayElementNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class GetArrayElementNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new GetArrayElementNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "array", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(2, "index", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object array = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object array, long index) {
|
||||
try {
|
||||
long index =
|
||||
TypesGen.expectLong(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2]);
|
||||
|
||||
Object res = library.readArrayElement(array, index);
|
||||
return new Stateful(state, res);
|
||||
} catch (UnsupportedMessageException
|
||||
| InvalidArrayIndexException
|
||||
| UnexpectedResultException e) {
|
||||
return library.readArrayElement(array, index);
|
||||
} catch (UnsupportedMessageException | InvalidArrayIndexException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.get_array_element";
|
||||
}
|
||||
}
|
||||
|
@ -1,70 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@NodeInfo(shortName = "Polyglot.get_array_size", description = "Gets the size of a polyglot array.")
|
||||
public class GetArraySizeNode extends BuiltinRootNode {
|
||||
private GetArraySizeNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_array_size",
|
||||
description = "Gets the size of a polyglot array.")
|
||||
public class GetArraySizeNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new GetArraySizeNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "array", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object obj = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object array) {
|
||||
try {
|
||||
long size = library.getArraySize(obj);
|
||||
return new Stateful(state, size);
|
||||
return library.getArraySize(array);
|
||||
} catch (UnsupportedMessageException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.get_array_size";
|
||||
}
|
||||
}
|
||||
|
@ -1,80 +1,29 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnknownIdentifierException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Polyglot.get_member",
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_member",
|
||||
description = "Gets a member by name from a polyglot object.")
|
||||
public class GetMemberNode extends BuiltinRootNode {
|
||||
private GetMemberNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class GetMemberNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new GetMemberNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "object", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(2, "name", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object obj = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object object, String member_name) {
|
||||
try {
|
||||
String name =
|
||||
TypesGen.expectString(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2]);
|
||||
Object res = library.readMember(obj, name);
|
||||
return new Stateful(state, res);
|
||||
} catch (UnsupportedMessageException
|
||||
| UnknownIdentifierException
|
||||
| UnexpectedResultException e) {
|
||||
return library.readMember(object, member_name);
|
||||
} catch (UnsupportedMessageException | UnknownIdentifierException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.get_member";
|
||||
}
|
||||
}
|
||||
|
@ -1,72 +1,28 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Polyglot.get_members",
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_members",
|
||||
description = "Returns a polyglot array of the object's member names.")
|
||||
public class GetMembersNode extends BuiltinRootNode {
|
||||
private GetMembersNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class GetMembersNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new GetMembersNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "object", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object arg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object object) {
|
||||
try {
|
||||
Object members = library.getMembers(arg);
|
||||
return new Stateful(state, members);
|
||||
return library.getMembers(object);
|
||||
} catch (UnsupportedMessageException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.get_members";
|
||||
}
|
||||
}
|
||||
|
@ -1,79 +1,32 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.ArityException;
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.interop.UnsupportedTypeException;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.data.Vector;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(shortName = "Polyglot.new", description = "Instantiates a polyglot constructor.")
|
||||
public class InstantiateNode extends BuiltinRootNode {
|
||||
private InstantiateNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "new",
|
||||
description = "Instantiates a polyglot constructor.")
|
||||
public class InstantiateNode extends Node {
|
||||
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new InstantiateNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "constructor", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(2, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object cons = args[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object constructor, Vector arguments) {
|
||||
try {
|
||||
Object[] arguments = TypesGen.expectVector(args[2]).getItems();
|
||||
Object res = library.instantiate(cons, arguments);
|
||||
return new Stateful(state, res);
|
||||
} catch (UnsupportedMessageException
|
||||
| ArityException
|
||||
| UnsupportedTypeException
|
||||
| UnexpectedResultException e) {
|
||||
return library.instantiate(constructor, arguments.getItems());
|
||||
} catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.new";
|
||||
}
|
||||
}
|
||||
|
@ -1,81 +1,31 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.interop.*;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.data.Vector;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Polyglot.invoke",
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "invoke",
|
||||
description = "Invokes a polyglot method by name, dispatching by the target argument.")
|
||||
public class InvokeNode extends BuiltinRootNode {
|
||||
private InvokeNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class InvokeNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new InvokeNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "target", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(2, "method_name", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(3, "arguments", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object[] args = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());
|
||||
Object callable = args[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object execute(Object _this, Object target, String name, Vector arguments) {
|
||||
try {
|
||||
String method = TypesGen.expectString(args[2]);
|
||||
Object[] arguments = TypesGen.expectVector(args[3]).getItems();
|
||||
Object res = library.invokeMember(callable, method, arguments);
|
||||
return new Stateful(state, res);
|
||||
return library.invokeMember(target, name, arguments.getItems());
|
||||
} catch (UnsupportedMessageException
|
||||
| ArityException
|
||||
| UnsupportedTypeException
|
||||
| UnexpectedResultException
|
||||
| UnknownIdentifierException e) {
|
||||
err.enter();
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Polyglot.invoke";
|
||||
}
|
||||
}
|
||||
|
@ -2,62 +2,28 @@ package org.enso.interpreter.node.expression.builtin.interop.java;
|
||||
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
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;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@NodeInfo(shortName = "Java.add_to_class_path", description = "Adds a path to the host class path.")
|
||||
public abstract class AddToClassPathNode extends BuiltinRootNode {
|
||||
AddToClassPathNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
@BuiltinMethod(
|
||||
type = "Java",
|
||||
name = "add_to_class_path",
|
||||
description = "Adds a path to the host class path.")
|
||||
public abstract class AddToClassPathNode extends Node {
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
AddToClassPathNodeGen.create(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "path", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
static AddToClassPathNode build() {
|
||||
return AddToClassPathNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Stateful doExecute(VirtualFrame frame, @CachedContext(Language.class) Context context) {
|
||||
try {
|
||||
String arg =
|
||||
TypesGen.expectString(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
context.getEnvironment().addToHostClassPath(context.getTruffleFile(new File(arg)));
|
||||
return new Stateful(state, context.getBuiltins().unit());
|
||||
} catch (UnexpectedResultException e) {
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
Object doExecute(Object _this, String path, @CachedContext(Language.class) Context context) {
|
||||
context.getEnvironment().addToHostClassPath(context.getTruffleFile(new File(path)));
|
||||
return context.getBuiltins().unit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Java.add_to_class_path";
|
||||
}
|
||||
abstract Object execute(Object _this, String path);
|
||||
}
|
||||
|
@ -2,60 +2,21 @@ package org.enso.interpreter.node.expression.builtin.interop.java;
|
||||
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
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;
|
||||
|
||||
@NodeInfo(shortName = "Java.lookup_class", description = "Looks up a Java symbol.")
|
||||
public abstract class LookupClassNode extends BuiltinRootNode {
|
||||
LookupClassNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
LookupClassNodeGen.create(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "name", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
@BuiltinMethod(type = "Java", name = "lookup_class", description = "Looks up a Java symbol.")
|
||||
public abstract class LookupClassNode extends Node {
|
||||
static LookupClassNode build() {
|
||||
return LookupClassNodeGen.create();
|
||||
}
|
||||
|
||||
@Specialization
|
||||
Stateful doExecute(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
||||
try {
|
||||
String arg =
|
||||
TypesGen.expectString(
|
||||
Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Object res = ctx.getEnvironment().lookupHostSymbol(arg);
|
||||
return new Stateful(state, res);
|
||||
} catch (UnexpectedResultException e) {
|
||||
throw new PanicException(e.getMessage(), this);
|
||||
}
|
||||
Object doExecute(Object _this, String name, @CachedContext(Language.class) Context ctx) {
|
||||
return ctx.getEnvironment().lookupHostSymbol(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Java.lookup_class";
|
||||
}
|
||||
abstract Object execute(Object _this, String name);
|
||||
}
|
||||
|
@ -3,59 +3,27 @@ package org.enso.interpreter.node.expression.builtin.io;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import java.io.PrintStream;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition.ExecutionMode;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@NodeInfo(shortName = "IO.print_err", description = "Prints its argument to standard error.")
|
||||
public abstract class PrintErrNode extends BuiltinRootNode {
|
||||
PrintErrNode(Language language) {
|
||||
super(language);
|
||||
@BuiltinMethod(
|
||||
type = "IO",
|
||||
name = "print_err",
|
||||
description = "Prints its argument to standard error.")
|
||||
public abstract class PrintErrNode extends Node {
|
||||
static PrintErrNode build() {
|
||||
return PrintErrNodeGen.create();
|
||||
}
|
||||
|
||||
abstract Object execute(Object _this, Object message);
|
||||
|
||||
@Specialization
|
||||
Stateful doPrint(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
||||
print(ctx.getErr(), Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1]);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, ctx.getUnit().newInstance());
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
private void print(PrintStream err, Object object) {
|
||||
err.println(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Function} object ignoring its first argument and printing the second to the
|
||||
* standard error stream.
|
||||
*
|
||||
* @param language the current {@link Language} instance
|
||||
* @return a {@link Function} object wrapping the behavior of this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
PrintErrNodeGen.create(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "value", ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IO.print_err";
|
||||
Object doPrint(Object self, Object message, @CachedContext(Language.class) Context ctx) {
|
||||
ctx.getErr().println(message);
|
||||
return ctx.getUnit().newInstance();
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +1,42 @@
|
||||
package org.enso.interpreter.node.expression.builtin.io;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import java.io.PrintStream;
|
||||
import org.enso.interpreter.Language;
|
||||
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.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.CallArgumentInfo;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Allows for printing arbitrary values to the standard output. */
|
||||
@NodeInfo(shortName = "IO.println", description = "Prints its argument to standard out.")
|
||||
public abstract class PrintlnNode extends BuiltinRootNode {
|
||||
private final UnresolvedSymbol toTextSym;
|
||||
@BuiltinMethod(type = "IO", name = "println", description = "Prints its argument to standard out.")
|
||||
public abstract class PrintlnNode extends Node {
|
||||
private @Child InvokeCallableNode invokeCallableNode =
|
||||
InvokeCallableNode.build(
|
||||
new CallArgumentInfo[] {new CallArgumentInfo()},
|
||||
InvokeCallableNode.DefaultsExecutionMode.EXECUTE,
|
||||
InvokeCallableNode.ArgumentsExecutionMode.PRE_EXECUTED);
|
||||
|
||||
PrintlnNode(Language language, ModuleScope scope) {
|
||||
super(language);
|
||||
toTextSym = UnresolvedSymbol.build("to_text", scope);
|
||||
}
|
||||
abstract Stateful execute(
|
||||
VirtualFrame frame, @MonadicState Object state, Object _this, Object message);
|
||||
|
||||
@Specialization
|
||||
Stateful doPrint(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
||||
Object in = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Stateful str = invokeCallableNode.execute(toTextSym, frame, state, new Object[] {in});
|
||||
Stateful doPrint(
|
||||
VirtualFrame frame,
|
||||
Object state,
|
||||
Object self,
|
||||
Object message,
|
||||
@CachedContext(Language.class) Context ctx,
|
||||
@Cached("buildSymbol(ctx)") UnresolvedSymbol symbol) {
|
||||
Stateful str = invokeCallableNode.execute(symbol, frame, state, new Object[] {message});
|
||||
print(ctx.getOut(), str.getValue());
|
||||
|
||||
return new Stateful(str.getState(), ctx.getUnit().newInstance());
|
||||
}
|
||||
|
||||
@ -48,28 +45,11 @@ public abstract class PrintlnNode extends BuiltinRootNode {
|
||||
out.println(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Function} object ignoring its first argument and printing the second to the
|
||||
* standard output.
|
||||
*
|
||||
* @param language the current {@link Language} instance
|
||||
* @return a {@link Function} object wrapping the behavior of this node
|
||||
*/
|
||||
public static Function makeFunction(Language language, ModuleScope scope) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
PrintlnNodeGen.create(language, scope),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "value", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
UnresolvedSymbol buildSymbol(Context ctx) {
|
||||
return UnresolvedSymbol.build("to_text", ctx.getBuiltins().getScope());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IO.println";
|
||||
static PrintlnNode build() {
|
||||
return PrintlnNodeGen.create();
|
||||
}
|
||||
}
|
||||
|
@ -3,63 +3,28 @@ package org.enso.interpreter.node.expression.builtin.io;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import java.io.BufferedReader;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import java.io.IOException;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition.ExecutionMode;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.error.RuntimeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@NodeInfo(shortName = "IO.readln", description = "Reads a line from standard in.")
|
||||
public abstract class ReadlnNode extends BuiltinRootNode {
|
||||
public ReadlnNode(Language language) {
|
||||
super(language);
|
||||
@BuiltinMethod(type = "IO", name = "readln", description = "Reads a line from standard in.")
|
||||
public abstract class ReadlnNode extends Node {
|
||||
static ReadlnNode build() {
|
||||
return ReadlnNodeGen.create();
|
||||
}
|
||||
|
||||
abstract Object execute(Object _this);
|
||||
|
||||
@Specialization
|
||||
Stateful doRead(VirtualFrame frame, @CachedContext(Language.class) Context ctx) {
|
||||
return read(ctx.getIn(), Function.ArgumentsHelper.getState(frame.getArguments()));
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
private Stateful read(BufferedReader in, Object state) {
|
||||
Object doRead(Object _this, @CachedContext(Language.class) Context ctx) {
|
||||
try {
|
||||
String str = in.readLine();
|
||||
|
||||
return new Stateful(state, str);
|
||||
return ctx.getIn().readLine();
|
||||
} catch (IOException e) {
|
||||
return new Stateful(state, new RuntimeError("Empty input stream."));
|
||||
return new RuntimeError("Empty input stream.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Function} object ignoring its first argument and reading from the standard
|
||||
* input stream.
|
||||
*
|
||||
* @param language the current {@link Language} instance
|
||||
* @return a {@link Function} object wrapping the behavior of this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
ReadlnNodeGen.create(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "IO.readln";
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
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 com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
/** An implementation of the operator + for numbers. */
|
||||
@NodeInfo(shortName = "Number.+", description = "Addition on numbers.")
|
||||
public class AddNode extends NumberBinaryOpMethod {
|
||||
private AddNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new AddNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the two operands to this method.
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the result of adding {@code thisArg} to {@code thatArg}
|
||||
*/
|
||||
@Override
|
||||
protected long op(long thisArg, long thatArg) {
|
||||
return thisArg + thatArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.+";
|
||||
@BuiltinMethod(type = "Number", name = "+", description = "Addition on numbers.")
|
||||
public class AddNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this + that;
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
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 com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number./", description = "Division for numbers.")
|
||||
public class DivideNode extends NumberBinaryOpMethod {
|
||||
public DivideNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new DivideNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* The result of dividing this node's operands
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the result of dividing {@code thisArg} by {@code thatArg}
|
||||
*/
|
||||
@Override
|
||||
protected long op(long thisArg, long thatArg) {
|
||||
return thisArg / thatArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number./";
|
||||
@BuiltinMethod(type = "Number", name = "/", description = "Division for numbers.")
|
||||
public class DivideNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this / that;
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number.==", description = "Equality on numbers.")
|
||||
public class EqualsNode extends BuiltinRootNode {
|
||||
private EqualsNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
private @CompilerDirectives.CompilationFinal AtomConstructor tru;
|
||||
private @CompilerDirectives.CompilationFinal AtomConstructor fls;
|
||||
private final BranchProfile thatOpBadTypeProfile = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new EqualsNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return whether or not the input arguments are equal
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
long thisArg =
|
||||
TypesGen.asLong(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object thatArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
|
||||
if (TypesGen.isLong(thatArg)) {
|
||||
long thatArgAsLong = TypesGen.asLong(thatArg);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, thisArg == thatArgAsLong);
|
||||
} else {
|
||||
thatOpBadTypeProfile.enter();
|
||||
throw new TypeError("Unexpected type for `that` operand in " + getName(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.==";
|
||||
@BuiltinMethod(type = "Number", name = "==", description = "Equality on numbers.")
|
||||
public class EqualsNode extends Node {
|
||||
boolean execute(long _this, long that) {
|
||||
return _this == that;
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
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 com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number.%", description = "Mod for numbers.")
|
||||
public class ModNode extends NumberBinaryOpMethod {
|
||||
private ModNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ModNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the remainder from dividing the node's operands.
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the remainder when dividing {@code thisArg} by {@code thatArg}
|
||||
*/
|
||||
@Override
|
||||
protected long op(long thisArg, long thatArg) {
|
||||
return thisArg % thatArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.%";
|
||||
@BuiltinMethod(type = "Number", name = "%", description = "Modulo operation for numbers.")
|
||||
public class ModNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this % that;
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
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 com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number.*", description = "Multiplication on numbers.")
|
||||
public class MultiplyNode extends NumberBinaryOpMethod {
|
||||
private MultiplyNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new MultiplyNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies this method's two operands.
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the result of multiplying {@code thisArg} by {@code thatArg}
|
||||
*/
|
||||
@Override
|
||||
protected long op(long thisArg, long thatArg) {
|
||||
return thisArg * thatArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.*";
|
||||
@BuiltinMethod(type = "Number", name = "*", description = "Multiplication on numbers.")
|
||||
public class MultiplyNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this * that;
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number.negate", description = "Negation for numbers.")
|
||||
public class NegateNode extends BuiltinRootNode {
|
||||
private NegateNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a one-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new NegateNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of negating the function argument
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
long thisArg =
|
||||
TypesGen.asLong(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, -thisArg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.negate";
|
||||
@BuiltinMethod(type = "Number", name = "negate", description = "Negation for numbers.")
|
||||
public class NegateNode extends Node {
|
||||
long execute(long _this) {
|
||||
return -_this;
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(shortName = "Number.BinOp", description = "An abstract class for binary ops on numbers.")
|
||||
public abstract class NumberBinaryOpMethod extends BuiltinRootNode {
|
||||
private final BranchProfile thatOpBadTypeProfile = BranchProfile.create();
|
||||
|
||||
/**
|
||||
* Constructs an instance of this node.
|
||||
*
|
||||
* @param language the language instance for which the node is being constructed
|
||||
*/
|
||||
protected NumberBinaryOpMethod(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes this node.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of performing `op` on the operands
|
||||
*/
|
||||
@Override
|
||||
public final Stateful execute(VirtualFrame frame) {
|
||||
// Note [Safe Casts in Execute]
|
||||
long thisArg =
|
||||
TypesGen.asLong(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
|
||||
Object thatArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
|
||||
if (TypesGen.isLong(thatArg)) {
|
||||
long thatArgAsLong = TypesGen.asLong(thatArg);
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, op(thisArg, thatArgAsLong));
|
||||
} else {
|
||||
thatOpBadTypeProfile.enter();
|
||||
throw new TypeError("Unexpected type for `that` operand in " + getName(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/* Note [Safe Casts in Execute]
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* It is safe to perform this cast here as the type of that argument has already been checked by
|
||||
* the method dispatch mechanism. If this `execute` method is being called, we know that the
|
||||
* `this` argument must be of the correct type.
|
||||
*
|
||||
* This does not hold for any remaining arguments, and as such they must be checked.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The binary operation embodied by the subclass of this node.
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the result of {@code this `op` that}
|
||||
*/
|
||||
protected abstract long op(long thisArg, long thatArg);
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.BinOp";
|
||||
}
|
||||
}
|
@ -1,50 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.number;
|
||||
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
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 com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@NodeInfo(shortName = "Number.-", description = "Subtraction on numbers.")
|
||||
public class SubtractNode extends NumberBinaryOpMethod {
|
||||
private SubtractNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new SubtractNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts this method's two operands.
|
||||
*
|
||||
* @param thisArg the left operand (this)
|
||||
* @param thatArg the right operand (that)
|
||||
* @return the result of subtracting {@code thatArg} from {@code thisArg}
|
||||
*/
|
||||
@Override
|
||||
protected long op(long thisArg, long thatArg) {
|
||||
return thisArg - thatArg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Number.-";
|
||||
@BuiltinMethod(type = "Number", name = "-", description = "Subtraction on numbers.")
|
||||
public class SubtractNode extends Node {
|
||||
long execute(long _this, long that) {
|
||||
return _this - that;
|
||||
}
|
||||
}
|
||||
|
@ -1,53 +1,15 @@
|
||||
package org.enso.interpreter.node.expression.builtin.state;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
|
||||
/** Root node for the builtin State.get function. */
|
||||
@NodeInfo(shortName = "State.get", description = "Root node for the builtin State.get function")
|
||||
public class GetStateNode extends BuiltinRootNode {
|
||||
private GetStateNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the function by accessing the state parameter and returning it.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the current state value without modifying the state
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new GetStateNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "State.get";
|
||||
@BuiltinMethod(
|
||||
type = "State",
|
||||
name = "get",
|
||||
description = "Returns the current value of monadic state.")
|
||||
public class GetStateNode extends Node {
|
||||
Object execute(@MonadicState Object state, Object _this) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,13 @@
|
||||
package org.enso.interpreter.node.expression.builtin.state;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** Root node for the builtin State.put function. */
|
||||
@NodeInfo(shortName = "State.put", description = "Root node for the builtin State.put function")
|
||||
public class PutStateNode extends BuiltinRootNode {
|
||||
private PutStateNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes by taking the desired state value from the second function argument and setting it as
|
||||
* the new state.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return The new state value and a modification setting the state to the same value
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object newState = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
return new Stateful(newState, newState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new PutStateNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "newState", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "State.put";
|
||||
@BuiltinMethod(type = "State", name = "put", description = "Updates the value of monadic state.")
|
||||
public class PutStateNode extends Node {
|
||||
Stateful execute(@MonadicState Object state, Object _this, Object new_state) {
|
||||
return new Stateful(new_state, state);
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,18 @@
|
||||
package org.enso.interpreter.node.expression.builtin.state;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
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;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** Root for the builtin State.run function. */
|
||||
@NodeInfo(shortName = "State.run", description = "Root for the builtin State.run function")
|
||||
public class RunStateNode extends BuiltinRootNode {
|
||||
private RunStateNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "State",
|
||||
name = "run",
|
||||
description = "Runs a stateful computation in a local state environment.")
|
||||
public class RunStateNode extends Node {
|
||||
private @Child ThunkExecutorNode thunkExecutorNode = ThunkExecutorNode.build();
|
||||
private final ConditionProfile thunksProfile = ConditionProfile.createCountingProfile();
|
||||
|
||||
/**
|
||||
* Runs a stateful computation ({@link org.enso.interpreter.runtime.callable.argument.Thunk}) with
|
||||
* a local state value, without modifying the caller state.
|
||||
*
|
||||
* <p>Assumes the local state value is the second argument, while the stateful computation is the
|
||||
* third argument.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @return the result of running the stateful computation with the desired initial state
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object localState = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Object maybeThunk = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
if (thunksProfile.profile(TypesGen.isThunk(maybeThunk))) {
|
||||
return new Stateful(
|
||||
state,
|
||||
thunkExecutorNode.executeThunk(TypesGen.asThunk(maybeThunk), localState, false).getValue());
|
||||
} else {
|
||||
return new Stateful(state, maybeThunk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a three-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new RunStateNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "state", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(
|
||||
2, "statefulComputation", ArgumentDefinition.ExecutionMode.PASS_THUNK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "State.run";
|
||||
Object execute(Object _this, Object local_state, Thunk computation) {
|
||||
return thunkExecutorNode.executeThunk(computation, local_state, false).getValue();
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,16 @@
|
||||
package org.enso.interpreter.node.expression.builtin.system;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
@NodeInfo(shortName = "System.nano_time", description = "Gets the nanosecond resolution system time.")
|
||||
public final class NanoTimeNode extends BuiltinRootNode {
|
||||
private NanoTimeNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link Function} object wrapping this object.
|
||||
*
|
||||
* @param language the current {@link Language} instance
|
||||
* @return a {@link Function} object wrapping the behavior of this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new NanoTimeNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, getNanoTime());
|
||||
}
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "System",
|
||||
name = "nano_time",
|
||||
description = "Gets the nanosecond resolution system time.")
|
||||
public final class NanoTimeNode extends Node {
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private long getNanoTime() {
|
||||
long execute(Object _this) {
|
||||
return System.nanoTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source-level name of this node.
|
||||
*
|
||||
* @return the source-level name of the node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "System.nano_time";
|
||||
}
|
||||
}
|
||||
|
@ -1,63 +1,13 @@
|
||||
package org.enso.interpreter.node.expression.builtin.text;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema.CallStrategy;
|
||||
import org.enso.interpreter.runtime.error.TypeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
/** An implementation of generic string conversion. */
|
||||
@NodeInfo(shortName = "Any.to_text", description = "Generic text conversion.")
|
||||
public class AnyToTextNode extends BuiltinRootNode {
|
||||
private AnyToTextNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new AnyToTextNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object thisArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, toText(thisArg));
|
||||
}
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(type = "Any", name = "to_text", description = "Generic text conversion.")
|
||||
public class AnyToTextNode extends Node {
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private String toText(Object txt) {
|
||||
return txt.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Any.to_text";
|
||||
String execute(Object _this) {
|
||||
return _this.toString();
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +1,11 @@
|
||||
package org.enso.interpreter.node.expression.builtin.text;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.node.expression.builtin.number.NumberBinaryOpMethod;
|
||||
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.TypeError;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
/** An implementation of the operator + for strings. */
|
||||
@NodeInfo(shortName = "Text.+", description = "Text concatenation.")
|
||||
public class ConcatNode extends BuiltinRootNode {
|
||||
private final BranchProfile thatOpBadTypeProfile = BranchProfile.create();
|
||||
|
||||
private ConcatNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a two-argument function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new ConcatNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "that", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of concatenating the input strings.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
String thisArg =
|
||||
TypesGen.asString(Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0]);
|
||||
Object thatArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
if (TypesGen.isString(thatArg)) {
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
|
||||
return new Stateful(state, thisArg + TypesGen.asString(thatArg));
|
||||
} else {
|
||||
thatOpBadTypeProfile.enter();
|
||||
throw new TypeError("Unexpected type for `that` operand in " + getName(), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Text.+";
|
||||
@BuiltinMethod(type = "Text", name = "+", description = "Text concatenation.")
|
||||
public class ConcatNode extends Node {
|
||||
String execute(String _this, String that) {
|
||||
return _this + that;
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,14 @@
|
||||
package org.enso.interpreter.node.expression.builtin.text;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.builtin.LanguageEntitySerializer;
|
||||
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.state.Stateful;
|
||||
|
||||
/** An implementation of generic JSON serialization. */
|
||||
@NodeInfo(shortName = "Any.json_serialize", description = "Generic JSON serialization.")
|
||||
public class JsonSerializeNode extends BuiltinRootNode {
|
||||
private JsonSerializeNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a function wrapping this node.
|
||||
*
|
||||
* @param language the current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new JsonSerializeNode(language),
|
||||
CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the node.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of converting input into a string.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Object thisArg = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[0];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
return new Stateful(state, serialize(thisArg));
|
||||
}
|
||||
|
||||
@BuiltinMethod(type = "Any", name = "json_serialize", description = "Generic JSON serialization.")
|
||||
public class JsonSerializeNode extends Node {
|
||||
@CompilerDirectives.TruffleBoundary
|
||||
private String serialize(Object obj) {
|
||||
return LanguageEntitySerializer.serialize(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a language-specific name for this node.
|
||||
*
|
||||
* @return the name of this node
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Any.json_serialize";
|
||||
String execute(Object _this) {
|
||||
return LanguageEntitySerializer.serialize(_this);
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +1,27 @@
|
||||
package org.enso.interpreter.node.expression.builtin.thread;
|
||||
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import com.oracle.truffle.api.profiles.ConditionProfile;
|
||||
import org.enso.interpreter.Language;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode;
|
||||
import org.enso.interpreter.node.expression.builtin.BuiltinRootNode;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
import org.enso.interpreter.runtime.callable.argument.Thunk;
|
||||
import org.enso.interpreter.runtime.callable.function.Function;
|
||||
import org.enso.interpreter.runtime.callable.function.FunctionSchema;
|
||||
import org.enso.interpreter.runtime.control.ThreadInterruptedException;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
import org.enso.interpreter.runtime.type.TypesGen;
|
||||
|
||||
@NodeInfo(
|
||||
shortName = "Thread.with_interrupt_handler",
|
||||
@BuiltinMethod(
|
||||
type = "Thread",
|
||||
name = "with_interrupt_handler",
|
||||
description = "Runs a computation with a handler for thread interrupts.")
|
||||
public class WithInterruptHandlerNode extends BuiltinRootNode {
|
||||
private WithInterruptHandlerNode(Language language) {
|
||||
super(language);
|
||||
}
|
||||
|
||||
public class WithInterruptHandlerNode extends Node {
|
||||
private @Child ThunkExecutorNode actExecutorNode = ThunkExecutorNode.build();
|
||||
private @Child ThunkExecutorNode handlerExecutorNode = ThunkExecutorNode.build();
|
||||
|
||||
/**
|
||||
* Executes the function.
|
||||
*
|
||||
* @param frame current execution frame.
|
||||
* @return the result of running the function.
|
||||
*/
|
||||
@Override
|
||||
public Stateful execute(VirtualFrame frame) {
|
||||
Thunk act = (Thunk) Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[1];
|
||||
Thunk handler =
|
||||
(Thunk) Function.ArgumentsHelper.getPositionalArguments(frame.getArguments())[2];
|
||||
Object state = Function.ArgumentsHelper.getState(frame.getArguments());
|
||||
Stateful execute(@MonadicState Object state, Object _this, Thunk action, Thunk interrupt_handler) {
|
||||
try {
|
||||
return actExecutorNode.executeThunk(act, state, false);
|
||||
return actExecutorNode.executeThunk(action, state, false);
|
||||
} catch (ThreadInterruptedException e) {
|
||||
handlerExecutorNode.executeThunk(handler, state, false);
|
||||
handlerExecutorNode.executeThunk(interrupt_handler, state, false);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a three-argument function wrapping this node.
|
||||
*
|
||||
* @param language current language instance
|
||||
* @return a function wrapping this node
|
||||
*/
|
||||
public static Function makeFunction(Language language) {
|
||||
return Function.fromBuiltinRootNode(
|
||||
new WithInterruptHandlerNode(language),
|
||||
FunctionSchema.CallStrategy.ALWAYS_DIRECT,
|
||||
new ArgumentDefinition(0, "this", ArgumentDefinition.ExecutionMode.EXECUTE),
|
||||
new ArgumentDefinition(1, "action", ArgumentDefinition.ExecutionMode.PASS_THUNK),
|
||||
new ArgumentDefinition(2, "handler", ArgumentDefinition.ExecutionMode.PASS_THUNK));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Thread.with_interrupt_handler";
|
||||
}
|
||||
}
|
||||
|
@ -1,84 +0,0 @@
|
||||
package org.enso.interpreter.node.expression.debug;
|
||||
|
||||
import com.oracle.truffle.api.debug.DebuggerTags;
|
||||
import com.oracle.truffle.api.dsl.CachedContext;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.instrumentation.GenerateWrapper;
|
||||
import com.oracle.truffle.api.instrumentation.InstrumentableNode;
|
||||
import com.oracle.truffle.api.instrumentation.ProbeNode;
|
||||
import com.oracle.truffle.api.instrumentation.Tag;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.nodes.NodeInfo;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.state.Stateful;
|
||||
|
||||
/** A base node serving as an instrumentable marker. */
|
||||
@NodeInfo(shortName = "Breakpoint", description = "Instrumentation marker node.")
|
||||
@GenerateWrapper
|
||||
public abstract class BreakpointNode extends Node implements InstrumentableNode {
|
||||
|
||||
BreakpointNode() {}
|
||||
|
||||
/**
|
||||
* Creates a new instance of this node.
|
||||
*
|
||||
* @return a new instance of this node
|
||||
*/
|
||||
public static BreakpointNode build() {
|
||||
return BreakpointNodeGen.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells Truffle this node is instrumentable.
|
||||
*
|
||||
* @return {@code true} – this node is always instrumentable.
|
||||
*/
|
||||
@Override
|
||||
public boolean isInstrumentable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this node. Does not do anything interesting, the default implementation returns {@link
|
||||
* Builtins#unit()}. The behavior and return value of this node are assumed to be injected by
|
||||
* attached instruments.
|
||||
*
|
||||
* @param frame current execution frame
|
||||
* @param state current value of the monadic state
|
||||
* @return the result of executing this node
|
||||
*/
|
||||
public abstract Stateful execute(VirtualFrame frame, Object state);
|
||||
|
||||
@Specialization
|
||||
Stateful execute(
|
||||
VirtualFrame frame, Object state, @CachedContext(Language.class) Context context) {
|
||||
return new Stateful(state, context.getUnit().newInstance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs Truffle about the provided tags.
|
||||
*
|
||||
* <p>This node only provides the {@link DebuggerTags.AlwaysHalt} tag.
|
||||
*
|
||||
* @param tag the tag to verify
|
||||
* @return {@code true} if the tag is {@link DebuggerTags.AlwaysHalt}, {@code false} otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean hasTag(Class<? extends Tag> tag) {
|
||||
return tag == DebuggerTags.AlwaysHalt.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instrumentable wrapper node for this node.
|
||||
*
|
||||
* @param probeNode the probe node to wrap
|
||||
* @return the wrapper instance wrapping both this and the probe node
|
||||
*/
|
||||
@Override
|
||||
public WrapperNode createWrapper(ProbeNode probeNode) {
|
||||
return new BreakpointNodeWrapper(this, probeNode);
|
||||
}
|
||||
}
|
@ -20,11 +20,11 @@ public class Bool {
|
||||
public Bool(Language language, ModuleScope scope) {
|
||||
bool = new AtomConstructor("Boolean", scope).initializeFields();
|
||||
scope.registerConstructor(bool);
|
||||
scope.registerMethod(bool, "if_then_else", IfThenElseNode.makeFunction(language));
|
||||
scope.registerMethod(bool, "to_text", ToTextNode.makeFunction(language));
|
||||
scope.registerMethod(bool, "&&", AndNode.makeFunction(language));
|
||||
scope.registerMethod(bool, "||", OrNode.makeFunction(language));
|
||||
scope.registerMethod(bool, "not", NotNode.makeFunction(language));
|
||||
scope.registerMethod(bool, "if_then_else", IfThenElseMethodGen.makeFunction(language));
|
||||
scope.registerMethod(bool, "to_text", ToTextMethodGen.makeFunction(language));
|
||||
scope.registerMethod(bool, "&&", AndMethodGen.makeFunction(language));
|
||||
scope.registerMethod(bool, "||", OrMethodGen.makeFunction(language));
|
||||
scope.registerMethod(bool, "not", NotMethodGen.makeFunction(language));
|
||||
tru = new AtomConstructor("True", scope).initializeFields();
|
||||
scope.registerConstructor(tru);
|
||||
fls = new AtomConstructor("False", scope).initializeFields();
|
||||
|
@ -3,30 +3,20 @@ 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.IfZeroNode;
|
||||
import org.enso.interpreter.node.expression.builtin.debug.DebugBreakpointNode;
|
||||
import org.enso.interpreter.node.expression.builtin.debug.DebugEvalNode;
|
||||
import org.enso.interpreter.node.expression.builtin.error.CatchErrorNode;
|
||||
import org.enso.interpreter.node.expression.builtin.error.CatchPanicNode;
|
||||
import org.enso.interpreter.node.expression.builtin.error.PanicNode;
|
||||
import org.enso.interpreter.node.expression.builtin.error.ThrowErrorNode;
|
||||
import org.enso.interpreter.node.expression.builtin.function.ExplicitCallFunctionNode;
|
||||
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.error.*;
|
||||
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.syntax.MethodDispatchNode;
|
||||
import org.enso.interpreter.node.expression.builtin.interop.syntax.ConstructorDispatchNode;
|
||||
import org.enso.interpreter.node.expression.builtin.io.PrintErrNode;
|
||||
import org.enso.interpreter.node.expression.builtin.io.PrintlnNode;
|
||||
import org.enso.interpreter.node.expression.builtin.io.ReadlnNode;
|
||||
import org.enso.interpreter.node.expression.builtin.io.*;
|
||||
import org.enso.interpreter.node.expression.builtin.number.*;
|
||||
import org.enso.interpreter.node.expression.builtin.system.NanoTimeNode;
|
||||
import org.enso.interpreter.node.expression.builtin.state.*;
|
||||
import org.enso.interpreter.node.expression.builtin.system.NanoTimeMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.interop.java.*;
|
||||
import org.enso.interpreter.node.expression.builtin.state.GetStateNode;
|
||||
import org.enso.interpreter.node.expression.builtin.state.PutStateNode;
|
||||
import org.enso.interpreter.node.expression.builtin.state.RunStateNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.AnyToTextNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.ConcatNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.JsonSerializeNode;
|
||||
import org.enso.interpreter.node.expression.builtin.thread.WithInterruptHandlerNode;
|
||||
import org.enso.interpreter.node.expression.builtin.text.*;
|
||||
import org.enso.interpreter.node.expression.builtin.thread.WithInterruptHandlerMethodGen;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.Module;
|
||||
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||
@ -132,44 +122,43 @@ public class Builtins {
|
||||
|
||||
createPolyglot(language);
|
||||
|
||||
scope.registerMethod(io, "println", PrintlnNode.makeFunction(language, scope));
|
||||
scope.registerMethod(io, "print_err", PrintErrNode.makeFunction(language));
|
||||
scope.registerMethod(io, "readln", ReadlnNode.makeFunction(language));
|
||||
scope.registerMethod(io, "println", PrintlnMethodGen.makeFunction(language));
|
||||
scope.registerMethod(io, "print_err", PrintErrMethodGen.makeFunction(language));
|
||||
scope.registerMethod(io, "readln", ReadlnMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(system, "nano_time", NanoTimeNode.makeFunction(language));
|
||||
scope.registerMethod(system, "nano_time", NanoTimeMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(panic, "throw", PanicNode.makeFunction(language));
|
||||
scope.registerMethod(panic, "recover", CatchPanicNode.makeFunction(language));
|
||||
scope.registerMethod(error, "throw", ThrowErrorNode.makeFunction(language));
|
||||
scope.registerMethod(any, "catch", CatchErrorNode.makeFunction(language));
|
||||
scope.registerMethod(panic, "throw", ThrowPanicMethodGen.makeFunction(language));
|
||||
scope.registerMethod(panic, "recover", CatchPanicMethodGen.makeFunction(language));
|
||||
scope.registerMethod(error, "throw", ThrowErrorMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "catch", CatchErrorMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(number, "ifZero", IfZeroNode.makeFunction(language));
|
||||
scope.registerMethod(number, "+", AddNode.makeFunction(language));
|
||||
scope.registerMethod(number, "-", SubtractNode.makeFunction(language));
|
||||
scope.registerMethod(number, "*", MultiplyNode.makeFunction(language));
|
||||
scope.registerMethod(number, "/", DivideNode.makeFunction(language));
|
||||
scope.registerMethod(number, "%", ModNode.makeFunction(language));
|
||||
scope.registerMethod(number, "negate", NegateNode.makeFunction(language));
|
||||
scope.registerMethod(number, "==", EqualsNode.makeFunction(language));
|
||||
scope.registerMethod(number, "+", AddMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "-", SubtractMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "*", MultiplyMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "/", DivideMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "%", ModMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "negate", NegateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(number, "==", EqualsMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(state, "get", GetStateNode.makeFunction(language));
|
||||
scope.registerMethod(state, "put", PutStateNode.makeFunction(language));
|
||||
scope.registerMethod(state, "run", RunStateNode.makeFunction(language));
|
||||
scope.registerMethod(state, "get", GetStateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(state, "put", PutStateMethodGen.makeFunction(language));
|
||||
scope.registerMethod(state, "run", RunStateMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(debug, MethodNames.Debug.EVAL, DebugEvalNode.makeFunction(language));
|
||||
scope.registerMethod(debug, "breakpoint", DebugBreakpointNode.makeFunction(language));
|
||||
scope.registerMethod(debug, MethodNames.Debug.EVAL, DebugEvalMethodGen.makeFunction(language));
|
||||
scope.registerMethod(debug, "breakpoint", DebugBreakpointMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(function, "call", ExplicitCallFunctionNode.makeFunction(language));
|
||||
scope.registerMethod(function, "call", ExplicitCallFunctionMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(text, "+", ConcatNode.makeFunction(language));
|
||||
scope.registerMethod(any, "to_text", AnyToTextNode.makeFunction(language));
|
||||
scope.registerMethod(any, "json_serialize", JsonSerializeNode.makeFunction(language));
|
||||
scope.registerMethod(text, "+", ConcatMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "to_text", AnyToTextMethodGen.makeFunction(language));
|
||||
scope.registerMethod(any, "json_serialize", JsonSerializeMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(java, "add_to_class_path", AddToClassPathNode.makeFunction(language));
|
||||
scope.registerMethod(java, "lookup_class", LookupClassNode.makeFunction(language));
|
||||
scope.registerMethod(java, "add_to_class_path", AddToClassPathMethodGen.makeFunction(language));
|
||||
scope.registerMethod(java, "lookup_class", LookupClassMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(
|
||||
thread, "with_interrupt_handler", WithInterruptHandlerNode.makeFunction(language));
|
||||
thread, "with_interrupt_handler", WithInterruptHandlerMethodGen.makeFunction(language));
|
||||
|
||||
interopDispatchRoot = Truffle.getRuntime().createCallTarget(MethodDispatchNode.build(language));
|
||||
interopDispatchSchema =
|
||||
@ -189,13 +178,14 @@ public class Builtins {
|
||||
private void createPolyglot(Language language) {
|
||||
AtomConstructor polyglot = new AtomConstructor("Polyglot", scope).initializeFields();
|
||||
scope.registerConstructor(polyglot);
|
||||
scope.registerMethod(polyglot, "execute", ExecuteNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "invoke", InvokeNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "new", InstantiateNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "get_member", GetMemberNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "get_members", GetMembersNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "get_array_size", GetArraySizeNode.makeFunction(language));
|
||||
scope.registerMethod(polyglot, "get_array_element", GetArrayElementNode.makeFunction(language));
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,7 +221,7 @@ class ReplTest extends InterpreterTest with BeforeAndAfter with EitherValues {
|
||||
}
|
||||
eval(code)
|
||||
val errorMsg =
|
||||
"Unexpected type for `that` operand in Number.+"
|
||||
"Unexpected type provided for argument `that` in Number.+"
|
||||
evalResult.left.value.getMessage shouldEqual errorMsg
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,9 @@ class CodeLocationsTest extends InterpreterTest {
|
||||
|
||||
"be correct in applications and method calls" in
|
||||
withLocationsInstrumenter { instrumenter =>
|
||||
val code = "main = (2 - 2).ifZero (Cons 5 6) 0"
|
||||
instrumenter.assertNodeExists(7, 27, classOf[ApplicationNode])
|
||||
instrumenter.assertNodeExists(23, 8, classOf[ApplicationNode])
|
||||
val code = "main = (2-2 == 0).if_then_else (Cons 5 6) 0"
|
||||
instrumenter.assertNodeExists(7, 36, classOf[ApplicationNode])
|
||||
instrumenter.assertNodeExists(32, 8, classOf[ApplicationNode])
|
||||
eval(code)
|
||||
()
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
val testCode =
|
||||
"""
|
||||
|main =
|
||||
| genList = i -> ifZero i Nil (Cons i (genList (i - 1)))
|
||||
| genList = i -> if i == 0 then Nil else Cons i (genList (i - 1))
|
||||
| sumList = list -> case list of
|
||||
| Cons h t -> h + sumList t
|
||||
| Nil -> 0
|
||||
@ -83,7 +83,7 @@ class ConstructorsTest extends InterpreterTest {
|
||||
"""
|
||||
|type Cons2 a b
|
||||
|
|
||||
|Unit.genList = i -> ifZero i Nil2 (Cons2 i (genList Unit (i - 1)))
|
||||
|Unit.genList = i -> if i == 0 then Nil2 else Cons2 i (genList Unit (i - 1))
|
||||
|
|
||||
|type Nil2
|
||||
|
|
||||
|
@ -65,7 +65,7 @@ class EvalTest extends InterpreterTest {
|
||||
|main =
|
||||
| fn = sumTo ->
|
||||
| summator = acc -> current ->
|
||||
| Debug.eval "ifZero current acc (summator (acc + current) (current - 1))"
|
||||
| Debug.eval "if current == 0 then acc else summator (acc + current) (current - 1)"
|
||||
| summator 0 sumTo
|
||||
| fn 100
|
||||
|""".stripMargin
|
||||
@ -78,7 +78,7 @@ class EvalTest extends InterpreterTest {
|
||||
|main =
|
||||
| fn = sumTo ->
|
||||
| summator = acc -> current ->
|
||||
| ifZero current acc (Debug.eval "summator (acc + current) (current - 1)")
|
||||
| if current == 0 then acc else Debug.eval "summator (acc + current) (current - 1)"
|
||||
|
|
||||
| summator 0 sumTo
|
||||
|
|
||||
|
@ -41,10 +41,10 @@ class ExpressionIdTest extends InterpreterTest {
|
||||
|
||||
"be correct in applications and method calls" in
|
||||
withIdsInstrumenter { instrumenter =>
|
||||
val code = "main = (2 - 2).ifZero (Cons 5 6) 0"
|
||||
val code = "main = (2-2 == 0).if_then_else (Cons 5 6) 0"
|
||||
val meta = new Metadata
|
||||
val id1 = meta.addItem(7, 27)
|
||||
val id2 = meta.addItem(23, 8)
|
||||
val id1 = meta.addItem(7, 36)
|
||||
val id2 = meta.addItem(32, 8)
|
||||
|
||||
instrumenter.assertNodeExists(id1, "Cons 5 6")
|
||||
instrumenter.assertNodeExists(id2, "Cons 5 6")
|
||||
|
@ -61,7 +61,7 @@ class GlobalScopeTest extends InterpreterTest {
|
||||
| Unit.fn1 res
|
||||
|
|
||||
|Unit.fn1 = number ->
|
||||
| ifZero (number % 3) number (Unit.decrementCall number)
|
||||
| if (number % 3) == 0 then number else Unit.decrementCall number
|
||||
|
|
||||
|main = Unit.fn1 5
|
||||
""".stripMargin
|
||||
|
@ -33,7 +33,7 @@ class GroupingTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| ifTest = c -> (~ifT) -> ~ifF -> ifZero c ifT ifF
|
||||
| ifTest = c -> (~ifT) -> ~ifF -> if c == 0 then ifT else ifF
|
||||
| sum = c -> acc -> ifTest c acc (sum c-1 acc+c)
|
||||
| sum 10000 0
|
||||
|""".stripMargin
|
||||
|
@ -12,7 +12,7 @@ class InteropTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| recurFun = i -> ifZero i 0 (recurFun i-1)
|
||||
| recurFun = i -> if i == 0 then 0 else recurFun i-1
|
||||
| recurFun
|
||||
|""".stripMargin
|
||||
|
||||
|
@ -51,7 +51,7 @@ class LambdaShorthandArgsTest extends InterpreterTest {
|
||||
"work with mixfix functions" in {
|
||||
val code =
|
||||
"""
|
||||
|Number.if_then_else = ~t -> ~f -> ifZero this t f
|
||||
|Number.if_then_else = ~t -> ~f -> if this == 0 then t else f
|
||||
|
|
||||
|main =
|
||||
| f = if _ then 10 else 5
|
||||
|
@ -44,7 +44,7 @@ class LambdaTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| sumTo = x -> ifZero x 0 (x + (sumTo (x-1)))
|
||||
| sumTo = x -> if x == 0 then 0 else x + (sumTo (x-1))
|
||||
| sumTo 10
|
||||
""".stripMargin
|
||||
|
||||
@ -105,7 +105,7 @@ class LambdaTest extends InterpreterTest {
|
||||
"""
|
||||
|main =
|
||||
| summator = current ->
|
||||
| ifZero current 0 ((x -> summator (current - 1)) 0)
|
||||
| if current == 0 then 0 else (x -> summator (current - 1)) 0
|
||||
| res = summator 0
|
||||
| res
|
||||
|""".stripMargin
|
||||
@ -132,7 +132,7 @@ class LambdaTest extends InterpreterTest {
|
||||
"call fully saturated lambdas returned with TCO" in {
|
||||
val code =
|
||||
"""
|
||||
|Number.if_then_else = ~t -> ~f -> ifZero this t f
|
||||
|Number.if_then_else = ~t -> ~f -> if this == 0 then t else f
|
||||
|
|
||||
|main =
|
||||
| lam = (x = 10) -> x
|
||||
|
@ -123,7 +123,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
"""
|
||||
|Unit.summer = sumTo ->
|
||||
| summator = (acc = 0) -> current ->
|
||||
| ifZero current acc (summator (current = current - 1) (acc = acc + current))
|
||||
| if current == 0 then acc else summator (current = current - 1) (acc = acc + current)
|
||||
| res = summator (current = sumTo)
|
||||
| res
|
||||
|
|
||||
@ -187,7 +187,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|type Nil2
|
||||
|
|
||||
|main =
|
||||
| genList = i -> ifZero i Nil2 (Cons2 (rest = genList i-1) head=i)
|
||||
| genList = i -> if i == 0 then Nil2 else Cons2 (rest = genList i-1) head=i
|
||||
|
|
||||
| sum = list -> case list of
|
||||
| Cons2 h t -> h + t.sum
|
||||
@ -206,7 +206,7 @@ class NamedArgumentsTest extends InterpreterTest {
|
||||
|type Cons2 head (rest = Nil2)
|
||||
|
|
||||
|main =
|
||||
| genList = i -> ifZero i Nil2 (Cons2 (rest = genList i-1) head=i)
|
||||
| genList = i -> if i == 0 then Nil2 else Cons2 (rest = genList i-1) head=i
|
||||
|
|
||||
| sum = list -> case list of
|
||||
| Cons2 h t -> h + t.sum
|
||||
|
@ -66,7 +66,7 @@ class StateTest extends InterpreterTest {
|
||||
| stateSum = n ->
|
||||
| acc = State.get
|
||||
| State.put acc+n
|
||||
| ifZero n State.get (stateSum n-1)
|
||||
| if n == 0 then State.get else stateSum n-1
|
||||
|
|
||||
| State.run 0 (stateSum 10)
|
||||
|""".stripMargin
|
||||
|
@ -25,7 +25,7 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| foo = i -> ~x -> ~y -> ifZero i x y
|
||||
| foo = i -> ~x -> ~y -> if i == 0 then x else y
|
||||
| foo 1 (IO.println 1) (IO.println 2)
|
||||
|""".stripMargin
|
||||
eval(code)
|
||||
@ -36,7 +36,7 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| ifTest = c -> ~ifT -> ~ifF -> ifZero c ifT ifF
|
||||
| ifTest = c -> ~ifT -> ~ifF -> if c == 0 then ifT else ifF
|
||||
| sum = c -> acc -> ifTest c acc (sum c-1 acc+c)
|
||||
| sum 10000 0
|
||||
|""".stripMargin
|
||||
@ -77,7 +77,7 @@ class SuspendedArgumentsTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|main =
|
||||
| ifTest = c -> ~ifT -> ~ifF -> ifZero c ifT ifF
|
||||
| ifTest = c -> ~ifT -> ~ifF -> if c == 0 then ifT else ifF
|
||||
| foo = c -> ifTest c
|
||||
|
|
||||
| foo 0 (IO.println 1) (IO.println 2)
|
||||
|
@ -22,7 +22,7 @@ class ThreadInterruptionTest extends InterpreterTest {
|
||||
val code =
|
||||
"""
|
||||
|foo x =
|
||||
| ifZero x (IO.println "Start.") Unit
|
||||
| if x == 0 then IO.println "Start." else Unit
|
||||
| here.foo x+1
|
||||
|
|
||||
|main =
|
||||
|
@ -0,0 +1,23 @@
|
||||
package org.enso.interpreter.dsl;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** An annotation denoting a node that should be wrapped for standard library export. */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface BuiltinMethod {
|
||||
/** @return the language-level type of {@code this} argument. */
|
||||
String type();
|
||||
|
||||
/** @return the language-level name of this method. */
|
||||
String name();
|
||||
|
||||
/** @return a short description of this method. */
|
||||
String description();
|
||||
|
||||
/** @return whether it is safe to always call this function directly. */
|
||||
boolean alwaysDirect() default true;
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
package org.enso.interpreter.dsl;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.enso.interpreter.dsl.model.MethodDefinition;
|
||||
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
/** The processor used to generate code from the {@link BuiltinMethod} annotation. */
|
||||
@SupportedAnnotationTypes("org.enso.interpreter.dsl.BuiltinMethod")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||
@AutoService(Processor.class)
|
||||
public class MethodProcessor extends AbstractProcessor {
|
||||
|
||||
/**
|
||||
* Processes annotated elements, generating code for each of them.
|
||||
*
|
||||
* @param annotations annotation being processed this round.
|
||||
* @param roundEnv additional round information.
|
||||
* @return {@code true}
|
||||
*/
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
for (TypeElement annotation : annotations) {
|
||||
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
|
||||
for (Element elt : annotatedElements) {
|
||||
TypeElement element = (TypeElement) elt;
|
||||
ExecutableElement executeMethod =
|
||||
element.getEnclosedElements().stream()
|
||||
.filter(
|
||||
x -> {
|
||||
if (!(x instanceof ExecutableElement)) return false;
|
||||
Name name = x.getSimpleName();
|
||||
return name.contentEquals("execute");
|
||||
})
|
||||
.map(x -> (ExecutableElement) x)
|
||||
.findFirst()
|
||||
.orElseGet(
|
||||
() -> {
|
||||
processingEnv
|
||||
.getMessager()
|
||||
.printMessage(Diagnostic.Kind.ERROR, "No execute method found.", element);
|
||||
return null;
|
||||
});
|
||||
if (executeMethod == null) continue;
|
||||
String pkgName =
|
||||
processingEnv.getElementUtils().getPackageOf(element).getQualifiedName().toString();
|
||||
MethodDefinition def = new MethodDefinition(pkgName, element, executeMethod);
|
||||
if (!def.validate(processingEnv)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
generateCode(def);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private final List<String> necessaryImports =
|
||||
Arrays.asList(
|
||||
"com.oracle.truffle.api.frame.VirtualFrame",
|
||||
"com.oracle.truffle.api.nodes.NodeInfo",
|
||||
"com.oracle.truffle.api.nodes.UnexpectedResultException",
|
||||
"org.enso.interpreter.Language",
|
||||
"org.enso.interpreter.node.expression.builtin.BuiltinRootNode",
|
||||
"org.enso.interpreter.runtime.callable.argument.ArgumentDefinition",
|
||||
"org.enso.interpreter.runtime.callable.function.Function",
|
||||
"org.enso.interpreter.runtime.callable.function.FunctionSchema",
|
||||
"org.enso.interpreter.runtime.error.TypeError",
|
||||
"org.enso.interpreter.runtime.state.Stateful",
|
||||
"org.enso.interpreter.runtime.type.TypesGen");
|
||||
|
||||
private void generateCode(MethodDefinition methodDefinition) throws IOException {
|
||||
JavaFileObject gen =
|
||||
processingEnv.getFiler().createSourceFile(methodDefinition.getQualifiedName());
|
||||
|
||||
Set<String> allImports = new HashSet<>(necessaryImports);
|
||||
allImports.addAll(methodDefinition.getImports());
|
||||
|
||||
try (PrintWriter out = new PrintWriter(gen.openWriter())) {
|
||||
out.println("package " + methodDefinition.getPackageName() + ";");
|
||||
out.println();
|
||||
|
||||
allImports.forEach(pkg -> out.println("import " + pkg + ";"));
|
||||
|
||||
out.println();
|
||||
|
||||
out.println("@NodeInfo(");
|
||||
out.println(" shortName = \"" + methodDefinition.getDeclaredName() + "\",");
|
||||
out.println(" description = \"" + methodDefinition.getDescription() + "\")");
|
||||
out.println("public class " + methodDefinition.getClassName() + " extends BuiltinRootNode {");
|
||||
out.println(" private @Child " + methodDefinition.getOriginalClassName() + " bodyNode;");
|
||||
|
||||
out.println();
|
||||
|
||||
out.println(" private " + methodDefinition.getClassName() + "(Language language) {");
|
||||
out.println(" super(language);");
|
||||
out.println(" bodyNode = " + methodDefinition.getConstructorExpression() + ";");
|
||||
out.println(" }");
|
||||
|
||||
out.println();
|
||||
|
||||
String functionBuilderMethod =
|
||||
methodDefinition.needsCallerInfo()
|
||||
? "fromBuiltinRootNodeWithCallerFrameAccess"
|
||||
: "fromBuiltinRootNode";
|
||||
|
||||
out.println(" public static Function makeFunction(Language language) {");
|
||||
out.println(" return Function." + functionBuilderMethod + "(");
|
||||
out.println(" new " + methodDefinition.getClassName() + "(language),");
|
||||
if (methodDefinition.isAlwaysDirect()) {
|
||||
out.println(" FunctionSchema.CallStrategy.ALWAYS_DIRECT,");
|
||||
} else {
|
||||
out.println(" FunctionSchema.CallStrategy.DIRECT_WHEN_TAIL,");
|
||||
}
|
||||
List<String> argumentDefs = new ArrayList<>();
|
||||
for (MethodDefinition.ArgumentDefinition arg : methodDefinition.getArguments()) {
|
||||
if (arg.isPositional()) {
|
||||
String executionMode = arg.isSuspended() ? "PASS_THUNK" : "EXECUTE";
|
||||
argumentDefs.add(
|
||||
" new ArgumentDefinition("
|
||||
+ arg.getPosition()
|
||||
+ ", \""
|
||||
+ arg.getName()
|
||||
+ "\", ArgumentDefinition.ExecutionMode."
|
||||
+ executionMode
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
out.println(String.join(",\n", argumentDefs) + ");");
|
||||
out.println(" }");
|
||||
|
||||
out.println();
|
||||
|
||||
out.println(" @Override");
|
||||
out.println(" public Stateful execute(VirtualFrame frame) {");
|
||||
out.println(" Object state = Function.ArgumentsHelper.getState(frame.getArguments());");
|
||||
if (methodDefinition.needsCallerInfo()) {
|
||||
out.println(
|
||||
" CallerInfo callerInfo = Function.ArgumentsHelper.getCallerInfo(frame.getArguments());");
|
||||
}
|
||||
out.println(
|
||||
" Object[] arguments = Function.ArgumentsHelper.getPositionalArguments(frame.getArguments());");
|
||||
List<String> callArgNames = new ArrayList<>();
|
||||
for (MethodDefinition.ArgumentDefinition argumentDefinition :
|
||||
methodDefinition.getArguments()) {
|
||||
if (argumentDefinition.isState()) {
|
||||
callArgNames.add("state");
|
||||
} else if (argumentDefinition.isFrame()) {
|
||||
callArgNames.add("frame");
|
||||
} else if (argumentDefinition.isCallerInfo()) {
|
||||
callArgNames.add("callerInfo");
|
||||
} else {
|
||||
callArgNames.add("arg" + argumentDefinition.getPosition());
|
||||
generateArgumentRead(
|
||||
out, argumentDefinition, methodDefinition.getDeclaredName(), "arguments");
|
||||
}
|
||||
}
|
||||
String executeCall = "bodyNode.execute(" + String.join(", ", callArgNames) + ")";
|
||||
if (methodDefinition.modifiesState()) {
|
||||
out.println(" return " + executeCall + ";");
|
||||
} else {
|
||||
out.println(" return new Stateful(state, " + executeCall + ");");
|
||||
}
|
||||
out.println(" }");
|
||||
|
||||
out.println();
|
||||
|
||||
out.println(" @Override");
|
||||
out.println(" public String getName() {");
|
||||
out.println(" return \"" + methodDefinition.getDeclaredName() + "\";");
|
||||
out.println(" }");
|
||||
|
||||
out.println();
|
||||
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateArgumentRead(
|
||||
PrintWriter out,
|
||||
MethodDefinition.ArgumentDefinition arg,
|
||||
String methodName,
|
||||
String argsArray) {
|
||||
if (!arg.requiresCast()) {
|
||||
generateUncastedArgumentRead(out, arg, argsArray);
|
||||
} else if (arg.getName().equals("this") && arg.getPosition() == 0) {
|
||||
generateUncheckedArgumentRead(out, arg, argsArray);
|
||||
} else {
|
||||
generateCheckedArgumentRead(out, arg, methodName, argsArray);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateUncastedArgumentRead(
|
||||
PrintWriter out, MethodDefinition.ArgumentDefinition arg, String argsArray) {
|
||||
String varName = "arg" + arg.getPosition();
|
||||
out.println(
|
||||
" "
|
||||
+ arg.getTypeName()
|
||||
+ " "
|
||||
+ varName
|
||||
+ " = "
|
||||
+ argsArray
|
||||
+ "["
|
||||
+ arg.getPosition()
|
||||
+ "];");
|
||||
}
|
||||
|
||||
private void generateUncheckedArgumentRead(
|
||||
PrintWriter out, MethodDefinition.ArgumentDefinition arg, String argsArray) {
|
||||
String castName = "TypesGen.as" + capitalize(arg.getTypeName());
|
||||
String varName = "arg" + arg.getPosition();
|
||||
out.println(
|
||||
" "
|
||||
+ arg.getTypeName()
|
||||
+ " "
|
||||
+ varName
|
||||
+ " = "
|
||||
+ castName
|
||||
+ "("
|
||||
+ argsArray
|
||||
+ "["
|
||||
+ arg.getPosition()
|
||||
+ "]);");
|
||||
}
|
||||
|
||||
private void generateCheckedArgumentRead(
|
||||
PrintWriter out,
|
||||
MethodDefinition.ArgumentDefinition arg,
|
||||
String methodName,
|
||||
String argsArray) {
|
||||
String castName = "TypesGen.expect" + capitalize(arg.getTypeName());
|
||||
String varName = "arg" + arg.getPosition();
|
||||
out.println(" " + arg.getTypeName() + " " + varName + ";");
|
||||
out.println(" try {");
|
||||
out.println(
|
||||
" " + varName + " = " + castName + "(" + argsArray + "[" + arg.getPosition() + "]);");
|
||||
out.println(" } catch (UnexpectedResultException e) {");
|
||||
out.println(
|
||||
" throw new TypeError(\"Unexpected type provided for argument `"
|
||||
+ arg.getName()
|
||||
+ "` in "
|
||||
+ methodName
|
||||
+ "\", this);");
|
||||
out.println(" }");
|
||||
}
|
||||
|
||||
private String capitalize(String name) {
|
||||
return name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package org.enso.interpreter.dsl;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** An interface marking an argument as requiring to be passed the current monadic state. */
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface MonadicState {}
|
@ -0,0 +1,276 @@
|
||||
package org.enso.interpreter.dsl.model;
|
||||
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.dsl.MonadicState;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.lang.model.element.*;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.tools.Diagnostic;
|
||||
import java.util.*;
|
||||
|
||||
/** A domain-specific representation of a builtin method. */
|
||||
public class MethodDefinition {
|
||||
private static final String STATEFUL = "org.enso.interpreter.runtime.state.Stateful";
|
||||
|
||||
private final String packageName;
|
||||
private final String originalClassName;
|
||||
private final String className;
|
||||
private final String qualifiedName;
|
||||
private final BuiltinMethod annotation;
|
||||
private final TypeElement element;
|
||||
private final ExecutableElement executeMethod;
|
||||
private final List<ArgumentDefinition> arguments;
|
||||
private final Set<String> imports;
|
||||
private final boolean modifiesState;
|
||||
private final boolean needsCallerInfo;
|
||||
private final String constructorExpression;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
*
|
||||
* @param packageName the name of the package this method is declared in.
|
||||
* @param element the element (class) declaring this method.
|
||||
* @param execute the element (method) containing the logic.
|
||||
*/
|
||||
public MethodDefinition(String packageName, TypeElement element, ExecutableElement execute) {
|
||||
this.annotation = element.getAnnotation(BuiltinMethod.class);
|
||||
this.element = element;
|
||||
this.executeMethod = execute;
|
||||
this.originalClassName = element.getSimpleName().toString();
|
||||
this.packageName = packageName;
|
||||
this.className = generateClassName(originalClassName);
|
||||
this.qualifiedName = packageName + "." + className;
|
||||
this.arguments = initArguments(execute);
|
||||
this.imports = initImports();
|
||||
this.needsCallerInfo = arguments.stream().anyMatch(ArgumentDefinition::isCallerInfo);
|
||||
this.modifiesState = execute.getReturnType().toString().equals(STATEFUL);
|
||||
this.constructorExpression = initConstructor(element);
|
||||
}
|
||||
|
||||
private String initConstructor(TypeElement element) {
|
||||
boolean useBuild =
|
||||
element.getEnclosedElements().stream()
|
||||
.anyMatch(
|
||||
el -> {
|
||||
if (el.getKind() != ElementKind.METHOD) {
|
||||
return false;
|
||||
}
|
||||
ExecutableElement method = (ExecutableElement) el;
|
||||
return method.getSimpleName().contentEquals("build")
|
||||
&& method.getParameters().isEmpty()
|
||||
&& method.getModifiers().contains(Modifier.STATIC);
|
||||
});
|
||||
if (useBuild) {
|
||||
return originalClassName + ".build()";
|
||||
} else {
|
||||
return "new " + originalClassName + "()";
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> initImports() {
|
||||
Set<String> result = new HashSet<>();
|
||||
for (ArgumentDefinition arg : arguments) {
|
||||
Optional<String> imp = arg.getImport();
|
||||
imp.ifPresent(result::add);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String generateClassName(String originalClassName) {
|
||||
String baseName =
|
||||
originalClassName.endsWith("Node")
|
||||
? originalClassName.substring(0, originalClassName.length() - 4)
|
||||
: originalClassName;
|
||||
return baseName + "MethodGen";
|
||||
}
|
||||
|
||||
private List<ArgumentDefinition> initArguments(ExecutableElement method) {
|
||||
List<ArgumentDefinition> args = new ArrayList<>();
|
||||
List<? extends VariableElement> params = method.getParameters();
|
||||
int position = 0;
|
||||
for (VariableElement param : params) {
|
||||
ArgumentDefinition def = new ArgumentDefinition(param, position);
|
||||
args.add(def);
|
||||
if (def.isPositional()) {
|
||||
position++;
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the validity of this definition with respect to required properties.
|
||||
*
|
||||
* <p>Any invalid elements will be reported as errors.
|
||||
*
|
||||
* @param processingEnvironment the current processing environment.
|
||||
* @return whether the definition is fully valid.
|
||||
*/
|
||||
public boolean validate(ProcessingEnvironment processingEnvironment) {
|
||||
boolean definesThis =
|
||||
arguments.stream().anyMatch(arg -> arg.getName().equals("this") && arg.isPositional());
|
||||
if (!definesThis) {
|
||||
processingEnvironment
|
||||
.getMessager()
|
||||
.printMessage(
|
||||
Diagnostic.Kind.ERROR,
|
||||
"The execute method does not take `this` argument. At least one positional argument must be named `_this`.",
|
||||
element);
|
||||
}
|
||||
return definesThis;
|
||||
}
|
||||
|
||||
/** @return the package name this method was declared in. */
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
/** @return the original class name of this method. */
|
||||
public String getOriginalClassName() {
|
||||
return originalClassName;
|
||||
}
|
||||
|
||||
/** @return the simple class name of generated method wrapper. */
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/** @return full name (with package) of the generated wrapper. */
|
||||
public String getQualifiedName() {
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
/** @return the language-level name of this method. */
|
||||
public String getDeclaredName() {
|
||||
return annotation.type() + "." + annotation.name();
|
||||
}
|
||||
|
||||
/** @return get the description of this method. */
|
||||
public String getDescription() {
|
||||
return annotation.description();
|
||||
}
|
||||
|
||||
/** @return the arguments this method declares. */
|
||||
public List<ArgumentDefinition> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
/** @return the additional imports this method definition requires. */
|
||||
public Set<String> getImports() {
|
||||
return imports;
|
||||
}
|
||||
|
||||
/** @return whether this method modifies the monadic state. */
|
||||
public boolean modifiesState() {
|
||||
return modifiesState;
|
||||
}
|
||||
|
||||
/** @return whether this method requires caller info to work properly. */
|
||||
public boolean needsCallerInfo() {
|
||||
return needsCallerInfo;
|
||||
}
|
||||
|
||||
/** @return whether this method can be always safely called directly. */
|
||||
public boolean isAlwaysDirect() {
|
||||
return annotation.alwaysDirect();
|
||||
}
|
||||
|
||||
public String getConstructorExpression() {
|
||||
return constructorExpression;
|
||||
}
|
||||
|
||||
/** A domain specific representation of a method argument. */
|
||||
public static class ArgumentDefinition {
|
||||
private static final String VIRTUAL_FRAME = "com.oracle.truffle.api.frame.VirtualFrame";
|
||||
private static final String OBJECT = "java.lang.Object";
|
||||
private static final String THUNK = "org.enso.interpreter.runtime.callable.argument.Thunk";
|
||||
private static final String CALLER_INFO = "org.enso.interpreter.runtime.callable.CallerInfo";
|
||||
private final String typeName;
|
||||
private final TypeMirror type;
|
||||
private final String name;
|
||||
private final boolean isState;
|
||||
private final boolean isFrame;
|
||||
private final boolean isCallerInfo;
|
||||
private final int position;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class.
|
||||
*
|
||||
* @param element the element representing this argument.
|
||||
* @param position the position (0-indexed) of this argument in the arguments list.
|
||||
*/
|
||||
public ArgumentDefinition(VariableElement element, int position) {
|
||||
type = element.asType();
|
||||
String[] typeNameSegments = type.toString().split("\\.");
|
||||
typeName = typeNameSegments[typeNameSegments.length - 1];
|
||||
String originalName = element.getSimpleName().toString();
|
||||
name = originalName.equals("_this") ? "this" : originalName;
|
||||
isState = element.getAnnotation(MonadicState.class) != null && type.toString().equals(OBJECT);
|
||||
isFrame = type.toString().equals(VIRTUAL_FRAME);
|
||||
isCallerInfo = type.toString().equals(CALLER_INFO);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
/** @return whether this argument should be passed the monadic state. */
|
||||
public boolean isState() {
|
||||
return isState;
|
||||
}
|
||||
|
||||
/** @return whether this argument should be passed the execution frame. */
|
||||
public boolean isFrame() {
|
||||
return isFrame;
|
||||
}
|
||||
|
||||
/** @return whether this argument should be passed the caller info. */
|
||||
public boolean isCallerInfo() {
|
||||
return isCallerInfo;
|
||||
}
|
||||
|
||||
/** @return whether this argument should be passed the next positional function argument. */
|
||||
public boolean isPositional() {
|
||||
return !isFrame() && !isState() && !isCallerInfo();
|
||||
}
|
||||
|
||||
/** @return the position of this argument in the positional arguments list. */
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
/** @return any import this argument requires. */
|
||||
public Optional<String> getImport() {
|
||||
if (type.getKind() == TypeKind.DECLARED) {
|
||||
if (!type.toString().equals(OBJECT)) {
|
||||
return Optional.of(type.toString());
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/** @return whether this argument needs to be type-casted on read. */
|
||||
public boolean requiresCast() {
|
||||
return !type.toString().equals(OBJECT);
|
||||
}
|
||||
|
||||
/** @return the name of the type of this argument. */
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/** @return the type of this argument. */
|
||||
public TypeMirror getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @return the name of this argument. */
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/** @return whether this argument is expected to be passed suspended. */
|
||||
public boolean isSuspended() {
|
||||
return type.toString().equals(THUNK);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user