mirror of
https://github.com/apple/pkl.git
synced 2026-01-11 22:30:54 +01:00
Compare commits
20 Commits
main
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e805a04a74 | ||
|
|
edf704b469 | ||
|
|
d9cfb68048 | ||
|
|
1e75001382 | ||
|
|
376eb2bdbf | ||
|
|
56a3b0a193 | ||
|
|
6c8e45b19a | ||
|
|
0bc1b7156e | ||
|
|
f0b961de81 | ||
|
|
3ece353e0c | ||
|
|
639cc2430e | ||
|
|
48a710f439 | ||
|
|
15d85b0660 | ||
|
|
aeace8bb3c | ||
|
|
7b850dd6d9 | ||
|
|
c2096f633b | ||
|
|
d6ba021e12 | ||
|
|
077497d9b8 | ||
|
|
552b301451 | ||
|
|
d3ac4b288c |
@@ -108,10 +108,12 @@ local gradleCheckJobs: Mapping<String, GradleCheckJob> = new {
|
||||
["gradle-check-jdk17"] {
|
||||
javaVersion = "17.0"
|
||||
isRelease = false
|
||||
os = "linux"
|
||||
}
|
||||
["gradle-check-jdk21"] {
|
||||
javaVersion = "21.0"
|
||||
isRelease = false
|
||||
os = "linux"
|
||||
}
|
||||
["gradle-check-jdk17-windows"] {
|
||||
javaVersion = "17.0"
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
curl -Lf https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -148,7 +148,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -222,7 +222,7 @@ jobs:
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
curl -Lf https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
@@ -262,6 +262,18 @@ jobs:
|
||||
pkl-cli-windows-amd64-release:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
# install jdk
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
|
||||
|
||||
unzip /tmp/jdk.zip -d /tmp/jdk \
|
||||
&& cd /tmp/jdk/jdk-* \
|
||||
&& mkdir /jdk \
|
||||
&& cp -r . /jdk
|
||||
name: Set up environment
|
||||
shell: bash.exe
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
@@ -276,6 +288,7 @@ jobs:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
@@ -315,7 +328,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -328,7 +341,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -341,7 +354,7 @@ jobs:
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
curl -Lf https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
@@ -411,7 +424,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -424,7 +437,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -472,7 +485,7 @@ jobs:
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9/OpenJDK17U-jdk_x64_linux_hotspot_17.0.9_9.tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
@@ -485,7 +498,7 @@ jobs:
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v1.2.13/zlib-1.2.13.tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-1.2.13 \
|
||||
&& cd /tmp/dep_zlib-1.2.13 \
|
||||
@@ -498,7 +511,7 @@ jobs:
|
||||
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
curl -Lf https://musl.libc.org/releases/musl-1.2.2.tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-1.2.2 \
|
||||
&& cd /tmp/dep_musl-1.2.2 \
|
||||
@@ -538,6 +551,18 @@ jobs:
|
||||
pkl-cli-windows-amd64-snapshot:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
# install jdk
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
|
||||
|
||||
unzip /tmp/jdk.zip -d /tmp/jdk \
|
||||
&& cd /tmp/jdk/jdk-* \
|
||||
&& mkdir /jdk \
|
||||
&& cp -r . /jdk
|
||||
name: Set up environment
|
||||
shell: bash.exe
|
||||
- run:
|
||||
command: |-
|
||||
export PATH=~/staticdeps/bin:$PATH
|
||||
@@ -552,6 +577,7 @@ jobs:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
@@ -582,6 +608,18 @@ jobs:
|
||||
gradle-check-jdk17-windows:
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: |-
|
||||
# install jdk
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.9%2B9.1/OpenJDK17U-jdk_x64_windows_hotspot_17.0.9_9.zip -o /tmp/jdk.zip
|
||||
|
||||
unzip /tmp/jdk.zip -d /tmp/jdk \
|
||||
&& cd /tmp/jdk/jdk-* \
|
||||
&& mkdir /jdk \
|
||||
&& cp -r . /jdk
|
||||
name: Set up environment
|
||||
shell: bash.exe
|
||||
- run:
|
||||
command: ./gradlew --info --stacktrace -DtestReportsDir=${HOME}/test-results check
|
||||
name: gradle check
|
||||
@@ -589,6 +627,7 @@ jobs:
|
||||
path: ~/test-results
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
JAVA_HOME: /jdk
|
||||
resource_class: windows.large
|
||||
machine:
|
||||
image: windows-server-2022-gui:current
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.uri@1.0.0#/URI.pkl"
|
||||
|
||||
/// The architecture to use
|
||||
arch: "amd64"|"aarch64"
|
||||
@@ -25,13 +24,11 @@ arch: "amd64"|"aarch64"
|
||||
/// Whether to link to musl. Otherwise, links to glibc.
|
||||
musl: Boolean = false
|
||||
|
||||
javaVersion = "17.0"
|
||||
|
||||
local setupLinuxEnvironment: Config.RunStep =
|
||||
let (jdkVersion = "17.0.9+9")
|
||||
let (muslVersion = "1.2.2")
|
||||
let (zlibVersion = "1.2.13")
|
||||
let (jdkVersionEncoded = URI.encodeComponent(jdkVersion))
|
||||
let (jdkVersionAlt = jdkVersion.replaceLast("+", "_"))
|
||||
let (majorJdkVersion = jdkVersion.split(".").first)
|
||||
new {
|
||||
name = "Set up environment"
|
||||
shell = "#!/bin/bash -exo pipefail"
|
||||
@@ -43,8 +40,8 @@ local setupLinuxEnvironment: Config.RunStep =
|
||||
&& rm -rf /var/cache/dnf
|
||||
|
||||
# install jdk
|
||||
curl -L \
|
||||
https://github.com/adoptium/temurin\#(majorJdkVersion)-binaries/releases/download/jdk-\#(jdkVersionEncoded)/OpenJDK\#(majorJdkVersion)U-jdk_\#(if (arch == "amd64") "x64" else "aarch64")_linux_hotspot_\#(jdkVersionAlt).tar.gz -o /tmp/jdk.tar.gz
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin\#(module.majorJdkVersion)-binaries/releases/download/\#(module.jdkGitHubReleaseName)/OpenJDK\#(module.majorJdkVersion)U-jdk_\#(if (arch == "amd64") "x64" else "aarch64")_linux_hotspot_\#(module.jdkVersionAlt).tar.gz -o /tmp/jdk.tar.gz
|
||||
|
||||
mkdir /jdk \
|
||||
&& cd /jdk \
|
||||
@@ -56,7 +53,7 @@ local setupLinuxEnvironment: Config.RunStep =
|
||||
|
||||
# install zlib
|
||||
if [[ ! -f ~/staticdeps/include/zlib.h ]]; then
|
||||
curl -L https://github.com/madler/zlib/releases/download/v\#(zlibVersion)/zlib-\#(zlibVersion).tar.gz -o /tmp/zlib.tar.gz
|
||||
curl -Lf https://github.com/madler/zlib/releases/download/v\#(zlibVersion)/zlib-\#(zlibVersion).tar.gz -o /tmp/zlib.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_zlib-\#(zlibVersion) \
|
||||
&& cd /tmp/dep_zlib-\#(zlibVersion) \
|
||||
@@ -72,7 +69,7 @@ local setupLinuxEnvironment: Config.RunStep =
|
||||
#"""
|
||||
# install musl
|
||||
if [[ ! -f ~/staticdeps/bin/x86_64-linux-musl-gcc ]]; then
|
||||
curl -L https://musl.libc.org/releases/musl-\#(muslVersion).tar.gz -o /tmp/musl.tar.gz
|
||||
curl -Lf https://musl.libc.org/releases/musl-\#(muslVersion).tar.gz -o /tmp/musl.tar.gz
|
||||
|
||||
mkdir -p /tmp/dep_musl-\#(muslVersion) \
|
||||
&& cd /tmp/dep_musl-\#(muslVersion) \
|
||||
@@ -145,7 +142,7 @@ job {
|
||||
resource_class = "macos.m1.large.gen1"
|
||||
}
|
||||
when (os == "linux") {
|
||||
docker {
|
||||
docker = new Listing<Config.DockerImage> {
|
||||
new {
|
||||
image = if (arch == "aarch64") "arm64v8/oraclelinux:8-slim" else "oraclelinux:8-slim"
|
||||
}
|
||||
@@ -160,5 +157,8 @@ job {
|
||||
image = "windows-server-2022-gui:current"
|
||||
}
|
||||
resource_class = "windows.large"
|
||||
environment {
|
||||
["JAVA_HOME"] = "/jdk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,9 @@ import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
local self = this
|
||||
|
||||
command: String
|
||||
javaVersion = "17.0"
|
||||
|
||||
job {
|
||||
docker {
|
||||
new { image = "cimg/openjdk:17.0" }
|
||||
}
|
||||
}
|
||||
command: String
|
||||
|
||||
os = "linux"
|
||||
|
||||
|
||||
@@ -17,29 +17,9 @@ extends "GradleJob.pkl"
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
|
||||
javaVersion: "17.0"|"21.0"
|
||||
|
||||
os = "linux"
|
||||
|
||||
steps {
|
||||
new Config.RunStep {
|
||||
name = "gradle check"
|
||||
command = "./gradlew \(module.gradleArgs) check"
|
||||
}
|
||||
}
|
||||
|
||||
job {
|
||||
when (os == "linux") {
|
||||
docker {
|
||||
new {
|
||||
image = "cimg/openjdk:\(javaVersion)"
|
||||
}
|
||||
}
|
||||
}
|
||||
when (os == "windows") {
|
||||
machine {
|
||||
image = "windows-server-2022-gui:current"
|
||||
}
|
||||
resource_class = "windows.large"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
abstract module GradleJob
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/com.circleci.v2@1.1.2#/Config.pkl"
|
||||
import "package://pkg.pkl-lang.org/pkl-pantry/pkl.experimental.uri@1.0.3#/URI.pkl"
|
||||
|
||||
/// Whether this is a release build or not.
|
||||
isRelease: Boolean = false
|
||||
@@ -23,6 +24,25 @@ isRelease: Boolean = false
|
||||
/// The OS to run on
|
||||
os: "macOS"|"linux"|"windows"
|
||||
|
||||
/// The version of Java to use.
|
||||
javaVersion: "17.0"|"21.0"
|
||||
|
||||
fixed javaVersionFull =
|
||||
if (javaVersion == "17.0") "17.0.9+9"
|
||||
else "21.0.5+11"
|
||||
|
||||
fixed jdkVersionAlt = javaVersionFull.replaceLast("+", "_")
|
||||
|
||||
fixed majorJdkVersion = javaVersionFull.split(".").first
|
||||
|
||||
fixed jdkGitHubReleaseName =
|
||||
let (ver =
|
||||
// 17.0.9+9 is missing some binaries (see https://github.com/adoptium/adoptium-support/issues/994)
|
||||
if (javaVersionFull == "17.0.9+9" && os == "windows") "jdk-17.0.9+9.1"
|
||||
else "jdk-\(javaVersionFull)"
|
||||
)
|
||||
URI.encodeComponent(ver)
|
||||
|
||||
fixed gradleArgs = new Listing {
|
||||
"--info"
|
||||
"--stacktrace"
|
||||
@@ -37,9 +57,41 @@ steps: Listing<Config.Step>
|
||||
job: Config.Job = new {
|
||||
environment {
|
||||
["LANG"] = "en_US.UTF-8"
|
||||
when (os == "windows") {
|
||||
["JAVA_HOME"] = "/jdk"
|
||||
}
|
||||
}
|
||||
when (os == "linux") {
|
||||
docker {
|
||||
new {
|
||||
image = "cimg/openjdk:\(javaVersion)"
|
||||
}
|
||||
}
|
||||
}
|
||||
when (os == "windows") {
|
||||
machine {
|
||||
image = "windows-server-2022-gui:current"
|
||||
}
|
||||
resource_class = "windows.large"
|
||||
}
|
||||
steps {
|
||||
"checkout"
|
||||
when (os == "windows") {
|
||||
new Config.RunStep {
|
||||
name = "Set up environment"
|
||||
shell = "bash.exe"
|
||||
command = #"""
|
||||
# install jdk
|
||||
curl -Lf \
|
||||
https://github.com/adoptium/temurin\#(majorJdkVersion)-binaries/releases/download/\#(jdkGitHubReleaseName)/OpenJDK\#(majorJdkVersion)U-jdk_x64_windows_hotspot_\#(jdkVersionAlt).zip -o /tmp/jdk.zip
|
||||
|
||||
unzip /tmp/jdk.zip -d /tmp/jdk \
|
||||
&& cd /tmp/jdk/jdk-* \
|
||||
&& mkdir /jdk \
|
||||
&& cp -r . /jdk
|
||||
"""#
|
||||
}
|
||||
}
|
||||
...module.steps
|
||||
new Config.StoreTestResults {
|
||||
path = "~/test-results"
|
||||
|
||||
@@ -23,6 +23,8 @@ command: String
|
||||
|
||||
os = "linux"
|
||||
|
||||
javaVersion = "17.0"
|
||||
|
||||
steps {
|
||||
new Config.RunStep {
|
||||
name = module.name
|
||||
@@ -31,9 +33,3 @@ steps {
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
job {
|
||||
docker {
|
||||
new { image = "cimg/openjdk:17.0" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
:uri-jenv: https://www.jenv.be
|
||||
:uri-intellij: https://www.jetbrains.com/idea/download/
|
||||
:uri-jdk: https://adoptopenjdk.net/releases.html?variant=openjdk17
|
||||
:uri-native-prerequisites: https://www.graalvm.org/latest/getting-started/windows/#prerequisites-for-native-image-on-windows
|
||||
:uri-native-prerequisites-linux: https://www.graalvm.org/latest/getting-started/linux/#prerequisites-for-native-image-on-linux
|
||||
:uri-native-prerequisites-windows: https://www.graalvm.org/latest/getting-started/windows/#prerequisites-for-native-image-on-windows
|
||||
|
||||
== Setup
|
||||
|
||||
@@ -25,12 +26,20 @@ Enable _jenv_ plugins for better handling by `gradle`:
|
||||
jenv enable-plugin gradle
|
||||
jenv enable-plugin export
|
||||
----
|
||||
. (optional) If you've named the original apple/pkl git repository something other than `origin`, set env var `PKL_ORIGINAL_REMOTE_NAME` to that name in your `.bashrc`, `.zshrc`, `config.fish` or however you manage your local environment.
|
||||
+
|
||||
This will allow spotless to pick the correct starting branch when formatting source code files.
|
||||
Otherwise, you might see that _every_ file has its copyright year updated.
|
||||
|
||||
=== Additional Linux Setup
|
||||
. (optional) To build the native executable (`./gradlew buildNative`),
|
||||
install {uri-native-prerequisites-linux}[Prerequisites For Native Image on Linux].
|
||||
|
||||
=== Additional Windows Setup
|
||||
. (optional) Go to `System->For developers` and enable `Developer Mode`.
|
||||
Otherwise, some tests may fail due to insufficient file system privileges.
|
||||
. (optional) To build the native executable (`./gradlew buildNative`),
|
||||
install {uri-native-prerequisites}[Prerequisites For Native Image on Windows].
|
||||
install {uri-native-prerequisites-windows}[Prerequisites For Native Image on Windows].
|
||||
|
||||
== Common Build Commands
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright © 2024 Apple Inc. and the Pkl project authors
|
||||
Copyright © 2024-2025 Apple Inc. and the Pkl project authors
|
||||
|
||||
|
||||
Portions of this software were originally based on 'SnakeYAML' developed by Andrey Somov.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -132,7 +132,11 @@ private fun KotlinGradleExtension.configureFormatter() {
|
||||
licenseHeaderFile(licenseHeaderFile, "([a-zA-Z]|@file|//)")
|
||||
}
|
||||
|
||||
val originalRemoteName = System.getenv("PKL_ORIGINAL_REMOTE_NAME") ?: "origin"
|
||||
|
||||
spotless {
|
||||
ratchetFrom = "$originalRemoteName/main"
|
||||
|
||||
// When building root project, format buildSrc files too.
|
||||
// We need this because buildSrc is not a subproject of the root project, so a top-level
|
||||
// `spotlessApply` will not trigger `buildSrc:spotlessApply`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © $YEAR Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © $YEAR Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: main
|
||||
title: Main Project
|
||||
version: 0.27.0-dev
|
||||
prerelease: true
|
||||
version: 0.27.2
|
||||
prerelease: false
|
||||
nav:
|
||||
- nav.adoc
|
||||
|
||||
20
docs/modules/ROOT/pages/evolution-and-roadmap.adoc
Normal file
20
docs/modules/ROOT/pages/evolution-and-roadmap.adoc
Normal file
@@ -0,0 +1,20 @@
|
||||
= Evolution and Roadmap
|
||||
|
||||
:uri-pkl-roadmap: https://github.com/orgs/apple/projects/12/views/1
|
||||
:uri-pkl-evolution: https://github.com/apple/pkl-evolution
|
||||
|
||||
== Evolution
|
||||
|
||||
Sometimes, a change to Pkl is large enough that it makes sense to create a proposal for the change so that it can be discussed in detail and vetted.
|
||||
|
||||
Pkl has a process for managing such designs in a repository called {uri-pkl-evolution}[Pkl Evolutiuon].
|
||||
|
||||
== Roadmap
|
||||
|
||||
To discover what might be coming in future versions, reference the {uri-pkl-roadmap}[Pkl Roadmap] project on GitHub.
|
||||
|
||||
The roadmap describes estimates.
|
||||
The Pkl team aims to cut a release in February, June, and October of each year.
|
||||
If an item is not complete by the release cutoff date, the roadmap item may be bumped to the next release.
|
||||
|
||||
Additionally, as priorities change, it is possible that items can be moved around, or backlogged.
|
||||
@@ -3,10 +3,10 @@
|
||||
// the following attributes must be updated immediately before a release
|
||||
|
||||
// pkl version corresponding to current git commit without -dev suffix or git hash
|
||||
:pkl-version-no-suffix: 0.27.0
|
||||
:pkl-version-no-suffix: 0.27.2
|
||||
// tells whether pkl version corresponding to current git commit
|
||||
// is a release version (:is-release-version: '') or dev version (:!is-release-version:)
|
||||
:!is-release-version:
|
||||
:is-release-version: ''
|
||||
|
||||
// the remaining attributes do not need to be updated regularly
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
= Pkl 0.27 Release Notes
|
||||
:version: 0.27
|
||||
:version-minor: 0.27.0
|
||||
:version-minor: 0.27.2
|
||||
:release-date: November 5th, 2024
|
||||
|
||||
include::ROOT:partial$component-attributes.adoc[]
|
||||
@@ -377,7 +377,7 @@ These are:
|
||||
|
||||
The `String` to `Number` converter methods, for example, {uri-stdlib-StringToInt}[`String.toInt()`], can now handle underscore separators (https://github.com/apple/pkl/pull/578[#578], https://github.com/apple/pkl/pull/580[#580]).
|
||||
|
||||
This better aligns with the source code representation of file:///Users/danielchao/code/apple/pkl-lang.org/build/local/main/current/language-reference/index.html#integers[number literals].
|
||||
This better aligns with the source code representation of xref:language-reference:index.adoc#integers[number literals].
|
||||
|
||||
[source,pkl]
|
||||
----
|
||||
|
||||
@@ -1,6 +1,44 @@
|
||||
= Changelog
|
||||
include::ROOT:partial$component-attributes.adoc[]
|
||||
|
||||
[[release-0.27.2]]
|
||||
== 0.27.2 (2025-01-22)
|
||||
|
||||
=== Fixes
|
||||
|
||||
* Fixes issues where server mode message decoding might result in null pointer exceptions (https://github.com/apple/pkl/pull/853[#853], https://github.com/apple/pkl/pull/882[#882]).
|
||||
* Fixes an issue where the test report outputs decimal numbers using local-specific decimals (https://github.com/apple/pkl/pull/868[#868]).
|
||||
* Fixes an issue where the native executables might not run on some environments, resulting in an error like "Fatal error: Failed to create the main Isolate" (https://github.com/apple/pkl/pull/875[#875]).
|
||||
|
||||
=== Contributors ❤️
|
||||
|
||||
Thank you to all the contributors for this release!
|
||||
|
||||
* link:https://github.com/HT154[@HT154]
|
||||
* link:https://github.com/StefMa[@StefMa]
|
||||
|
||||
[[release-0.27.1]]
|
||||
== 0.27.1 (2024-12-06)
|
||||
|
||||
=== Fixes
|
||||
|
||||
- Fixes a broken "number literals" link in the 0.27 release notes (https://github.com/apple/pkl/pull/784[#784]).
|
||||
- Fixes a possible deadlock during external reader process close (https://github.com/apple/pkl/pull/786[#786]).
|
||||
- Fixes counting elements with computed indices multiple times in length computation of listings (https://github.com/apple/pkl/pull/797[#797]).
|
||||
- Fixes non Pkl modules being reported in GatherImports task, leading to plugin failures (https://github.com/apple/pkl/pull/821[#821]).
|
||||
- Fixes a problem where the delegate chain of type casts for Listing/Mapping get unreasonably big, even though the type nodes are the same, which may lead to a stack overflow or performance degradation (https://github.com/apple/pkl/pull/826[#826]).
|
||||
- Fixes incorrect scoping of type variables in lazy Listing/Mapping type checking in cross-module typealiases (https://github.com/apple/pkl/pull/789[#789]).
|
||||
- Fixes regression in type checking logic for Listing/Mapping (https://github.com/apple/pkl/pull/789[#789]).
|
||||
|
||||
=== Contributors ❤️
|
||||
|
||||
Thank you to all the contributors for this release!
|
||||
|
||||
* link:https://github.com/GUI[@GUI]
|
||||
* link:https://github.com/HT154[@HT154]
|
||||
* link:https://github.com/odenix[@odenix] (formerly @translatenix)
|
||||
|
||||
|
||||
[[release-0.27.0]]
|
||||
== 0.27.0 (2024-11-05)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
= Release Notes
|
||||
|
||||
The Pkl team aims to release a new version of Pkl in February, June, and October of each year.
|
||||
|
||||
* xref:0.27.adoc[0.27 Release Notes]
|
||||
* xref:0.26.adoc[0.26 Release Notes]
|
||||
* xref:0.25.adoc[0.25 Release Notes]
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
* xref:ROOT:examples.adoc[Examples]
|
||||
|
||||
* xref:ROOT:evolution-and-roadmap.adoc[Evolution and Roadmap]
|
||||
|
||||
* xref:release-notes:index.adoc[Release Notes]
|
||||
** xref:release-notes:0.27.adoc[0.27 Release Notes]
|
||||
** xref:release-notes:0.26.adoc[0.26 Release Notes]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# suppress inspection "UnusedProperty" for whole file
|
||||
|
||||
group=org.pkl-lang
|
||||
version=0.27.0
|
||||
version=0.27.2
|
||||
|
||||
# google-java-format requires jdk.compiler exports
|
||||
org.gradle.jvmargs= \
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
"catalogs": {},
|
||||
"aliases": {
|
||||
"pkl": {
|
||||
"script-ref": "org.pkl-lang:pkl-cli-java:0.26.3",
|
||||
"script-ref": "org.pkl-lang:pkl-cli-java:0.27.2",
|
||||
"java-agents": []
|
||||
},
|
||||
"pkl-codegen-java": {
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-java:0.26.3",
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-java:0.27.2",
|
||||
"java-agents": []
|
||||
},
|
||||
"pkl-codegen-kotlin": {
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.26.3",
|
||||
"script-ref": "org.pkl-lang:pkl-codegen-kotlin:0.27.2",
|
||||
"java-agents": []
|
||||
}
|
||||
},
|
||||
"templates": {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -276,7 +276,12 @@ val linuxExecutableAarch64: TaskProvider<Exec> by
|
||||
dependsOn(":installGraalVmAarch64")
|
||||
configureExecutable(
|
||||
buildInfo.graalVmAarch64,
|
||||
layout.buildDirectory.file("executable/pkl-linux-aarch64")
|
||||
layout.buildDirectory.file("executable/pkl-linux-aarch64"),
|
||||
listOf(
|
||||
// Ensure compatibility for kernels with page size set to 4k, 16k and 64k
|
||||
// (e.g. Raspberry Pi 5, Asahi Linux)
|
||||
"-H:PageSize=65536"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.io.StringWriter
|
||||
import java.io.Writer
|
||||
import java.net.URI
|
||||
import java.nio.file.Path
|
||||
import java.util.Locale
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatCode
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -487,6 +488,50 @@ class CliTestRunnerTest {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `CliTestRunner locale independence test`(@TempDir tempDir: Path) {
|
||||
val originalLocale = Locale.getDefault()
|
||||
Locale.setDefault(Locale.GERMANY)
|
||||
|
||||
try {
|
||||
val code =
|
||||
"""
|
||||
amends "pkl:test"
|
||||
|
||||
facts {
|
||||
["localeTest"] {
|
||||
1 == 1
|
||||
}
|
||||
}
|
||||
"""
|
||||
.trimIndent()
|
||||
val input = tempDir.resolve("test.pkl").writeString(code).toString()
|
||||
val out = StringWriter()
|
||||
val err = StringWriter()
|
||||
val opts =
|
||||
CliBaseOptions(sourceModules = listOf(input.toUri()), settings = URI("pkl:settings"))
|
||||
val testOpts = CliTestOptions()
|
||||
val runner = CliTestRunner(opts, testOpts, consoleWriter = out, errWriter = err)
|
||||
runner.run()
|
||||
|
||||
assertThat(out.toString().stripFileAndLines(tempDir))
|
||||
.isEqualTo(
|
||||
"""
|
||||
module test
|
||||
facts
|
||||
✔ localeTest
|
||||
|
||||
100.0% tests pass [1 passed], 100.0% asserts pass [1 passed]
|
||||
|
||||
"""
|
||||
.trimIndent()
|
||||
)
|
||||
assertThat(err.toString()).isEqualTo("")
|
||||
} finally {
|
||||
Locale.setDefault(originalLocale)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.stripFileAndLines(tmpDir: Path): String {
|
||||
// handle platform differences in handling of file URIs
|
||||
// (file:/// on *nix vs. file:/ on Windows)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ import java.nio.file.Path
|
||||
import java.util.stream.Collectors
|
||||
import kotlin.io.path.*
|
||||
import org.assertj.core.api.Assertions.fail
|
||||
import org.opentest4j.AssertionFailedError
|
||||
import org.pkl.commons.*
|
||||
|
||||
object FileTestUtils {
|
||||
@@ -110,5 +111,11 @@ data class SnippetOutcome(val expectedOutFile: Path, val actual: String, val suc
|
||||
}
|
||||
|
||||
private fun failWithDiff(message: String): Nothing =
|
||||
throw PklAssertionFailedError(message, expected, actual)
|
||||
if (System.getProperty("sun.java.command", "").contains("intellij")) {
|
||||
// IntelliJ only shows diffs for AssertionFailedError
|
||||
throw AssertionFailedError(message, expected, actual)
|
||||
} else {
|
||||
// Gradle test logging/report only shows diffs for PklAssertionFailedError
|
||||
throw PklAssertionFailedError(message, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -1221,7 +1221,7 @@ public final class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
member.initConstantValue(constantNode);
|
||||
} else {
|
||||
member.initMemberNode(
|
||||
new UntypedObjectMemberNode(
|
||||
ElementOrEntryNodeGen.create(
|
||||
language, scope.buildFrameDescriptor(), member, elementNode));
|
||||
}
|
||||
|
||||
@@ -1278,7 +1278,7 @@ public final class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
member.initConstantValue(constantNode);
|
||||
} else {
|
||||
member.initMemberNode(
|
||||
new UntypedObjectMemberNode(
|
||||
ElementOrEntryNodeGen.create(
|
||||
language, scope.buildFrameDescriptor(), member, valueNode));
|
||||
}
|
||||
} else { // ["key"] { ... }
|
||||
@@ -1287,7 +1287,7 @@ public final class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
objectBodyCtxs,
|
||||
new ReadSuperEntryNode(unavailableSourceSection(), new GetMemberKeyNode()));
|
||||
member.initMemberNode(
|
||||
new UntypedObjectMemberNode(
|
||||
ElementOrEntryNodeGen.create(
|
||||
language, scope.buildFrameDescriptor(), member, objectBody));
|
||||
}
|
||||
|
||||
@@ -2446,6 +2446,7 @@ public final class AstBuilder extends AbstractAstBuilder<Object> {
|
||||
|
||||
return new UnresolvedTypeNode.Parameterized(
|
||||
createSourceSection(ctx),
|
||||
language,
|
||||
doVisitTypeName(idCtx),
|
||||
argCtx.ts.stream().map(this::visitType).toArray(UnresolvedTypeNode[]::new));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -103,7 +103,7 @@ public abstract class GeneratorPredicateMemberNode extends GeneratorMemberNode {
|
||||
var callTarget = member.getCallTarget();
|
||||
value = callTarget.call(parent, owner, key);
|
||||
}
|
||||
owner.setCachedValue(key, value, member);
|
||||
owner.setCachedValue(key, value);
|
||||
}
|
||||
|
||||
frame.setAuxiliarySlot(customThisSlot, value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -43,15 +43,15 @@ public abstract class EntriesLiteralNode extends SpecializedObjectLiteralNode {
|
||||
@Children private final ExpressionNode[] keyNodes;
|
||||
private final ObjectMember[] values;
|
||||
|
||||
public EntriesLiteralNode(
|
||||
protected EntriesLiteralNode(
|
||||
SourceSection sourceSection,
|
||||
VmLanguage language,
|
||||
// contains local properties and default property (if present)
|
||||
// does *not* contain entries with constant keys to maintain definition order of entries
|
||||
String qualifiedScopeName,
|
||||
boolean isCustomThisScope,
|
||||
@Nullable FrameDescriptor parametersDescriptor,
|
||||
UnresolvedTypeNode[] parameterTypes,
|
||||
// contains local properties and default property (if present)
|
||||
// does *not* contain entries with constant keys to maintain definition order of entries
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members,
|
||||
ExpressionNode[] keyNodes,
|
||||
ObjectMember[] values) {
|
||||
@@ -103,7 +103,8 @@ public abstract class EntriesLiteralNode extends SpecializedObjectLiteralNode {
|
||||
frame.materialize(),
|
||||
parent,
|
||||
createListMembers(frame, parent.getLength()),
|
||||
parent.getLength() + keyNodes.length);
|
||||
// `[x] = y` overrides existing element and doesn't increase length
|
||||
parent.getLength());
|
||||
}
|
||||
|
||||
@Specialization
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -71,7 +71,7 @@ public final class ReadLocalPropertyNode extends ExpressionNode {
|
||||
|
||||
if (result == null) {
|
||||
result = callNode.call(objReceiver, owner, property.getName());
|
||||
objReceiver.setCachedValue(property, result, property);
|
||||
objReceiver.setCachedValue(property, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -184,12 +184,12 @@ public final class ResolveVariableNode extends ExpressionNode {
|
||||
if (member != null) {
|
||||
var constantValue = member.getConstantValue();
|
||||
if (constantValue != null) {
|
||||
baseModule.setCachedValue(variableName, constantValue, member);
|
||||
baseModule.setCachedValue(variableName, constantValue);
|
||||
return new ConstantValueNode(sourceSection, constantValue);
|
||||
}
|
||||
|
||||
var computedValue = member.getCallTarget().call(baseModule, baseModule);
|
||||
baseModule.setCachedValue(variableName, computedValue, member);
|
||||
baseModule.setCachedValue(variableName, computedValue);
|
||||
return new ConstantValueNode(sourceSection, computedValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.core.ast.member;
|
||||
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Cached.Shared;
|
||||
import com.oracle.truffle.api.dsl.Executed;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import org.pkl.core.ast.ExpressionNode;
|
||||
import org.pkl.core.ast.expression.primary.GetReceiverNode;
|
||||
import org.pkl.core.runtime.VmDynamic;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmListing;
|
||||
import org.pkl.core.runtime.VmMapping;
|
||||
import org.pkl.core.runtime.VmUtils;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
/** Equivalent of {@link TypedPropertyNode} for elements/entries. */
|
||||
public abstract class ElementOrEntryNode extends RegularMemberNode {
|
||||
@Child @Executed protected ExpressionNode receiverNode = new GetReceiverNode();
|
||||
|
||||
protected ElementOrEntryNode(
|
||||
@Nullable VmLanguage language,
|
||||
FrameDescriptor descriptor,
|
||||
ObjectMember member,
|
||||
ExpressionNode bodyNode) {
|
||||
|
||||
super(language, descriptor, member, bodyNode);
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected Object evalListing(
|
||||
VirtualFrame frame,
|
||||
VmListing receiver,
|
||||
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
||||
var result = executeBody(frame);
|
||||
return VmUtils.shouldRunTypeCheck(frame)
|
||||
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null, null)
|
||||
: result;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected Object evalMapping(
|
||||
VirtualFrame frame,
|
||||
VmMapping receiver,
|
||||
@Cached("create()") @Shared("callNode") IndirectCallNode callNode) {
|
||||
var result = executeBody(frame);
|
||||
return VmUtils.shouldRunTypeCheck(frame)
|
||||
? receiver.executeTypeCasts(result, VmUtils.getOwner(frame), callNode, null, null)
|
||||
: result;
|
||||
}
|
||||
|
||||
@Specialization
|
||||
protected Object evalDynamic(VirtualFrame frame, VmDynamic ignored) {
|
||||
return executeBody(frame);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@ import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
/** Performs a typecast on a Mapping entry value, or a Listing element. */
|
||||
public class ListingOrMappingTypeCastNode extends PklRootNode {
|
||||
public final class ListingOrMappingTypeCastNode extends PklRootNode {
|
||||
|
||||
@Child private TypeNode typeNode;
|
||||
private final String qualifiedName;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -73,7 +73,7 @@ public abstract class ResolveDeclaredTypeNode extends ExpressionNode {
|
||||
var result = module.getCachedValue(importName);
|
||||
if (result == null) {
|
||||
result = callNode.call(member.getCallTarget(), module, module, importName);
|
||||
module.setCachedValue(importName, result, member);
|
||||
module.setCachedValue(importName, result);
|
||||
}
|
||||
return (VmTyped) result;
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public abstract class ResolveDeclaredTypeNode extends ExpressionNode {
|
||||
var result = module.getCachedValue(typeName);
|
||||
if (result == null) {
|
||||
result = callNode.call(member.getCallTarget(), module, module, typeName);
|
||||
module.setCachedValue(typeName, result, member);
|
||||
module.setCachedValue(typeName, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Cached;
|
||||
import com.oracle.truffle.api.dsl.Fallback;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.frame.Frame;
|
||||
import com.oracle.truffle.api.frame.FrameDescriptor;
|
||||
import com.oracle.truffle.api.frame.FrameSlotKind;
|
||||
import com.oracle.truffle.api.frame.VirtualFrame;
|
||||
@@ -161,7 +162,11 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
/** Tells if this typenode is the same typecheck as the other typenode. */
|
||||
public abstract boolean isEquivalentTo(TypeNode other);
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
return this == other || doIsEquivalentTo(other);
|
||||
}
|
||||
|
||||
protected abstract boolean doIsEquivalentTo(TypeNode other);
|
||||
|
||||
public @Nullable VmClass getVmClass() {
|
||||
return null;
|
||||
@@ -304,7 +309,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof UnknownTypeNode;
|
||||
}
|
||||
|
||||
@@ -371,7 +376,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof NothingTypeNode;
|
||||
}
|
||||
|
||||
@@ -408,7 +413,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof FinalModuleTypeNode finalModuleTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -460,7 +465,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof NonFinalModuleTypeNode nonFinalModuleTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -496,7 +501,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof StringLiteralTypeNode stringLiteralTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -551,7 +556,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof TypedTypeNode;
|
||||
}
|
||||
|
||||
@@ -586,7 +591,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof DynamicTypeNode;
|
||||
}
|
||||
|
||||
@@ -636,7 +641,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof FinalClassTypeNode finalClassTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -705,7 +710,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof NonFinalClassTypeNode nonFinalClassTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -772,7 +777,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof NullableTypeNode nullableTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -842,7 +847,7 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
@ExplodeLoop
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof UnionTypeNode unionTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1016,7 +1021,7 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof UnionOfStringLiteralsTypeNode unionOfStringLiteralsTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1092,7 +1097,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1223,7 +1228,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof ListTypeNode listTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1268,7 +1273,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof SetTypeNode setTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1360,7 +1365,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof MapTypeNode mapTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1414,8 +1419,9 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
public static final class ListingTypeNode extends ListingOrMappingTypeNode {
|
||||
public ListingTypeNode(SourceSection sourceSection, TypeNode valueTypeNode) {
|
||||
super(sourceSection, null, valueTypeNode);
|
||||
public ListingTypeNode(
|
||||
SourceSection sourceSection, VmLanguage language, TypeNode valueTypeNode) {
|
||||
super(sourceSection, language, null, valueTypeNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1423,7 +1429,17 @@ public abstract class TypeNode extends PklNode {
|
||||
if (!(value instanceof VmListing vmListing)) {
|
||||
throw typeMismatch(value, BaseModule.getListingClass());
|
||||
}
|
||||
return doTypeCast(frame, vmListing);
|
||||
if (vmListing.isValueTypeKnownSubtypeOf(valueTypeNode)) {
|
||||
return vmListing;
|
||||
}
|
||||
return new VmListing(
|
||||
vmListing.getEnclosingFrame(),
|
||||
vmListing,
|
||||
EconomicMaps.emptyMap(),
|
||||
vmListing.getLength(),
|
||||
getValueTypeCastNode(),
|
||||
VmUtils.getReceiver(frame),
|
||||
VmUtils.getOwner(frame));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1451,7 +1467,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof ListingTypeNode listingTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1466,9 +1482,12 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
public static final class MappingTypeNode extends ListingOrMappingTypeNode {
|
||||
public MappingTypeNode(
|
||||
SourceSection sourceSection, TypeNode keyTypeNode, TypeNode valueTypeNode) {
|
||||
SourceSection sourceSection,
|
||||
VmLanguage language,
|
||||
TypeNode keyTypeNode,
|
||||
TypeNode valueTypeNode) {
|
||||
|
||||
super(sourceSection, keyTypeNode, valueTypeNode);
|
||||
super(sourceSection, language, keyTypeNode, valueTypeNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1478,7 +1497,16 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
// execute type checks on mapping keys
|
||||
doEagerCheck(frame, vmMapping, false, true);
|
||||
return doTypeCast(frame, vmMapping);
|
||||
if (vmMapping.isValueTypeKnownSubtypeOf(valueTypeNode)) {
|
||||
return vmMapping;
|
||||
}
|
||||
return new VmMapping(
|
||||
vmMapping.getEnclosingFrame(),
|
||||
vmMapping,
|
||||
EconomicMaps.emptyMap(),
|
||||
getValueTypeCastNode(),
|
||||
VmUtils.getReceiver(frame),
|
||||
VmUtils.getOwner(frame));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1509,7 +1537,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof MappingTypeNode mappingTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1526,17 +1554,22 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
public abstract static class ListingOrMappingTypeNode extends ObjectSlotTypeNode {
|
||||
private final VmLanguage language;
|
||||
@Child protected @Nullable TypeNode keyTypeNode;
|
||||
@Child protected TypeNode valueTypeNode;
|
||||
@Child @Nullable protected ListingOrMappingTypeCastNode listingOrMappingTypeCastNode;
|
||||
@Child @Nullable protected ListingOrMappingTypeCastNode valueTypeCastNode;
|
||||
|
||||
private final boolean skipKeyTypeChecks;
|
||||
private final boolean skipValueTypeChecks;
|
||||
|
||||
protected ListingOrMappingTypeNode(
|
||||
SourceSection sourceSection, @Nullable TypeNode keyTypeNode, TypeNode valueTypeNode) {
|
||||
SourceSection sourceSection,
|
||||
VmLanguage language,
|
||||
@Nullable TypeNode keyTypeNode,
|
||||
TypeNode valueTypeNode) {
|
||||
|
||||
super(sourceSection);
|
||||
this.language = language;
|
||||
this.keyTypeNode = keyTypeNode;
|
||||
this.valueTypeNode = valueTypeNode;
|
||||
|
||||
@@ -1556,17 +1589,14 @@ public abstract class TypeNode extends PklNode {
|
||||
return valueTypeNode;
|
||||
}
|
||||
|
||||
protected ListingOrMappingTypeCastNode getListingOrMappingTypeCastNode() {
|
||||
if (listingOrMappingTypeCastNode == null) {
|
||||
protected ListingOrMappingTypeCastNode getValueTypeCastNode() {
|
||||
if (valueTypeCastNode == null) {
|
||||
CompilerDirectives.transferToInterpreterAndInvalidate();
|
||||
listingOrMappingTypeCastNode =
|
||||
valueTypeCastNode =
|
||||
new ListingOrMappingTypeCastNode(
|
||||
VmLanguage.get(this),
|
||||
getRootNode().getFrameDescriptor(),
|
||||
valueTypeNode,
|
||||
getRootNode().getName());
|
||||
language, new FrameDescriptor(), valueTypeNode, getRootNode().getName());
|
||||
}
|
||||
return listingOrMappingTypeCastNode;
|
||||
return valueTypeCastNode;
|
||||
}
|
||||
|
||||
// either (if defaultMemberValue != null):
|
||||
@@ -1647,15 +1677,6 @@ public abstract class TypeNode extends PklNode {
|
||||
EconomicMaps.of(Identifier.DEFAULT, defaultMember));
|
||||
}
|
||||
|
||||
protected <T extends VmListingOrMapping<T>> T doTypeCast(VirtualFrame frame, T original) {
|
||||
// optimization: don't create new object if the original already has the same typecheck, or if
|
||||
// this typecheck is a no-op.
|
||||
if (isNoopTypeCheck() || original.hasSameChecksAs(valueTypeNode)) {
|
||||
return original;
|
||||
}
|
||||
return original.withCheckedMembers(getListingOrMappingTypeCastNode(), frame.materialize());
|
||||
}
|
||||
|
||||
protected void doEagerCheck(VirtualFrame frame, VmObject object) {
|
||||
doEagerCheck(frame, object, skipKeyTypeChecks, skipValueTypeChecks);
|
||||
}
|
||||
@@ -1700,7 +1721,7 @@ public abstract class TypeNode extends PklNode {
|
||||
var callTarget = member.getCallTarget();
|
||||
memberValue = callTarget.call(object, owner, memberKey);
|
||||
}
|
||||
object.setCachedValue(memberKey, memberValue, member);
|
||||
object.setCachedValue(memberKey, memberValue);
|
||||
}
|
||||
valueTypeNode.executeEagerly(frame, memberValue);
|
||||
}
|
||||
@@ -1748,7 +1769,7 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
@ExplodeLoop
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof FunctionTypeNode functionTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1845,7 +1866,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof FunctionClassTypeNode functionClassTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1883,7 +1904,7 @@ public abstract class TypeNode extends PklNode {
|
||||
|
||||
@Override
|
||||
@ExplodeLoop
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof FunctionNClassTypeNode functionNClassTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1986,7 +2007,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof PairTypeNode pairTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -2043,7 +2064,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if (!(other instanceof VarArgsTypeNode varArgsTypeNode)) {
|
||||
return false;
|
||||
}
|
||||
@@ -2095,7 +2116,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof TypeVariableNode;
|
||||
}
|
||||
|
||||
@@ -2135,7 +2156,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof NonNullTypeAliasTypeNode;
|
||||
}
|
||||
|
||||
@@ -2184,7 +2205,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof UIntTypeAliasTypeNode aliasTypeNode && mask == aliasTypeNode.mask;
|
||||
}
|
||||
|
||||
@@ -2228,7 +2249,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof Int8TypeAliasTypeNode;
|
||||
}
|
||||
|
||||
@@ -2272,7 +2293,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof Int16TypeAliasTypeNode;
|
||||
}
|
||||
|
||||
@@ -2316,7 +2337,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof Int32TypeAliasTypeNode;
|
||||
}
|
||||
|
||||
@@ -2387,14 +2408,14 @@ public abstract class TypeNode extends PklNode {
|
||||
public Object execute(VirtualFrame frame, Object value) {
|
||||
var prevOwner = VmUtils.getOwner(frame);
|
||||
var prevReceiver = VmUtils.getReceiver(frame);
|
||||
VmUtils.setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
VmUtils.setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
|
||||
try {
|
||||
return aliasedTypeNode.execute(frame, value);
|
||||
} finally {
|
||||
VmUtils.setOwner(frame, prevOwner);
|
||||
VmUtils.setReceiver(frame, prevReceiver);
|
||||
setOwner(frame, prevOwner);
|
||||
setReceiver(frame, prevReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2403,14 +2424,14 @@ public abstract class TypeNode extends PklNode {
|
||||
public Object executeAndSet(VirtualFrame frame, Object value) {
|
||||
var prevOwner = VmUtils.getOwner(frame);
|
||||
var prevReceiver = VmUtils.getReceiver(frame);
|
||||
VmUtils.setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
VmUtils.setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
|
||||
try {
|
||||
return aliasedTypeNode.executeAndSet(frame, value);
|
||||
} finally {
|
||||
VmUtils.setOwner(frame, prevOwner);
|
||||
VmUtils.setReceiver(frame, prevReceiver);
|
||||
setOwner(frame, prevOwner);
|
||||
setReceiver(frame, prevReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2419,14 +2440,14 @@ public abstract class TypeNode extends PklNode {
|
||||
public Object executeEagerlyAndSet(VirtualFrame frame, Object value) {
|
||||
var prevOwner = VmUtils.getOwner(frame);
|
||||
var prevReceiver = VmUtils.getReceiver(frame);
|
||||
VmUtils.setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
VmUtils.setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
setOwner(frame, VmUtils.getOwner(typeAlias.getEnclosingFrame()));
|
||||
setReceiver(frame, VmUtils.getReceiver(typeAlias.getEnclosingFrame()));
|
||||
|
||||
try {
|
||||
return aliasedTypeNode.executeEagerlyAndSet(frame, value);
|
||||
} finally {
|
||||
VmUtils.setOwner(frame, prevOwner);
|
||||
VmUtils.setReceiver(frame, prevReceiver);
|
||||
setOwner(frame, prevOwner);
|
||||
setReceiver(frame, prevReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2471,7 +2492,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
if ((other instanceof TypeAliasTypeNode typeAliasTypeNode)) {
|
||||
return aliasedTypeNode.isEquivalentTo(typeAliasTypeNode.aliasedTypeNode);
|
||||
}
|
||||
@@ -2498,6 +2519,22 @@ public abstract class TypeNode extends PklNode {
|
||||
protected boolean isParametric() {
|
||||
return typeArgumentNodes.length > 0;
|
||||
}
|
||||
|
||||
// Note that mutating a frame's receiver and owner argument is very risky
|
||||
// because any VmObject instantiated within the same root node execution
|
||||
// holds a reference to (not immutable snapshot of) the frame
|
||||
// via VmObjectLike.enclosingFrame.
|
||||
// *Maybe* this works out for TypeAliasTypeNode because an object instantiated
|
||||
// within a type constraint doesn't escape the constraint expression.
|
||||
// If mutating receiver and owner can't be avoided, it would be safer
|
||||
// to have VmObjectLike store them directly instead of storing enclosingFrame.
|
||||
private static void setReceiver(Frame frame, Object receiver) {
|
||||
frame.getArguments()[0] = receiver;
|
||||
}
|
||||
|
||||
private static void setOwner(Frame frame, VmObjectLike owner) {
|
||||
frame.getArguments()[1] = owner;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ConstrainedTypeNode extends TypeNode {
|
||||
@@ -2581,7 +2618,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
// consider constrained types as always different
|
||||
return false;
|
||||
}
|
||||
@@ -2622,7 +2659,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof AnyTypeNode;
|
||||
}
|
||||
|
||||
@@ -2650,7 +2687,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof StringTypeNode;
|
||||
}
|
||||
|
||||
@@ -2714,7 +2751,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof NumberTypeNode;
|
||||
}
|
||||
|
||||
@@ -2742,7 +2779,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof IntTypeNode;
|
||||
}
|
||||
|
||||
@@ -2787,7 +2824,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof FloatTypeNode;
|
||||
}
|
||||
|
||||
@@ -2832,7 +2869,7 @@ public abstract class TypeNode extends PklNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(TypeNode other) {
|
||||
public boolean doIsEquivalentTo(TypeNode other) {
|
||||
return other instanceof BooleanTypeNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -197,14 +197,17 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
}
|
||||
|
||||
public static final class Parameterized extends UnresolvedTypeNode {
|
||||
private final VmLanguage language;
|
||||
@Child private ExpressionNode resolveTypeNode;
|
||||
@Children private final UnresolvedTypeNode[] typeArgumentNodes;
|
||||
|
||||
public Parameterized(
|
||||
SourceSection sourceSection,
|
||||
VmLanguage language,
|
||||
ExpressionNode resolveTypeNode,
|
||||
UnresolvedTypeNode[] typeArgumentNodes) {
|
||||
super(sourceSection);
|
||||
this.language = language;
|
||||
this.resolveTypeNode = resolveTypeNode;
|
||||
this.typeArgumentNodes = typeArgumentNodes;
|
||||
}
|
||||
@@ -238,12 +241,13 @@ public abstract class UnresolvedTypeNode extends PklNode {
|
||||
}
|
||||
|
||||
if (clazz.isListingClass()) {
|
||||
return new ListingTypeNode(sourceSection, typeArgumentNodes[0].execute(frame));
|
||||
return new ListingTypeNode(sourceSection, language, typeArgumentNodes[0].execute(frame));
|
||||
}
|
||||
|
||||
if (clazz.isMappingClass()) {
|
||||
return new MappingTypeNode(
|
||||
sourceSection,
|
||||
language,
|
||||
typeArgumentNodes[0].execute(frame),
|
||||
typeArgumentNodes[1].execute(frame));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,17 +17,16 @@ package org.pkl.core.externalreader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import org.pkl.core.Duration;
|
||||
import org.pkl.core.evaluatorSettings.PklEvaluatorSettings.ExternalReader;
|
||||
import org.pkl.core.externalreader.ExternalReaderMessages.*;
|
||||
import org.pkl.core.messaging.MessageTransport;
|
||||
@@ -108,7 +107,9 @@ final class ExternalReaderProcessImpl implements ExternalReaderProcess {
|
||||
// This relies on Java/OS behavior around PATH resolution, absolute/relative paths, etc.
|
||||
var command = new ArrayList<String>();
|
||||
command.add(spec.executable());
|
||||
command.addAll(spec.arguments());
|
||||
if (spec.arguments() != null) {
|
||||
command.addAll(spec.arguments());
|
||||
}
|
||||
|
||||
var builder = new ProcessBuilder(command);
|
||||
builder.redirectError(Redirect.INHERIT); // inherit stderr from this pkl process
|
||||
@@ -152,40 +153,23 @@ final class ExternalReaderProcessImpl implements ExternalReaderProcess {
|
||||
@Override
|
||||
public void close() {
|
||||
synchronized (lock) {
|
||||
if (closed) return;
|
||||
closed = true;
|
||||
if (process == null || !process.isAlive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (transport != null) {
|
||||
if (transport != null && process != null && process.isAlive()) {
|
||||
transport.send(new CloseExternalProcess());
|
||||
process.waitFor(CLOSE_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
} finally {
|
||||
if (process != null) {
|
||||
// no-op unless process is alive
|
||||
process.destroyForcibly();
|
||||
}
|
||||
if (transport != null) {
|
||||
transport.close();
|
||||
}
|
||||
|
||||
// forcefully stop the process after the timeout
|
||||
// note that both transport.close() and process.destroy() are safe to call multiple times
|
||||
new Timer()
|
||||
.schedule(
|
||||
new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (process != null) {
|
||||
transport.close();
|
||||
process.destroyForcibly();
|
||||
}
|
||||
}
|
||||
},
|
||||
CLOSE_TIMEOUT.inWholeMillis());
|
||||
|
||||
// block on process exit
|
||||
process.onExit().get();
|
||||
} catch (Exception e) {
|
||||
transport.close();
|
||||
process.destroyForcibly();
|
||||
} finally {
|
||||
process = null;
|
||||
transport = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -113,7 +113,7 @@ public final class VmFunction extends VmObjectLike {
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public void setCachedValue(Object key, Object value, ObjectMember objectMember) {
|
||||
public void setCachedValue(Object key, Object value) {
|
||||
throw new VmExceptionBuilder()
|
||||
.bug("Class `VmFunction` does not support method `setCachedValue()`.")
|
||||
.build();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -33,7 +33,7 @@ import org.pkl.core.util.Nullable;
|
||||
@TruffleLanguage.Registration(
|
||||
id = "pkl",
|
||||
name = "Pkl",
|
||||
version = "0.27.0-dev",
|
||||
version = "0.27.2",
|
||||
characterMimeTypes = VmLanguage.MIME_TYPE,
|
||||
contextPolicy = ContextPolicy.SHARED)
|
||||
public final class VmLanguage extends TruffleLanguage<VmContext> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,14 +19,13 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import org.graalvm.collections.UnmodifiableEconomicMap;
|
||||
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
public final class VmListing extends VmListingOrMapping {
|
||||
private static final class EmptyHolder {
|
||||
private static final VmListing EMPTY =
|
||||
new VmListing(
|
||||
@@ -47,7 +46,7 @@ public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members,
|
||||
int length) {
|
||||
super(enclosingFrame, Objects.requireNonNull(parent), members, null, null, null);
|
||||
super(enclosingFrame, parent, members);
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@@ -56,16 +55,10 @@ public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members,
|
||||
int length,
|
||||
@Nullable VmListing delegate,
|
||||
ListingOrMappingTypeCastNode typeCheckNode,
|
||||
MaterializedFrame typeNodeFrame) {
|
||||
super(
|
||||
enclosingFrame,
|
||||
Objects.requireNonNull(parent),
|
||||
members,
|
||||
delegate,
|
||||
typeCheckNode,
|
||||
typeNodeFrame);
|
||||
ListingOrMappingTypeCastNode typeCastNode,
|
||||
Object typeCheckReceiver,
|
||||
VmObjectLike typeCheckOwner) {
|
||||
super(enclosingFrame, parent, members, typeCastNode, typeCheckReceiver, typeCheckOwner);
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
@@ -117,20 +110,6 @@ public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
return converter.convertListing(this, path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VmListing withCheckedMembers(
|
||||
ListingOrMappingTypeCastNode typeCheckNode, MaterializedFrame typeNodeFrame) {
|
||||
|
||||
return new VmListing(
|
||||
getEnclosingFrame(),
|
||||
Objects.requireNonNull(parent),
|
||||
members,
|
||||
length,
|
||||
this,
|
||||
typeCheckNode,
|
||||
typeNodeFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
@@ -142,10 +121,14 @@ public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
force(false);
|
||||
other.force(false);
|
||||
|
||||
for (var i = 0L; i < length; i++) {
|
||||
var value = getCachedValue(i);
|
||||
var cursor = cachedValues.getEntries();
|
||||
while (cursor.advance()) {
|
||||
var key = cursor.getKey();
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
assert value != null;
|
||||
var otherValue = other.getCachedValue(i);
|
||||
var otherValue = other.getCachedValue(key);
|
||||
if (!value.equals(otherValue)) return false;
|
||||
}
|
||||
|
||||
@@ -156,14 +139,16 @@ public final class VmListing extends VmListingOrMapping<VmListing> {
|
||||
@TruffleBoundary
|
||||
public int hashCode() {
|
||||
if (cachedHash != 0) return cachedHash;
|
||||
// It's possible that the delegate has already computed its hash code.
|
||||
// If so, we can go ahead and use it.
|
||||
if (delegate != null && delegate.cachedHash != 0) return delegate.cachedHash;
|
||||
|
||||
force(false);
|
||||
var result = 0;
|
||||
for (var i = 0L; i < length; i++) {
|
||||
var value = getCachedValue(i);
|
||||
var cursor = cachedValues.getEntries();
|
||||
|
||||
while (cursor.advance()) {
|
||||
var key = cursor.getKey();
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
assert value != null;
|
||||
result = 31 * result + value.hashCode();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,159 +16,122 @@
|
||||
package org.pkl.core.runtime;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import org.graalvm.collections.EconomicMap;
|
||||
import org.graalvm.collections.EconomicSet;
|
||||
import org.graalvm.collections.UnmodifiableEconomicMap;
|
||||
import org.pkl.core.PklBugException;
|
||||
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.ast.type.TypeNode;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.EconomicSets;
|
||||
import org.pkl.core.util.Nullable;
|
||||
|
||||
public abstract class VmListingOrMapping<SELF extends VmListingOrMapping<SELF>> extends VmObject {
|
||||
|
||||
/**
|
||||
* A Listing or Mapping typecast creates a new object that contains a new typecheck node, and
|
||||
* delegates member lookups to this delegate.
|
||||
*/
|
||||
protected final @Nullable SELF delegate;
|
||||
|
||||
public abstract class VmListingOrMapping extends VmObject {
|
||||
// reified type of listing elements and mapping values
|
||||
private final @Nullable ListingOrMappingTypeCastNode typeCastNode;
|
||||
private final MaterializedFrame typeNodeFrame;
|
||||
private final EconomicMap<Object, ObjectMember> cachedMembers = EconomicMaps.create();
|
||||
private final EconomicSet<Object> checkedMembers = EconomicSets.create();
|
||||
private final @Nullable Object typeCheckReceiver;
|
||||
private final @Nullable VmObjectLike typeCheckOwner;
|
||||
|
||||
public VmListingOrMapping(
|
||||
MaterializedFrame enclosingFrame,
|
||||
@Nullable VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members) {
|
||||
super(enclosingFrame, parent, members);
|
||||
typeCastNode = null;
|
||||
typeCheckReceiver = null;
|
||||
typeCheckOwner = null;
|
||||
}
|
||||
|
||||
public VmListingOrMapping(
|
||||
MaterializedFrame enclosingFrame,
|
||||
@Nullable VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members,
|
||||
@Nullable SELF delegate,
|
||||
@Nullable ListingOrMappingTypeCastNode typeCastNode,
|
||||
@Nullable MaterializedFrame typeNodeFrame) {
|
||||
ListingOrMappingTypeCastNode typeCastNode,
|
||||
Object typeCheckReceiver,
|
||||
VmObjectLike typeCheckOwner) {
|
||||
super(enclosingFrame, parent, members);
|
||||
this.delegate = delegate;
|
||||
this.typeCastNode = typeCastNode;
|
||||
this.typeNodeFrame = typeNodeFrame;
|
||||
this.typeCheckReceiver = typeCheckReceiver;
|
||||
this.typeCheckOwner = typeCheckOwner;
|
||||
}
|
||||
|
||||
ObjectMember findMember(Object key) {
|
||||
var member = EconomicMaps.get(cachedMembers, key);
|
||||
if (member != null) {
|
||||
return member;
|
||||
}
|
||||
if (delegate != null) {
|
||||
return delegate.findMember(key);
|
||||
}
|
||||
// member is guaranteed to exist; this is only called if `getCachedValue()` returns non-null
|
||||
// and `setCachedValue` will record the object member in `cachedMembers`.
|
||||
throw PklBugException.unreachableCode();
|
||||
}
|
||||
|
||||
public @Nullable ListingOrMappingTypeCastNode getTypeCastNode() {
|
||||
return typeCastNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCachedValue(Object key, Object value, ObjectMember objectMember) {
|
||||
super.setCachedValue(key, value, objectMember);
|
||||
EconomicMaps.put(cachedMembers, key, objectMember);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCachedValue(Object key) {
|
||||
return super.hasCachedValue(key) || delegate != null && delegate.hasCachedValue(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object getCachedValue(Object key) {
|
||||
var myCachedValue = super.getCachedValue(key);
|
||||
if (myCachedValue != null || delegate == null) {
|
||||
return myCachedValue;
|
||||
}
|
||||
var memberValue = delegate.getCachedValue(key);
|
||||
// if this object member appears inside `checkedMembers`, we have already checked its type
|
||||
// and can safely return it.
|
||||
if (EconomicSets.contains(checkedMembers, key)) {
|
||||
return memberValue;
|
||||
}
|
||||
if (memberValue == null) {
|
||||
return null;
|
||||
}
|
||||
// If a cached value already exists on the delegate, run a typecast on it.
|
||||
// optimization: don't use `VmUtils.findMember` to avoid iterating over all members
|
||||
var objectMember = findMember(key);
|
||||
var ret = typecastObjectMember(objectMember, memberValue, IndirectCallNode.getUncached());
|
||||
if (ret != memberValue) {
|
||||
EconomicMaps.put(cachedValues, key, ret);
|
||||
} else {
|
||||
// optimization: don't add to own cached values if typecast results in the same value
|
||||
EconomicSets.add(checkedMembers, key);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getExtraStorage() {
|
||||
if (delegate != null) {
|
||||
return delegate.getExtraStorage();
|
||||
}
|
||||
assert extraStorage != null;
|
||||
return extraStorage;
|
||||
}
|
||||
|
||||
/** Perform a typecast on this member, */
|
||||
public Object typecastObjectMember(
|
||||
ObjectMember member, Object memberValue, IndirectCallNode callNode) {
|
||||
if (!(member.isEntry() || member.isElement()) || typeCastNode == null) {
|
||||
return memberValue;
|
||||
}
|
||||
assert typeNodeFrame != null;
|
||||
var ret = memberValue;
|
||||
if (delegate != null) {
|
||||
ret = delegate.typecastObjectMember(member, ret, callNode);
|
||||
}
|
||||
// Recursively executes type casts between `owner` and `this` and returns the resulting value.
|
||||
public final Object executeTypeCasts(
|
||||
Object value,
|
||||
VmObjectLike owner,
|
||||
IndirectCallNode callNode,
|
||||
// if non-null, a stack frame for this member is inserted if a type cast fails
|
||||
@Nullable ObjectMember member,
|
||||
// Next type cast to be performed by the caller.
|
||||
// Avoids repeating the same type cast in some cases.
|
||||
@Nullable ListingOrMappingTypeCastNode nextTypeCastNode) {
|
||||
var newNextTypeCastNode = typeCastNode != null ? typeCastNode : nextTypeCastNode;
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
var result =
|
||||
this == owner
|
||||
? value
|
||||
: ((VmListingOrMapping) parent)
|
||||
.executeTypeCasts(value, owner, callNode, member, newNextTypeCastNode);
|
||||
if (typeCastNode == null || typeCastNode == nextTypeCastNode) return result;
|
||||
var callTarget = typeCastNode.getCallTarget();
|
||||
try {
|
||||
return callNode.call(
|
||||
callTarget, VmUtils.getReceiver(typeNodeFrame), VmUtils.getOwner(typeNodeFrame), ret);
|
||||
} catch (VmException vmException) {
|
||||
return callNode.call(callTarget, typeCheckReceiver, typeCheckOwner, result);
|
||||
} catch (VmException e) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
// treat typecheck as part of the call stack to read the original member if there is a
|
||||
// source section for it.
|
||||
var sourceSection = member.getBodySection();
|
||||
if (!sourceSection.isAvailable()) {
|
||||
sourceSection = member.getSourceSection();
|
||||
if (member != null) {
|
||||
VmUtils.insertStackFrame(member, callTarget, e);
|
||||
}
|
||||
if (sourceSection.isAvailable()) {
|
||||
vmException
|
||||
.getInsertedStackFrames()
|
||||
.put(callTarget, VmUtils.createStackFrame(sourceSection, member.getQualifiedName()));
|
||||
}
|
||||
throw vmException;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract SELF withCheckedMembers(
|
||||
ListingOrMappingTypeCastNode typeCastNode, MaterializedFrame typeNodeFrame);
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public final @Nullable Object getCachedValue(Object key) {
|
||||
var result = EconomicMaps.get(cachedValues, key);
|
||||
// if this object has members, `this[key]` may differ from `parent[key]`, so stop the search
|
||||
if (result != null || !members.isEmpty()) return result;
|
||||
|
||||
/** Tells if this mapping/listing runs the same typechecks as {@code typeNode}. */
|
||||
public boolean hasSameChecksAs(TypeNode typeNode) {
|
||||
// Optimization: Recursively steal value from parent cache to avoid computing it multiple times.
|
||||
// The current implementation has the following limitations and drawbacks:
|
||||
// * It only works if a parent has, coincidentally, already cached `key`.
|
||||
// * It turns getCachedValue() into an operation that isn't guaranteed to be fast and fail-safe.
|
||||
// * It requires making VmObject.getCachedValue() non-final,
|
||||
// which is unfavorable for Truffle partial evaluation and JVM inlining.
|
||||
// * It may not be worth its cost for constant members and members that are cheap to compute.
|
||||
|
||||
assert parent != null; // VmListingOrMapping always has a parent
|
||||
result = parent.getCachedValue(key);
|
||||
if (result == null) return null;
|
||||
|
||||
if (typeCastNode != null && !(key instanceof Identifier)) {
|
||||
var callNode = IndirectCallNode.getUncached();
|
||||
var callTarget = typeCastNode.getCallTarget();
|
||||
try {
|
||||
result = callNode.call(callTarget, typeCheckReceiver, typeCheckOwner, result);
|
||||
} catch (VmException e) {
|
||||
var member = VmUtils.findMember(parent, key);
|
||||
assert member != null; // already found the member's cached value
|
||||
VmUtils.insertStackFrame(member, callTarget, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
setCachedValue(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the value type of this listing/mapping is known to be a subtype of {@code
|
||||
* typeNode}. If {@code true}, type checks of individual values can be elided because
|
||||
* listings/mappings are covariant in their value type.
|
||||
*/
|
||||
public final boolean isValueTypeKnownSubtypeOf(TypeNode typeNode) {
|
||||
if (typeNode.isNoopTypeCheck()) {
|
||||
return true;
|
||||
}
|
||||
if (typeCastNode == null) {
|
||||
return false;
|
||||
}
|
||||
if (typeCastNode.getTypeNode().isEquivalentTo(typeNode)) {
|
||||
return true;
|
||||
}
|
||||
// we can say the check is the same if the delegate has this check.
|
||||
// when `Listing<Any>` delegates to `Listing<UInt>`, it has the same checks as a `UInt`
|
||||
// typenode.
|
||||
if (delegate != null) {
|
||||
return delegate.hasSameChecksAs(typeNode);
|
||||
}
|
||||
return false;
|
||||
return typeCastNode.getTypeNode().isEquivalentTo(typeNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,6 @@ package org.pkl.core.runtime;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.frame.MaterializedFrame;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import org.graalvm.collections.UnmodifiableEconomicMap;
|
||||
import org.pkl.core.ast.member.ListingOrMappingTypeCastNode;
|
||||
@@ -27,7 +26,7 @@ import org.pkl.core.util.CollectionUtils;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.LateInit;
|
||||
|
||||
public final class VmMapping extends VmListingOrMapping<VmMapping> {
|
||||
public final class VmMapping extends VmListingOrMapping {
|
||||
|
||||
private int cachedEntryCount = -1;
|
||||
|
||||
@@ -50,24 +49,17 @@ public final class VmMapping extends VmListingOrMapping<VmMapping> {
|
||||
MaterializedFrame enclosingFrame,
|
||||
VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members) {
|
||||
|
||||
super(enclosingFrame, Objects.requireNonNull(parent), members, null, null, null);
|
||||
super(enclosingFrame, parent, members);
|
||||
}
|
||||
|
||||
public VmMapping(
|
||||
MaterializedFrame enclosingFrame,
|
||||
VmObject parent,
|
||||
UnmodifiableEconomicMap<Object, ObjectMember> members,
|
||||
VmMapping delegate,
|
||||
ListingOrMappingTypeCastNode typeCheckNode,
|
||||
MaterializedFrame typeNodeFrame) {
|
||||
super(
|
||||
enclosingFrame,
|
||||
Objects.requireNonNull(parent),
|
||||
members,
|
||||
delegate,
|
||||
typeCheckNode,
|
||||
typeNodeFrame);
|
||||
ListingOrMappingTypeCastNode typeCastNode,
|
||||
Object typeCheckReceiver,
|
||||
VmObjectLike typeCheckOwner) {
|
||||
super(enclosingFrame, parent, members, typeCastNode, typeCheckReceiver, typeCheckOwner);
|
||||
}
|
||||
|
||||
public static boolean isDefaultProperty(Object propertyKey) {
|
||||
@@ -81,16 +73,12 @@ public final class VmMapping extends VmListingOrMapping<VmMapping> {
|
||||
|
||||
@TruffleBoundary
|
||||
public VmSet getAllKeys() {
|
||||
if (delegate != null) {
|
||||
return delegate.getAllKeys();
|
||||
}
|
||||
synchronized (this) {
|
||||
if (__allKeys == null) {
|
||||
// building upon parent's `getAllKeys()` should improve at least worst case efficiency
|
||||
var parentKeys =
|
||||
getParent() instanceof VmMapping mapping ? mapping.getAllKeys() : VmSet.EMPTY;
|
||||
var parentKeys = parent instanceof VmMapping mapping ? mapping.getAllKeys() : VmSet.EMPTY;
|
||||
var builder = VmSet.builder(parentKeys);
|
||||
for (var cursor = getMembers().getEntries(); cursor.advance(); ) {
|
||||
for (var cursor = members.getEntries(); cursor.advance(); ) {
|
||||
var member = cursor.getValue();
|
||||
if (!member.isEntry()) continue;
|
||||
builder.add(cursor.getKey());
|
||||
@@ -133,12 +121,17 @@ public final class VmMapping extends VmListingOrMapping<VmMapping> {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof VmMapping other)) return false;
|
||||
|
||||
if (getEntryCount() != other.getEntryCount()) return false;
|
||||
// could use shallow force, but deep force is cached
|
||||
force(false);
|
||||
other.force(false);
|
||||
for (var key : getAllKeys()) {
|
||||
var value = getCachedValue(key);
|
||||
if (getEntryCount() != other.getEntryCount()) return false;
|
||||
|
||||
var cursor = cachedValues.getEntries();
|
||||
while (cursor.advance()) {
|
||||
Object key = cursor.getKey();
|
||||
if (key instanceof Identifier) continue;
|
||||
|
||||
var value = cursor.getValue();
|
||||
assert value != null;
|
||||
var otherValue = other.getCachedValue(key);
|
||||
if (!value.equals(otherValue)) return false;
|
||||
@@ -151,38 +144,34 @@ public final class VmMapping extends VmListingOrMapping<VmMapping> {
|
||||
@TruffleBoundary
|
||||
public int hashCode() {
|
||||
if (cachedHash != 0) return cachedHash;
|
||||
// It's possible that the delegate has already computed its hash code.
|
||||
// If so, we can go ahead and use it.
|
||||
if (delegate != null && delegate.cachedHash != 0) return delegate.cachedHash;
|
||||
|
||||
force(false);
|
||||
var result = 0;
|
||||
for (var key : getAllKeys()) {
|
||||
var cursor = cachedValues.getEntries();
|
||||
|
||||
while (cursor.advance()) {
|
||||
var key = cursor.getKey();
|
||||
if (key instanceof Identifier) continue;
|
||||
var value = getCachedValue(key);
|
||||
|
||||
var value = cursor.getValue();
|
||||
assert value != null;
|
||||
result += key.hashCode() ^ value.hashCode();
|
||||
}
|
||||
|
||||
cachedHash = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// assumes mapping has been forced
|
||||
public int getEntryCount() {
|
||||
if (cachedEntryCount != -1) return cachedEntryCount;
|
||||
cachedEntryCount = getAllKeys().getLength();
|
||||
return cachedEntryCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@TruffleBoundary
|
||||
public VmMapping withCheckedMembers(
|
||||
ListingOrMappingTypeCastNode typeCheckNode, MaterializedFrame typeNodeFrame) {
|
||||
return new VmMapping(
|
||||
getEnclosingFrame(),
|
||||
Objects.requireNonNull(getParent()),
|
||||
getMembers(),
|
||||
this,
|
||||
typeCheckNode,
|
||||
typeNodeFrame);
|
||||
var result = 0;
|
||||
for (var key : cachedValues.getKeys()) {
|
||||
if (key instanceof Identifier) continue;
|
||||
result += 1;
|
||||
}
|
||||
cachedEntryCount = result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -87,12 +87,12 @@ public abstract class VmObject extends VmObjectLike {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCachedValue(Object key, Object value, ObjectMember objectMember) {
|
||||
public final void setCachedValue(Object key, Object value) {
|
||||
EconomicMaps.put(cachedValues, key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCachedValue(Object key) {
|
||||
public final boolean hasCachedValue(Object key) {
|
||||
return EconomicMaps.containsKey(cachedValues, key);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -96,7 +96,7 @@ public abstract class VmObjectLike extends VmValue {
|
||||
* receiver.
|
||||
*/
|
||||
@TruffleBoundary
|
||||
public abstract void setCachedValue(Object key, Object value, ObjectMember objectMember);
|
||||
public abstract void setCachedValue(Object key, Object value);
|
||||
|
||||
/**
|
||||
* Prefer this method over {@link #getCachedValue} if the value is not required. (There is no
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.pkl.core.runtime;
|
||||
|
||||
import com.oracle.truffle.api.CallTarget;
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.Truffle;
|
||||
@@ -134,10 +135,6 @@ public final class VmUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setReceiver(Frame frame, Object receiver) {
|
||||
frame.getArguments()[0] = receiver;
|
||||
}
|
||||
|
||||
public static VmObjectLike getObjectReceiver(Frame frame) {
|
||||
return (VmObjectLike) getReceiver(frame);
|
||||
}
|
||||
@@ -158,10 +155,6 @@ public final class VmUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void setOwner(Frame frame, VmObjectLike owner) {
|
||||
frame.getArguments()[1] = owner;
|
||||
}
|
||||
|
||||
/** Returns a `ObjectMember`'s key while executing the corresponding `MemberNode`. */
|
||||
public static Object getMemberKey(Frame frame) {
|
||||
return frame.getArguments()[2];
|
||||
@@ -261,17 +254,17 @@ public final class VmUtils {
|
||||
|
||||
final var constantValue = member.getConstantValue();
|
||||
if (constantValue != null) {
|
||||
var ret = constantValue;
|
||||
// for a property, do a type check
|
||||
var result = constantValue;
|
||||
// for a property, Listing element, or Mapping value, do a type check
|
||||
if (member.isProp()) {
|
||||
var property = receiver.getVmClass().getProperty(member.getName());
|
||||
if (property != null && property.getTypeNode() != null) {
|
||||
var callTarget = property.getTypeNode().getCallTarget();
|
||||
try {
|
||||
if (checkType) {
|
||||
ret = callNode.call(callTarget, receiver, property.getOwner(), constantValue);
|
||||
result = callNode.call(callTarget, receiver, property.getOwner(), constantValue);
|
||||
} else {
|
||||
ret =
|
||||
result =
|
||||
callNode.call(
|
||||
callTarget,
|
||||
receiver,
|
||||
@@ -281,44 +274,52 @@ public final class VmUtils {
|
||||
}
|
||||
} catch (VmException e) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
// A failed property type check looks as follows in the stack trace:
|
||||
// x: Int(isPositive)
|
||||
// at ...
|
||||
// x = -10
|
||||
// at ...
|
||||
// However, if the value of `x` is a parse-time constant (as in `x = -10`),
|
||||
// there's no root node for it and hence no stack trace element.
|
||||
// In this case, insert a stack trace element to make the stack trace look the same
|
||||
// as in the non-constant case. (Parse-time constants are an internal optimization.)
|
||||
e.getInsertedStackFrames()
|
||||
.put(
|
||||
callTarget,
|
||||
createStackFrame(member.getBodySection(), member.getQualifiedName()));
|
||||
insertStackFrame(member, callTarget, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} else if (receiver instanceof VmListingOrMapping<?> vmListingOrMapping) {
|
||||
if (owner != receiver && owner instanceof VmListingOrMapping<?> vmListingOrMappingOwner) {
|
||||
ret = vmListingOrMappingOwner.typecastObjectMember(member, ret, callNode);
|
||||
}
|
||||
ret = vmListingOrMapping.typecastObjectMember(member, ret, callNode);
|
||||
} else if (receiver instanceof VmListingOrMapping listingOrMapping
|
||||
&& owner instanceof VmListingOrMapping) {
|
||||
// `owner instanceof VmListingOrMapping` guards against
|
||||
// PropertiesRenderer amending VmDynamic with VmListing (hack?)
|
||||
result = listingOrMapping.executeTypeCasts(constantValue, owner, callNode, member, null);
|
||||
}
|
||||
receiver.setCachedValue(memberKey, ret, member);
|
||||
return ret;
|
||||
|
||||
receiver.setCachedValue(memberKey, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
var callTarget = member.getCallTarget();
|
||||
Object ret;
|
||||
Object result;
|
||||
if (checkType) {
|
||||
ret = callNode.call(callTarget, receiver, owner, memberKey);
|
||||
result = callNode.call(callTarget, receiver, owner, memberKey);
|
||||
} else {
|
||||
ret = callNode.call(callTarget, receiver, owner, memberKey, VmUtils.SKIP_TYPECHECK_MARKER);
|
||||
result = callNode.call(callTarget, receiver, owner, memberKey, VmUtils.SKIP_TYPECHECK_MARKER);
|
||||
}
|
||||
if (receiver instanceof VmListingOrMapping<?> vmListingOrMapping) {
|
||||
ret = vmListingOrMapping.typecastObjectMember(member, ret, callNode);
|
||||
receiver.setCachedValue(memberKey, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// A failed property type check looks as follows in the stack trace:
|
||||
// x: Int(isPositive)
|
||||
// at ...
|
||||
// x = -10
|
||||
// at ...
|
||||
// However, if the value of `x` is a parse-time constant (as in `x = -10`),
|
||||
// there's no root node for it and hence no stack trace element.
|
||||
// In this case, insert a stack trace element to make the stack trace look the same
|
||||
// as in the non-constant case. (Parse-time constants are an internal optimization.)
|
||||
public static void insertStackFrame(
|
||||
ObjectMember member, CallTarget location, VmException exception) {
|
||||
var sourceSection = member.getBodySection();
|
||||
if (!sourceSection.isAvailable()) {
|
||||
sourceSection = member.getSourceSection();
|
||||
}
|
||||
if (sourceSection.isAvailable()) {
|
||||
exception
|
||||
.getInsertedStackFrames()
|
||||
.put(location, createStackFrame(sourceSection, member.getQualifiedName()));
|
||||
}
|
||||
receiver.setCachedValue(memberKey, ret, member);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static @Nullable ObjectMember findMember(VmObjectLike receiver, Object memberKey) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -50,6 +50,7 @@ import org.pkl.core.runtime.VmDuration;
|
||||
import org.pkl.core.runtime.VmDynamic;
|
||||
import org.pkl.core.runtime.VmExceptionBuilder;
|
||||
import org.pkl.core.runtime.VmIntSeq;
|
||||
import org.pkl.core.runtime.VmLanguage;
|
||||
import org.pkl.core.runtime.VmList;
|
||||
import org.pkl.core.runtime.VmListing;
|
||||
import org.pkl.core.runtime.VmMap;
|
||||
@@ -573,7 +574,8 @@ public final class RendererNodes {
|
||||
type =
|
||||
requiresWrapper()
|
||||
? null
|
||||
: new ListingTypeNode(VmUtils.unavailableSourceSection(), valueType);
|
||||
: new ListingTypeNode(
|
||||
VmUtils.unavailableSourceSection(), VmLanguage.get(null), valueType);
|
||||
return type;
|
||||
} else if (type instanceof MappingTypeNode mappingType) {
|
||||
var keyType = resolveType(mappingType.getKeyTypeNode());
|
||||
@@ -587,7 +589,9 @@ public final class RendererNodes {
|
||||
}
|
||||
var valueType = resolveType(mappingType.getValueTypeNode());
|
||||
assert valueType != null : "Incomplete or malformed Mapping type";
|
||||
mappingType = new MappingTypeNode(VmUtils.unavailableSourceSection(), keyType, valueType);
|
||||
mappingType =
|
||||
new MappingTypeNode(
|
||||
VmUtils.unavailableSourceSection(), VmLanguage.get(null), keyType, valueType);
|
||||
|
||||
type = requiresWrapper() ? null : mappingType;
|
||||
return type;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.pkl.core.stdlib.test.report;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
import org.pkl.core.TestResults;
|
||||
import org.pkl.core.TestResults.TestResult;
|
||||
@@ -144,7 +145,10 @@ public final class SimpleReport implements TestReport {
|
||||
sb.append(
|
||||
color,
|
||||
() ->
|
||||
sb.append(String.format("%.1f%%", passRate)).append(" ").append(kind).append(" pass"));
|
||||
sb.append(String.format(Locale.ROOT, "%.1f%%", passRate))
|
||||
.append(" ")
|
||||
.append(kind)
|
||||
.append(" pass"));
|
||||
|
||||
if (isFailed) {
|
||||
sb.append(" [").append(failed).append('/').append(total).append(" failed]");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,10 @@ import org.graalvm.collections.UnmodifiableMapCursor;
|
||||
public final class EconomicMaps {
|
||||
private EconomicMaps() {}
|
||||
|
||||
public static <K, V> UnmodifiableEconomicMap<K, V> emptyMap() {
|
||||
return EconomicMap.emptyMap();
|
||||
}
|
||||
|
||||
@TruffleBoundary
|
||||
public static <K, V> EconomicMap<K, V> create() {
|
||||
return EconomicMap.create();
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
function isValid(str): Boolean = str.startsWith("a")
|
||||
|
||||
foo: Listing<String(isValid(this))>(isDistinct)
|
||||
@@ -27,12 +27,20 @@ local altered: Listing<Person> = (base) {
|
||||
[0] { name = "Wood Pigeon" }
|
||||
}
|
||||
|
||||
local computedIndex: Listing<Person> = (base) {
|
||||
[computeIndex()] { name = "Wood Pigeon" }
|
||||
}
|
||||
|
||||
local function computeIndex() = 0
|
||||
|
||||
facts {
|
||||
["isEmpty"] {
|
||||
empty.isEmpty
|
||||
empty2.isEmpty
|
||||
!base.isEmpty
|
||||
!derived.isEmpty
|
||||
!altered.isEmpty
|
||||
!computedIndex.isEmpty
|
||||
}
|
||||
|
||||
["lastIndex"] {
|
||||
@@ -41,6 +49,8 @@ facts {
|
||||
base.lastIndex == 2
|
||||
derived.lastIndex == 4
|
||||
duplicate.lastIndex == 5
|
||||
altered.lastIndex == 2
|
||||
computedIndex.lastIndex == 2
|
||||
}
|
||||
|
||||
["isDistinct"] {
|
||||
@@ -49,6 +59,8 @@ facts {
|
||||
base.isDistinct
|
||||
derived.isDistinct
|
||||
!duplicate.isDistinct
|
||||
altered.isDistinct
|
||||
computedIndex.isDistinct
|
||||
}
|
||||
|
||||
["isDistinctBy()"] {
|
||||
@@ -57,18 +69,24 @@ facts {
|
||||
base.isDistinctBy((it) -> it)
|
||||
derived.isDistinctBy((it) -> it)
|
||||
!duplicate.isDistinctBy((it) -> it)
|
||||
altered.isDistinctBy((it) -> it)
|
||||
computedIndex.isDistinctBy((it) -> it)
|
||||
|
||||
empty.isDistinctBy((it) -> it.name)
|
||||
empty2.isDistinctBy((it) -> it.name)
|
||||
base.isDistinctBy((it) -> it.name)
|
||||
derived.isDistinctBy((it) -> it.name)
|
||||
!duplicate.isDistinctBy((it) -> it.name)
|
||||
altered.isDistinctBy((it) -> it.name)
|
||||
computedIndex.isDistinctBy((it) -> it.name)
|
||||
|
||||
empty.isDistinctBy((it) -> it.getClass())
|
||||
empty2.isDistinctBy((it) -> it.getClass())
|
||||
!base.isDistinctBy((it) -> it.getClass())
|
||||
!derived.isDistinctBy((it) -> it.getClass())
|
||||
!duplicate.isDistinctBy((it) -> it.getClass())
|
||||
!altered.isDistinctBy((it) -> it.getClass())
|
||||
!computedIndex.isDistinctBy((it) -> it.getClass())
|
||||
}
|
||||
|
||||
["getOrNull"] {
|
||||
@@ -85,24 +103,32 @@ facts {
|
||||
module.catch(() -> empty.first) == "Expected a non-empty Listing."
|
||||
base.first == base[0]
|
||||
derived.first == base[0]
|
||||
altered.first != base[0]
|
||||
computedIndex.first == altered.first
|
||||
}
|
||||
|
||||
["firstOrNull"] {
|
||||
empty.firstOrNull == null
|
||||
base.firstOrNull == base[0]
|
||||
derived.firstOrNull == base[0]
|
||||
altered.firstOrNull != base[0]
|
||||
computedIndex.firstOrNull == altered.first
|
||||
}
|
||||
|
||||
["last"] {
|
||||
module.catch(() -> empty.last) == "Expected a non-empty Listing."
|
||||
base.last == base[2]
|
||||
derived.last == derived[4]
|
||||
altered.last == base[2]
|
||||
computedIndex.last == base[2]
|
||||
}
|
||||
|
||||
["lastOrNull"] {
|
||||
empty.lastOrNull == null
|
||||
base.lastOrNull == base[2]
|
||||
derived.lastOrNull == derived[4]
|
||||
altered.lastOrNull == base[2]
|
||||
computedIndex.lastOrNull == base[2]
|
||||
}
|
||||
|
||||
["single"] {
|
||||
@@ -135,6 +161,7 @@ facts {
|
||||
derived.contains(base[1])
|
||||
derived.contains(derived[3])
|
||||
!altered.contains(base[0])
|
||||
!computedIndex.contains(base[0])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +171,17 @@ examples {
|
||||
empty2.length
|
||||
base.length
|
||||
derived.length
|
||||
altered.length
|
||||
computedIndex.length
|
||||
|
||||
local elementsAndEntries = (base) {
|
||||
new { name = "" }
|
||||
[2] { name = "" }
|
||||
[computeIndex()] { name = "" }
|
||||
new { name = "" }
|
||||
[1 + 0] { name = "" }
|
||||
}
|
||||
elementsAndEntries.length
|
||||
}
|
||||
|
||||
["toList()"] {
|
||||
@@ -152,6 +190,8 @@ examples {
|
||||
base.toList()
|
||||
derived.toList()
|
||||
duplicate.toList()
|
||||
altered.toList()
|
||||
computedIndex.toList()
|
||||
}
|
||||
|
||||
["toSet()"] {
|
||||
@@ -160,6 +200,8 @@ examples {
|
||||
base.toSet()
|
||||
derived.toSet()
|
||||
duplicate.toSet()
|
||||
altered.toSet()
|
||||
computedIndex.toSet()
|
||||
}
|
||||
|
||||
["distinct"] {
|
||||
@@ -168,6 +210,8 @@ examples {
|
||||
base.distinct
|
||||
derived.distinct
|
||||
duplicate.distinct
|
||||
altered.distinct
|
||||
computedIndex.distinct
|
||||
}
|
||||
|
||||
["distinctBy()"] {
|
||||
@@ -176,36 +220,48 @@ examples {
|
||||
base.distinctBy((it) -> it)
|
||||
derived.distinctBy((it) -> it)
|
||||
duplicate.distinctBy((it) -> it)
|
||||
altered.distinctBy((it) -> it)
|
||||
computedIndex.distinctBy((it) -> it)
|
||||
|
||||
empty.distinctBy((it) -> it.name)
|
||||
empty2.distinctBy((it) -> it.name)
|
||||
base.distinctBy((it) -> it.name)
|
||||
derived.distinctBy((it) -> it.name)
|
||||
duplicate.distinctBy((it) -> it.name)
|
||||
altered.distinctBy((it) -> it.name)
|
||||
computedIndex.distinctBy((it) -> it.name)
|
||||
|
||||
empty.distinctBy((it) -> it.getClass())
|
||||
empty2.distinctBy((it) -> it.getClass())
|
||||
base.distinctBy((it) -> it.getClass())
|
||||
derived.distinctBy((it) -> it.getClass())
|
||||
duplicate.distinctBy((it) -> it.getClass())
|
||||
altered.distinctBy((it) -> it.getClass())
|
||||
computedIndex.distinctBy((it) -> it.getClass())
|
||||
}
|
||||
|
||||
["fold"] {
|
||||
empty.fold(List(), (l, e) -> l.add(e))
|
||||
base.fold(List(), (l, e) -> l.add(e))
|
||||
derived.fold(List(), (l, e) -> l.add(e))
|
||||
altered.fold(List(), (l, e) -> l.add(e))
|
||||
computedIndex.fold(List(), (l, e) -> l.add(e))
|
||||
}
|
||||
|
||||
["foldIndexed"] {
|
||||
empty.foldIndexed(List(), (i, l, e) -> l.add(Pair(i, e)))
|
||||
base.foldIndexed(List(), (i, l, e) -> l.add(Pair(i, e)))
|
||||
derived.foldIndexed(List(), (i, l, e) -> l.add(Pair(i, e)))
|
||||
altered.foldIndexed(List(), (i, l, e) -> l.add(Pair(i, e)))
|
||||
computedIndex.foldIndexed(List(), (i, l, e) -> l.add(Pair(i, e)))
|
||||
}
|
||||
|
||||
|
||||
local baseNum = new Listing { 1; 2; 3 }
|
||||
local baseString = new Listing { "Pigeon"; "Barn Owl"; "Parrot" }
|
||||
local derivedString = (baseString) { "Albatross"; "Elf Owl" }
|
||||
local alteredString = (baseString) { [0] = "Wood Pigeon" }
|
||||
local computedIndexString = (baseString) { [computeIndex()] = "Wood Pigeon" }
|
||||
|
||||
["join"] {
|
||||
empty.join("")
|
||||
@@ -215,5 +271,9 @@ examples {
|
||||
baseString.join("---")
|
||||
derivedString.join("")
|
||||
derivedString.join("\n")
|
||||
alteredString.join("")
|
||||
alteredString.join("\n")
|
||||
computedIndexString.join("")
|
||||
computedIndexString.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
6
pkl-core/src/test/files/LanguageSnippetTests/input/errors/listingTypeCheckError8.pkl
vendored
Normal file
6
pkl-core/src/test/files/LanguageSnippetTests/input/errors/listingTypeCheckError8.pkl
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
local a = new Listing { new Listing { 0 } }
|
||||
local b = a as Listing<Listing<String>>
|
||||
local c = (b) { new Listing { 1 } }
|
||||
local d = c as Listing<Listing<Int>>
|
||||
|
||||
result = d
|
||||
10
pkl-core/src/test/files/LanguageSnippetTests/input/errors/listingTypeCheckError9.pkl
vendored
Normal file
10
pkl-core/src/test/files/LanguageSnippetTests/input/errors/listingTypeCheckError9.pkl
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
local a = new Listing { new Foo {} }
|
||||
local b = (a) { new Bar {} }
|
||||
local c = b as Listing<Bar>
|
||||
local d = (c) { new Foo {} }
|
||||
local e = d as Listing<Foo>
|
||||
|
||||
result = e
|
||||
|
||||
open class Foo
|
||||
class Bar extends Foo
|
||||
10
pkl-core/src/test/files/LanguageSnippetTests/input/errors/mappingTypeCheckError11.pkl
vendored
Normal file
10
pkl-core/src/test/files/LanguageSnippetTests/input/errors/mappingTypeCheckError11.pkl
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
local a = new Mapping { [0] = new Foo {} }
|
||||
local b = (a) { [1] = new Bar {} }
|
||||
local c = b as Mapping<Int, Bar>
|
||||
local d = (c) { [2] = new Foo {} }
|
||||
local e = d as Mapping<Int, Foo>
|
||||
|
||||
result = e
|
||||
|
||||
open class Foo
|
||||
class Bar extends Foo
|
||||
7
pkl-core/src/test/files/LanguageSnippetTests/input/listings/cacheStealing.pkl
vendored
Normal file
7
pkl-core/src/test/files/LanguageSnippetTests/input/listings/cacheStealing.pkl
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
foo1: Listing<String> = new { "hello" }
|
||||
foo2: Listing<String|Int> = foo1
|
||||
|
||||
res1 = foo1.isDistinct
|
||||
// steals isDistinct from foo1's VmListing.cachedValues but must not
|
||||
// perform a String|Int type check because isDistinct is not an element
|
||||
res2 = foo2.isDistinct
|
||||
8
pkl-core/src/test/files/LanguageSnippetTests/input/listings/cacheStealingTypeCheck.pkl
vendored
Normal file
8
pkl-core/src/test/files/LanguageSnippetTests/input/listings/cacheStealingTypeCheck.pkl
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
amends "../../input-helper/listings/cacheStealingTypeCheck.pkl"
|
||||
|
||||
// this test covers a regression where the wrong receiver
|
||||
// and owner was used to typecheck a stolen value
|
||||
foo {
|
||||
"abcdx"
|
||||
"ax"
|
||||
}
|
||||
5
pkl-core/src/test/files/LanguageSnippetTests/input/types/helpers/originalTypealias.pkl
vendored
Normal file
5
pkl-core/src/test/files/LanguageSnippetTests/input/types/helpers/originalTypealias.pkl
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
const local lastName = "Birdo"
|
||||
|
||||
typealias Birds = Listing<String(endsWith(lastName))>
|
||||
|
||||
typealias Birds2 = Pair<Listing<String(endsWith(lastName))>, Int>
|
||||
@@ -1,5 +1,7 @@
|
||||
import "pkl:test"
|
||||
|
||||
import "helpers/originalTypealias.pkl"
|
||||
|
||||
typealias Simple = String
|
||||
const function simple(arg: Simple): Simple = arg
|
||||
|
||||
@@ -105,3 +107,8 @@ res19: LocalTypeAlias = "abc"
|
||||
typealias VeryComposite = Pair<Composite, Composite>
|
||||
|
||||
res20: VeryComposite = Pair(Map("abc", List("def")), Map("abc", List("def")))
|
||||
|
||||
// typealiases should be executed in their original context
|
||||
res21: originalTypealias.Birds = new { "John Birdo" }
|
||||
|
||||
res22: originalTypealias.Birds2 = Pair(new Listing { "John Birdo" }, 0)
|
||||
|
||||
3
pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAliasContext.pkl
vendored
Normal file
3
pkl-core/src/test/files/LanguageSnippetTests/input/types/typeAliasContext.pkl
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import "helpers/originalTypealias.pkl"
|
||||
|
||||
res: originalTypealias.Birds = new { "Jimmy Bird" }
|
||||
@@ -4,6 +4,8 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["lastIndex"] {
|
||||
true
|
||||
@@ -11,6 +13,8 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["isDistinct"] {
|
||||
true
|
||||
@@ -18,6 +22,8 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["isDistinctBy()"] {
|
||||
true
|
||||
@@ -35,6 +41,12 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["getOrNull"] {
|
||||
true
|
||||
@@ -49,21 +61,29 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["firstOrNull"] {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["last"] {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["lastOrNull"] {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
["single"] {
|
||||
true
|
||||
@@ -91,6 +111,7 @@ facts {
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
}
|
||||
}
|
||||
examples {
|
||||
@@ -99,6 +120,9 @@ examples {
|
||||
0
|
||||
3
|
||||
5
|
||||
3
|
||||
3
|
||||
5
|
||||
}
|
||||
["toList()"] {
|
||||
List()
|
||||
@@ -134,6 +158,20 @@ examples {
|
||||
}, new {
|
||||
name = "Elf Owl"
|
||||
})
|
||||
List(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
List(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
}
|
||||
["toSet()"] {
|
||||
Set()
|
||||
@@ -167,6 +205,20 @@ examples {
|
||||
}, new {
|
||||
name = "Elf Owl"
|
||||
})
|
||||
Set(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
Set(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
}
|
||||
["distinct"] {
|
||||
new {}
|
||||
@@ -216,6 +268,28 @@ examples {
|
||||
name = "Elf Owl"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
}
|
||||
["distinctBy()"] {
|
||||
new {}
|
||||
@@ -265,6 +339,28 @@ examples {
|
||||
name = "Elf Owl"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
new {}
|
||||
new {}
|
||||
new {
|
||||
@@ -312,6 +408,28 @@ examples {
|
||||
name = "Elf Owl"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
new {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
new {
|
||||
name = "Parrot"
|
||||
}
|
||||
}
|
||||
new {}
|
||||
new {}
|
||||
new {
|
||||
@@ -329,6 +447,16 @@ examples {
|
||||
name = "Pigeon"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
}
|
||||
new {
|
||||
new {
|
||||
name = "Wood Pigeon"
|
||||
}
|
||||
}
|
||||
}
|
||||
["fold"] {
|
||||
List()
|
||||
@@ -350,6 +478,20 @@ examples {
|
||||
}, new {
|
||||
name = "Elf Owl"
|
||||
})
|
||||
List(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
List(new {
|
||||
name = "Wood Pigeon"
|
||||
}, new {
|
||||
name = "Barn Owl"
|
||||
}, new {
|
||||
name = "Parrot"
|
||||
})
|
||||
}
|
||||
["foldIndexed"] {
|
||||
List()
|
||||
@@ -371,6 +513,20 @@ examples {
|
||||
}), Pair(4, new {
|
||||
name = "Elf Owl"
|
||||
}))
|
||||
List(Pair(0, new {
|
||||
name = "Wood Pigeon"
|
||||
}), Pair(1, new {
|
||||
name = "Barn Owl"
|
||||
}), Pair(2, new {
|
||||
name = "Parrot"
|
||||
}))
|
||||
List(Pair(0, new {
|
||||
name = "Wood Pigeon"
|
||||
}), Pair(1, new {
|
||||
name = "Barn Owl"
|
||||
}), Pair(2, new {
|
||||
name = "Parrot"
|
||||
}))
|
||||
}
|
||||
["join"] {
|
||||
""
|
||||
@@ -386,5 +542,17 @@ examples {
|
||||
Albatross
|
||||
Elf Owl
|
||||
"""
|
||||
"Wood PigeonBarn OwlParrot"
|
||||
"""
|
||||
Wood Pigeon
|
||||
Barn Owl
|
||||
Parrot
|
||||
"""
|
||||
"Wood PigeonBarn OwlParrot"
|
||||
"""
|
||||
Wood Pigeon
|
||||
Barn Owl
|
||||
Parrot
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/listingTypeCheckError8.err
vendored
Normal file
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/listingTypeCheckError8.err
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Expected value of type `String`, but got type `Int`.
|
||||
Value: 0
|
||||
|
||||
x | local b = a as Listing<Listing<String>>
|
||||
^^^^^^
|
||||
at listingTypeCheckError8#b (file:///$snippetsDir/input/errors/listingTypeCheckError8.pkl)
|
||||
|
||||
x | local a = new Listing { new Listing { 0 } }
|
||||
^
|
||||
at listingTypeCheckError8#a[#1][#1] (file:///$snippetsDir/input/errors/listingTypeCheckError8.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/listingTypeCheckError9.err
vendored
Normal file
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/listingTypeCheckError9.err
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Expected value of type `listingTypeCheckError9#Bar`, but got type `listingTypeCheckError9#Foo`.
|
||||
Value: new Foo {}
|
||||
|
||||
x | local c = b as Listing<Bar>
|
||||
^^^
|
||||
at listingTypeCheckError9#c (file:///$snippetsDir/input/errors/listingTypeCheckError9.pkl)
|
||||
|
||||
x | local a = new Listing { new Foo {} }
|
||||
^^^^^^^^^^
|
||||
at listingTypeCheckError9#a[#1] (file:///$snippetsDir/input/errors/listingTypeCheckError9.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/mappingTypeCheckError11.err
vendored
Normal file
15
pkl-core/src/test/files/LanguageSnippetTests/output/errors/mappingTypeCheckError11.err
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Expected value of type `mappingTypeCheckError11#Bar`, but got type `mappingTypeCheckError11#Foo`.
|
||||
Value: new Foo {}
|
||||
|
||||
x | local c = b as Mapping<Int, Bar>
|
||||
^^^
|
||||
at mappingTypeCheckError11#c (file:///$snippetsDir/input/errors/mappingTypeCheckError11.pkl)
|
||||
|
||||
x | local a = new Mapping { [0] = new Foo {} }
|
||||
^^^^^^^^^^
|
||||
at mappingTypeCheckError11#a[0] (file:///$snippetsDir/input/errors/mappingTypeCheckError11.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
8
pkl-core/src/test/files/LanguageSnippetTests/output/listings/cacheStealing.pcf
vendored
Normal file
8
pkl-core/src/test/files/LanguageSnippetTests/output/listings/cacheStealing.pcf
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
foo1 {
|
||||
"hello"
|
||||
}
|
||||
foo2 {
|
||||
"hello"
|
||||
}
|
||||
res1 = true
|
||||
res2 = true
|
||||
4
pkl-core/src/test/files/LanguageSnippetTests/output/listings/cacheStealingTypeCheck.pcf
vendored
Normal file
4
pkl-core/src/test/files/LanguageSnippetTests/output/listings/cacheStealingTypeCheck.pcf
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
foo {
|
||||
"abcdx"
|
||||
"ax"
|
||||
}
|
||||
@@ -38,3 +38,9 @@ res18 = "Expected value of type `Duration`, but got type `DataSize`. Value: 5.mb
|
||||
res18b = "Expected value of type `Duration`, but got type `DataSize`. Value: 5.mb"
|
||||
res19 = "abc"
|
||||
res20 = Pair(Map("abc", List("def")), Map("abc", List("def")))
|
||||
res21 {
|
||||
"John Birdo"
|
||||
}
|
||||
res22 = Pair(new {
|
||||
"John Birdo"
|
||||
}, 0)
|
||||
|
||||
15
pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAliasContext.err
vendored
Normal file
15
pkl-core/src/test/files/LanguageSnippetTests/output/types/typeAliasContext.err
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
–– Pkl Error ––
|
||||
Type constraint `endsWith(lastName)` violated.
|
||||
Value: "Jimmy Bird"
|
||||
|
||||
x | typealias Birds = Listing<String(endsWith(lastName))>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
at typeAliasContext#res (file:///$snippetsDir/input/types/helpers/originalTypealias.pkl)
|
||||
|
||||
x | res: originalTypealias.Birds = new { "Jimmy Bird" }
|
||||
^^^^^^^^^^^^
|
||||
at typeAliasContext#res[#1] (file:///$snippetsDir/input/types/typeAliasContext.pkl)
|
||||
|
||||
xxx | text = renderer.renderDocument(value)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
at pkl.base#Module.output.text (pkl:base)
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -117,7 +117,7 @@ class DocGenerator(
|
||||
}
|
||||
|
||||
private fun DocPackage.deletePackageDir() {
|
||||
outputDir.resolve("$name/$version").deleteRecursively()
|
||||
outputDir.resolve(IoUtils.encodePath("$name/$version")).deleteRecursively()
|
||||
}
|
||||
|
||||
private fun createSymlinks(currentPackagesData: List<PackageData>) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.pkl.gradle;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -27,6 +28,7 @@ import org.gradle.api.GradleException;
|
||||
import org.gradle.api.NamedDomainObjectContainer;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Transformer;
|
||||
import org.gradle.api.file.SourceDirectorySet;
|
||||
import org.gradle.api.plugins.Convention;
|
||||
import org.gradle.api.provider.Provider;
|
||||
@@ -64,6 +66,7 @@ import org.pkl.gradle.task.PkldocTask;
|
||||
import org.pkl.gradle.task.ProjectPackageTask;
|
||||
import org.pkl.gradle.task.ProjectResolveTask;
|
||||
import org.pkl.gradle.task.TestTask;
|
||||
import org.pkl.gradle.utils.PluginUtils;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class PklPlugin implements Plugin<Project> {
|
||||
@@ -456,6 +459,9 @@ public class PklPlugin implements Plugin<Project> {
|
||||
|
||||
private List<File> getTransitiveModules(AnalyzeImportsTask analyzeTask) {
|
||||
var outputFile = analyzeTask.getOutputFile().get().getAsFile().toPath();
|
||||
if (!analyzeTask.getOnlyIf().isSatisfiedBy(analyzeTask)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
try {
|
||||
var contents = Files.readString(outputFile);
|
||||
ImportGraph importGraph = ImportGraph.parseFromJson(contents);
|
||||
@@ -470,9 +476,16 @@ public class PklPlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
private <T extends ModulesTask, S extends ModulesSpec> void configureModulesTask(
|
||||
T task, S spec, @Nullable TaskProvider<AnalyzeImportsTask> analyzeImportsTask) {
|
||||
T task,
|
||||
S spec,
|
||||
@Nullable TaskProvider<AnalyzeImportsTask> analyzeImportsTask,
|
||||
@Nullable Transformer<List<?>, List<?>> mapSourceModules) {
|
||||
configureBaseTask(task, spec);
|
||||
task.getSourceModules().set(spec.getSourceModules());
|
||||
if (mapSourceModules != null) {
|
||||
task.getSourceModules().set(spec.getSourceModules().map(mapSourceModules));
|
||||
} else {
|
||||
task.getSourceModules().set(spec.getSourceModules());
|
||||
}
|
||||
task.getNoProject().set(spec.getNoProject());
|
||||
task.getProjectDir().set(spec.getProjectDir());
|
||||
task.getOmitProjectSettings().set(spec.getOmitProjectSettings());
|
||||
@@ -484,6 +497,11 @@ public class PklPlugin implements Plugin<Project> {
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends ModulesTask, S extends ModulesSpec> void configureModulesTask(
|
||||
T task, S spec, @Nullable TaskProvider<AnalyzeImportsTask> analyzeImportsTask) {
|
||||
configureModulesTask(task, spec, analyzeImportsTask, null);
|
||||
}
|
||||
|
||||
private TaskProvider<AnalyzeImportsTask> createAnalyzeImportsTask(ModulesSpec spec) {
|
||||
var outputFile =
|
||||
project
|
||||
@@ -496,11 +514,26 @@ public class PklPlugin implements Plugin<Project> {
|
||||
spec.getName() + "GatherImports",
|
||||
AnalyzeImportsTask.class,
|
||||
task -> {
|
||||
configureModulesTask(task, spec, null);
|
||||
configureModulesTask(
|
||||
task,
|
||||
spec,
|
||||
null,
|
||||
(modules) ->
|
||||
// only need to analyze imports of file-based modules; it's unlikely that a
|
||||
// non-file-based module will import a file-based module due to security
|
||||
// manager trust levels (see
|
||||
// org.pkl.core.SecurityManagers.getDefaultTrustLevel).
|
||||
modules.stream()
|
||||
.map(PluginUtils::parseModuleNotationToUri)
|
||||
.filter(
|
||||
(it) ->
|
||||
it.getScheme() == null || it.getScheme().equalsIgnoreCase("file"))
|
||||
.toList());
|
||||
task.setDescription("Compute the set of imports declared by input modules");
|
||||
task.setGroup("build");
|
||||
task.getOutputFormat().set(OutputFormat.JSON.toString());
|
||||
task.getOutputFile().set(outputFile);
|
||||
task.onlyIf(ignored -> !task.getSourceModules().get().isEmpty());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,6 @@ package org.pkl.gradle.task;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
@@ -31,10 +28,8 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.InvalidUserDataException;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileSystemLocation;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
@@ -49,9 +44,9 @@ import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.pkl.commons.cli.CliBaseOptions;
|
||||
import org.pkl.core.evaluatorSettings.Color;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.LateInit;
|
||||
import org.pkl.core.util.Nullable;
|
||||
import org.pkl.gradle.utils.PluginUtils;
|
||||
|
||||
public abstract class BasePklTask extends DefaultTask {
|
||||
@Input
|
||||
@@ -74,7 +69,7 @@ public abstract class BasePklTask extends DefaultTask {
|
||||
|
||||
@Internal
|
||||
public Provider<Object> getParsedSettingsModule() {
|
||||
return getSettingsModule().map(this::parseModuleNotation);
|
||||
return getSettingsModule().map(PluginUtils::parseModuleNotation);
|
||||
}
|
||||
|
||||
@InputFile
|
||||
@@ -165,7 +160,7 @@ public abstract class BasePklTask extends DefaultTask {
|
||||
parseModulePath(),
|
||||
getProject().getProjectDir().toPath(),
|
||||
mapAndGetOrNull(getEvalRootDirPath(), Paths::get),
|
||||
mapAndGetOrNull(getSettingsModule(), this::parseModuleNotationToUri),
|
||||
mapAndGetOrNull(getSettingsModule(), PluginUtils::parseModuleNotationToUri),
|
||||
null,
|
||||
getEvalTimeout().getOrNull(),
|
||||
mapAndGetOrNull(getModuleCacheDir(), it1 -> it1.getAsFile().toPath()),
|
||||
@@ -199,100 +194,6 @@ public abstract class BasePklTask extends DefaultTask {
|
||||
return getModulePath().getFiles().stream().map(File::toPath).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the specified source module notation into a "parsed" notation which is then used for
|
||||
* input path tracking and as an argument for the CLI API.
|
||||
*
|
||||
* <p>This method accepts the following input types:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link URI} - used as is.
|
||||
* <li>{@link File} - used as is.
|
||||
* <li>{@link Path} - converted to a {@link File}. This conversion may fail because not all
|
||||
* {@link Path}s point to the local file system.
|
||||
* <li>{@link URL} - converted to a {@link URI}. This conversion may fail because {@link URL}
|
||||
* allows for URLs which are not compliant URIs.
|
||||
* <li>{@link CharSequence} - first, converted to a string. If this string is "URI-like" (see
|
||||
* {@link IoUtils#isUriLike(String)}), then we attempt to parse it as a {@link URI}, which
|
||||
* may fail. Otherwise, we attempt to parse it as a {@link Path}, which is then converted to
|
||||
* a {@link File} (both of these operations may fail).
|
||||
* <li>{@link FileSystemLocation} - converted to a {@link File} via the {@link
|
||||
* FileSystemLocation#getAsFile()} method.
|
||||
* </ul>
|
||||
*
|
||||
* In case the returned value is determined to be a {@link URI}, then this URI is first checked
|
||||
* for whether its scheme is {@code file}, like {@code file:///example/path}. In such case, this
|
||||
* method returns a {@link File} corresponding to the file path in the URI. Otherwise, a {@link
|
||||
* URI} instance is returned.
|
||||
*
|
||||
* @throws InvalidUserDataException In case the input is none of the types described above, or
|
||||
* when the underlying value cannot be parsed correctly.
|
||||
*/
|
||||
protected Object parseModuleNotation(Object notation) {
|
||||
if (notation instanceof URI uri) {
|
||||
if ("file".equals(uri.getScheme())) {
|
||||
return new File(uri.getPath());
|
||||
}
|
||||
return uri;
|
||||
} else if (notation instanceof File) {
|
||||
return notation;
|
||||
} else if (notation instanceof Path path) {
|
||||
try {
|
||||
return path.toFile();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module file path: " + notation, e);
|
||||
}
|
||||
} else if (notation instanceof URL url) {
|
||||
try {
|
||||
return parseModuleNotation(url.toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + notation, e);
|
||||
}
|
||||
} else if (notation instanceof CharSequence) {
|
||||
var s = notation.toString();
|
||||
if (IoUtils.isUriLike(s)) {
|
||||
try {
|
||||
return parseModuleNotation(IoUtils.toUri(s));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + s, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return Paths.get(s).toFile();
|
||||
} catch (InvalidPathException | UnsupportedOperationException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module file path: " + s, e);
|
||||
}
|
||||
}
|
||||
} else if (notation instanceof FileSystemLocation location) {
|
||||
return location.getAsFile();
|
||||
} else {
|
||||
throw new InvalidUserDataException(
|
||||
"Unsupported value of type "
|
||||
+ notation.getClass()
|
||||
+ " used as a module path: "
|
||||
+ notation);
|
||||
}
|
||||
}
|
||||
|
||||
protected URI parseModuleNotationToUri(Object m) {
|
||||
var parsed1 = parseModuleNotation(m);
|
||||
return parsedModuleNotationToUri(parsed1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts either a file or a URI to a URI. We convert a file to a URI via the {@link
|
||||
* IoUtils#createUri(String)} because other ways of conversion can make relative paths into
|
||||
* absolute URIs, which may break module loading.
|
||||
*/
|
||||
private URI parsedModuleNotationToUri(Object notation) {
|
||||
if (notation instanceof File file) {
|
||||
return IoUtils.createUri(file.getPath());
|
||||
} else if (notation instanceof URI uri) {
|
||||
return uri;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid parsed module notation: " + notation);
|
||||
}
|
||||
|
||||
protected List<Pattern> patternsFromStrings(List<String> patterns) {
|
||||
return patterns.stream().map(Pattern::compile).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,8 +37,8 @@ import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.pkl.commons.cli.CliBaseOptions;
|
||||
import org.pkl.core.evaluatorSettings.Color;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
import org.pkl.core.util.Pair;
|
||||
import org.pkl.gradle.utils.PluginUtils;
|
||||
|
||||
public abstract class ModulesTask extends BasePklTask {
|
||||
// We expose the contents of this property as task inputs via the sourceModuleFiles
|
||||
@@ -84,7 +84,7 @@ public abstract class ModulesTask extends BasePklTask {
|
||||
@Override
|
||||
protected List<URI> getSourceModulesAsUris() {
|
||||
return getSourceModules().get().stream()
|
||||
.map(this::parseModuleNotationToUri)
|
||||
.map(PluginUtils::parseModuleNotationToUri)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public abstract class ModulesTask extends BasePklTask {
|
||||
var files = new ArrayList<File>();
|
||||
var uris = new ArrayList<URI>();
|
||||
for (var m : modules) {
|
||||
var parsed = parseModuleNotation(m);
|
||||
var parsed = PluginUtils.parseModuleNotation(m);
|
||||
if (parsed instanceof File file) {
|
||||
files.add(file);
|
||||
} else if (parsed instanceof URI uri) {
|
||||
@@ -127,28 +127,6 @@ public abstract class ModulesTask extends BasePklTask {
|
||||
return Pair.of(files, uris);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts either a file or a URI to a URI. We convert a relative file to a URI via the {@link
|
||||
* IoUtils#createUri(String)} because other ways of conversion can make relative paths into
|
||||
* absolute URIs, which may break module loading.
|
||||
*/
|
||||
private URI parsedModuleNotationToUri(Object notation) {
|
||||
if (notation instanceof File file) {
|
||||
if (file.isAbsolute()) {
|
||||
return file.toPath().toUri();
|
||||
}
|
||||
return IoUtils.createUri(IoUtils.toNormalizedPathString(file.toPath()));
|
||||
} else if (notation instanceof URI uri) {
|
||||
return uri;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid parsed module notation: " + notation);
|
||||
}
|
||||
|
||||
protected URI parseModuleNotationToUri(Object m) {
|
||||
var parsed1 = parseModuleNotation(m);
|
||||
return parsedModuleNotationToUri(parsed1);
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
@Override
|
||||
public void runTask() {
|
||||
@@ -172,7 +150,7 @@ public abstract class ModulesTask extends BasePklTask {
|
||||
parseModulePath(),
|
||||
getProject().getProjectDir().toPath(),
|
||||
mapAndGetOrNull(getEvalRootDirPath(), Paths::get),
|
||||
mapAndGetOrNull(getSettingsModule(), this::parseModuleNotationToUri),
|
||||
mapAndGetOrNull(getSettingsModule(), PluginUtils::parseModuleNotationToUri),
|
||||
getProjectDir().isPresent() ? getProjectDir().get().getAsFile().toPath() : null,
|
||||
getEvalTimeout().getOrNull(),
|
||||
mapAndGetOrNull(getModuleCacheDir(), it1 -> it1.getAsFile().toPath()),
|
||||
|
||||
128
pkl-gradle/src/main/java/org/pkl/gradle/utils/PluginUtils.java
Normal file
128
pkl-gradle/src/main/java/org/pkl/gradle/utils/PluginUtils.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.pkl.gradle.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.InvalidPathException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import org.gradle.api.InvalidUserDataException;
|
||||
import org.gradle.api.file.FileSystemLocation;
|
||||
import org.pkl.core.util.IoUtils;
|
||||
|
||||
public class PluginUtils {
|
||||
private PluginUtils() {}
|
||||
|
||||
/**
|
||||
* Parses the specified source module notation into a "parsed" notation which is then used for
|
||||
* input path tracking and as an argument for the CLI API.
|
||||
*
|
||||
* <p>This method accepts the following input types:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link URI} - used as is.
|
||||
* <li>{@link File} - used as is.
|
||||
* <li>{@link Path} - converted to a {@link File}. This conversion may fail because not all
|
||||
* {@link Path}s point to the local file system.
|
||||
* <li>{@link URL} - converted to a {@link URI}. This conversion may fail because {@link URL}
|
||||
* allows for URLs which are not compliant URIs.
|
||||
* <li>{@link CharSequence} - first, converted to a string. If this string is "URI-like" (see
|
||||
* {@link IoUtils#isUriLike(String)}), then we attempt to parse it as a {@link URI}, which
|
||||
* may fail. Otherwise, we attempt to parse it as a {@link Path}, which is then converted to
|
||||
* a {@link File} (both of these operations may fail).
|
||||
* <li>{@link FileSystemLocation} - converted to a {@link File} via the {@link
|
||||
* FileSystemLocation#getAsFile()} method.
|
||||
* </ul>
|
||||
*
|
||||
* In case the returned value is determined to be a {@link URI}, then this URI is first checked
|
||||
* for whether its scheme is {@code file}, like {@code file:///example/path}. In such case, this
|
||||
* method returns a {@link File} corresponding to the file path in the URI. Otherwise, a {@link
|
||||
* URI} instance is returned.
|
||||
*
|
||||
* @throws InvalidUserDataException In case the input is none of the types described above, or
|
||||
* when the underlying value cannot be parsed correctly.
|
||||
*/
|
||||
public static Object parseModuleNotation(Object notation) {
|
||||
if (notation instanceof URI uri) {
|
||||
if ("file".equals(uri.getScheme())) {
|
||||
return new File(uri.getPath());
|
||||
}
|
||||
return uri;
|
||||
} else if (notation instanceof File) {
|
||||
return notation;
|
||||
} else if (notation instanceof Path path) {
|
||||
try {
|
||||
return path.toFile();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module file path: " + notation, e);
|
||||
}
|
||||
} else if (notation instanceof URL url) {
|
||||
try {
|
||||
return parseModuleNotation(url.toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + notation, e);
|
||||
}
|
||||
} else if (notation instanceof CharSequence) {
|
||||
var s = notation.toString();
|
||||
if (IoUtils.isUriLike(s)) {
|
||||
try {
|
||||
return parseModuleNotation(IoUtils.toUri(s));
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module URI: " + s, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
return Paths.get(s).toFile();
|
||||
} catch (InvalidPathException | UnsupportedOperationException e) {
|
||||
throw new InvalidUserDataException("Failed to parse Pkl module file path: " + s, e);
|
||||
}
|
||||
}
|
||||
} else if (notation instanceof FileSystemLocation location) {
|
||||
return location.getAsFile();
|
||||
} else {
|
||||
throw new InvalidUserDataException(
|
||||
"Unsupported value of type "
|
||||
+ notation.getClass()
|
||||
+ " used as a module path: "
|
||||
+ notation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts either a file or a URI to a URI. We convert a relative file to a URI via the {@link
|
||||
* IoUtils#createUri(String)} because other ways of conversion can make relative paths into
|
||||
* absolute URIs, which may break module loading.
|
||||
*/
|
||||
public static URI parsedModuleNotationToUri(Object notation) {
|
||||
if (notation instanceof File file) {
|
||||
if (file.isAbsolute()) {
|
||||
return file.toPath().toUri();
|
||||
}
|
||||
return IoUtils.createUri(IoUtils.toNormalizedPathString(file.toPath()));
|
||||
} else if (notation instanceof URI uri) {
|
||||
return uri;
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid parsed module notation: " + notation);
|
||||
}
|
||||
|
||||
public static URI parseModuleNotationToUri(Object m) {
|
||||
var parsed1 = PluginUtils.parseModuleNotation(m);
|
||||
return parsedModuleNotationToUri(parsed1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@NonnullByDefault
|
||||
package org.pkl.gradle.utils;
|
||||
|
||||
import org.pkl.core.util.NonnullByDefault;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,13 +15,17 @@
|
||||
*/
|
||||
package org.pkl.gradle
|
||||
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.readText
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import org.pkl.commons.test.PackageServer
|
||||
|
||||
class PkldocGeneratorsTest : AbstractTest() {
|
||||
@Test
|
||||
fun `generate docs`() {
|
||||
fun `generate docs`(@TempDir tempDir: Path) {
|
||||
PackageServer.populateCacheDir(tempDir)
|
||||
writeFile(
|
||||
"build.gradle",
|
||||
"""
|
||||
@@ -32,7 +36,8 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
pkl {
|
||||
pkldocGenerators {
|
||||
pkldoc {
|
||||
sourceModules = ["person.pkl", "doc-package-info.pkl"]
|
||||
moduleCacheDir = file("${tempDir.toUri()}")
|
||||
sourceModules = ["package://localhost:0/birds@0.5.0", "person.pkl", "doc-package-info.pkl"]
|
||||
outputDir = file("build/pkldoc")
|
||||
settingsModule = "pkl:settings"
|
||||
}
|
||||
@@ -94,6 +99,39 @@ class PkldocGeneratorsTest : AbstractTest() {
|
||||
checkTextContains(moduleFile.readText(), "<html>", "Person", "Address", "other")
|
||||
checkTextContains(personFile.readText(), "<html>", "name", "addresses")
|
||||
checkTextContains(addressFile.readText(), "<html>", "street", "zip")
|
||||
|
||||
val birdsPackageFile = baseDir.resolve("localhost(3a)0/birds/0.5.0/index.html")
|
||||
assertThat(birdsPackageFile).exists()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `generate docs only for package`(@TempDir tempDir: Path) {
|
||||
PackageServer.populateCacheDir(tempDir)
|
||||
writeFile(
|
||||
"build.gradle",
|
||||
"""
|
||||
plugins {
|
||||
id "org.pkl-lang"
|
||||
}
|
||||
|
||||
pkl {
|
||||
pkldocGenerators {
|
||||
pkldoc {
|
||||
moduleCacheDir = file("${tempDir.toUri()}")
|
||||
sourceModules = ["package://localhost:0/birds@0.5.0"]
|
||||
outputDir = file("build/pkldoc")
|
||||
settingsModule = "pkl:settings"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
runTask("pkldoc")
|
||||
|
||||
val baseDir = testProjectDir.resolve("build/pkldoc")
|
||||
val birdsPackageFile = baseDir.resolve("localhost(3a)0/birds/0.5.0/index.html")
|
||||
assertThat(birdsPackageFile).exists()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -130,5 +130,5 @@ class ServerMessagePackDecoder(unpacker: MessageUnpacker) : BaseMessagePackDecod
|
||||
}
|
||||
|
||||
private fun unpackExternalReader(map: Map<Value, Value>): ExternalReader =
|
||||
ExternalReader(unpackString(map, "executable"), unpackStringListOrNull(map, "arguments")!!)
|
||||
ExternalReader(unpackString(map, "executable"), unpackStringListOrNull(map, "arguments"))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -36,7 +36,7 @@
|
||||
///
|
||||
/// Warning: Although this module is ready for initial use,
|
||||
/// benchmark results may be inaccurate or inconsistent.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.Benchmark
|
||||
|
||||
import "pkl:platform" as _platform
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -63,7 +63,7 @@
|
||||
/// @Deprecated { message = "Use `com.example.Birds.Parrot` instead" }
|
||||
/// amends "pkl:PackageInfo"
|
||||
/// ```
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.DocPackageInfo
|
||||
|
||||
import "pkl:reflect"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@
|
||||
///
|
||||
/// title = "Title displayed in the header of each page"
|
||||
/// ```
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.DocsiteInfo
|
||||
|
||||
import "pkl:reflect"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Common settings for Pkl's own evaluator.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
@Since { version = "0.26.0" }
|
||||
module pkl.EvaluatorSettings
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -64,7 +64,7 @@
|
||||
/// value = project
|
||||
/// }
|
||||
/// ```
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.Project
|
||||
|
||||
import "pkl:EvaluatorSettings" as EvaluatorSettingsModule
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@
|
||||
/// These tools differentiate from [pkl:reflect][reflect] in that they parse Pkl modules, but do not
|
||||
/// execute any code within these modules.
|
||||
@Since { version = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.analyze
|
||||
|
||||
// used by doc comments
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,7 @@
|
||||
/// Fundamental properties, methods, and classes for writing Pkl programs.
|
||||
///
|
||||
/// Members of this module are automatically available in every Pkl module.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.base
|
||||
|
||||
import "pkl:jsonnet"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// A JSON parser.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.json
|
||||
|
||||
/// A JSON parser.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// A [Jsonnet](https://jsonnet.org) renderer.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.jsonnet
|
||||
|
||||
/// Constructs an [ImportStr].
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@
|
||||
///
|
||||
/// Note that some mathematical functions, such as `sign()`, `abs()`, and `round()`,
|
||||
/// are directly defined in classes [Number], [Int], and [Float].
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.math
|
||||
|
||||
/// The minimum [Int] value: `-9223372036854775808`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Information about the platform that the current program runs on.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.platform
|
||||
|
||||
/// The platform that the current program runs on.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
/// A renderer for [Protocol Buffers](https://developers.google.com/protocol-buffers).
|
||||
/// Note: This module is _experimental_ and not ready for production use.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.protobuf
|
||||
|
||||
import "pkl:reflect"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -26,7 +26,7 @@
|
||||
/// - Documentation generators (such as *Pkldoc*)
|
||||
/// - Code generators (such as *pkl-codegen-java* and *pkl-codegen-kotlin*)
|
||||
/// - Domain-specific schema validators
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.reflect
|
||||
|
||||
import "pkl:base"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Information about the Pkl release that the current program runs on.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.release
|
||||
|
||||
import "pkl:semver"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Parsing, comparison, and manipulation of [semantic version](https://semver.org/spec/v2.0.0.html) numbers.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.semver
|
||||
|
||||
/// Tells whether [version] is a valid semantic version number.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@
|
||||
/// Every settings file must amend this module.
|
||||
/// Unless CLI commands and build tool plugins are explicitly configured with a settings file,
|
||||
/// they will use `~/.pkl/settings.pkl` or the defaults specified in this module.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.settings
|
||||
|
||||
import "pkl:EvaluatorSettings"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Utilities for generating shell scripts.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.shell
|
||||
|
||||
/// Escapes [str] by enclosing it in single quotes.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -18,7 +18,7 @@
|
||||
///
|
||||
/// To write tests, amend this module and define [facts] or [examples] (or both).
|
||||
/// To run tests, evaluate the amended module.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
open module pkl.test
|
||||
|
||||
/// Named groups of boolean expressions that are expected to evaluate to [true].
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// An XML renderer.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.xml
|
||||
|
||||
/// Renders values as XML.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
// Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,7 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// A YAML 1.2 compliant YAML parser.
|
||||
@ModuleInfo { minPklVersion = "0.27.0" }
|
||||
@ModuleInfo { minPklVersion = "0.27.2" }
|
||||
module pkl.yaml
|
||||
|
||||
/// A YAML parser.
|
||||
|
||||
Reference in New Issue
Block a user