Initial commit

This commit is contained in:
Peter Niederwieser
2016-01-19 14:51:19 +01:00
committed by Dan Chao
commit ecad035dca
2972 changed files with 211653 additions and 0 deletions

232
stdlib/Benchmark.pkl Normal file
View File

@@ -0,0 +1,232 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A template for writing and running benchmarks.
///
/// To write benchmarks, amend this module and define [microbenchmarks],
/// [outputBenchmarks], and/or [parserBenchmarks].
/// To run benchmarks, evaluate the amended module.
///
/// Each benchmark run consists of *m* [iterations] of *n* repetitions.
/// The number of repetitions is controlled indirectly via [iterationTime].
///
/// The reported metric is time per repetition.
/// It is calculated as measured iteration time divided by number of repetitions.
///
/// Benchmarks are warmed up for approximately the same time they are measured.
/// The goal is to measure steady state performance.
///
/// The benchmark [report] details benchmark [results][BenchmarkResult]
/// and the [platform][_platform.Platform] that benchmarks were run on.
/// By default, the report is rendered in *Pcf*.
/// To render the report in a different format, override `output.renderer`.
///
/// Warning: Although this module is ready for initial use,
/// benchmark results may be inaccurate or inconsistent.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.Benchmark
import "pkl:platform" as _platform
/// The number of benchmark iterations to run.
///
/// This value can be [overridden][Benchmark.iterations] per benchmark.
iterations: UInt32 = 15
/// The approximate time to spend on each benchmark iteration.
///
/// This value indirectly controls the number of repetitions per iteration.
///
/// This value can be [overridden][Benchmark.iterationTime] per benchmark.
iterationTime: Duration = 100.ms
/// Whether to report detailed results such as [BenchmarkResult.samples].
///
/// This value can be [overridden][Benchmark.isVerbose] per benchmark.
isVerbose: Boolean = false
/// Benchmarks that measure the time taken to evaluate an expression.
///
/// Mapping keys are the benchmarks' descriptive names.
microbenchmarks: Mapping<String, Microbenchmark> = new {
default {
iterations = module.iterations
iterationTime = module.iterationTime
isVerbose = module.isVerbose
}
}
/// Benchmarks that measure the time taken to render a module's output.
///
/// Mapping keys are the benchmarks' descriptive names.
outputBenchmarks: Mapping<String, OutputBenchmark> = new {
default {
iterations = module.iterations
iterationTime = module.iterationTime
isVerbose = module.isVerbose
}
}
/// Benchmarks that measure the time taken to parse a module's source code into an abstract syntax tree.
///
/// Mapping keys are the benchmarks' descriptive names.
parserBenchmarks: Mapping<String, ParserBenchmark> = new {
default {
iterations = module.iterations
iterationTime = module.iterationTime
isVerbose = module.isVerbose
}
}
/// The report containing benchmark results. Typically not configured from user code.
report: BenchmarkReport = new {
platform = _platform.current
when (!module.microbenchmarks.isEmpty) {
microbenchmarks {
for (name, benchmark in module.microbenchmarks) {
[name] = benchmark.run()
}
}
}
when (!module.outputBenchmarks.isEmpty) {
outputBenchmarks {
for (name, benchmark in module.outputBenchmarks) {
[name] = benchmark.run()
}
}
}
when (!module.parserBenchmarks.isEmpty) {
parserBenchmarks {
for (name, benchmark in module.parserBenchmarks) {
[name] = benchmark.run()
}
}
}
}
/// Common base class for benchmarks.
abstract class Benchmark {
/// The number of benchmark iterations to run.
iterations: UInt32
/// The approximate time to spend on each benchmark iteration.
///
/// This value indirectly controls the number of repetitions per iteration.
iterationTime: Duration
/// Whether to report detailed results such as [BenchmarkResult.samples].
isVerbose: Boolean
/// Runs this benchmark. Typically not called from user code.
abstract function run(): BenchmarkResult
}
/// The result of running a benchmark.
class BenchmarkResult {
/// The number of iterations run.
iterations: UInt32
/// The number of repetitions run per iteration.
repetitions: UInt
/// The average time that a repetition took to complete in each iteration,
/// calculated as measured iteration time divided by number of repetitions.
///
/// This property is only set if [Benchmark.isVerbose] is [true].
samples: List<Duration>(length == iterations)?
/// The minimum of [samples].
min: Duration
/// The maximum of [samples].
max: Duration
/// The mean of [samples].
mean: Duration
/// The standard deviation of [samples].
stdev: Duration
/// The margin of error for [mean] at 99% confidence level.
error: Duration
}
/// A benchmark that measures the time taken to evaluate an expression.
class Microbenchmark extends Benchmark {
/// The expression to evaluate.
expression: Any
external function run(): BenchmarkResult
}
/// A benchmark that measures the time taken to render a module's output.
class OutputBenchmark extends Benchmark {
/// The module to evaluate.
sourceModule: Module
external function run(): BenchmarkResult
}
/// A benchmark that measures the time taken to parse a module's source code.
class ParserBenchmark extends Benchmark {
/// The module source code to parse.
@SourceCode { language = "Pkl" }
sourceText: String
/// The effective URI of [sourceText].
///
/// If [sourceText] contains relative imports, set [sourceUri] so that these imports may be
/// resolved.
sourceUri: String = "repl:text"
external function run(): BenchmarkResult
}
/// The results of running a module's benchmarks.
class BenchmarkReport {
/// The results of the microbenchmarks that were run.
///
/// Mapping keys are the benchmarks' descriptive names.
microbenchmarks: Mapping<String, BenchmarkResult>?
/// The results of the output benchmarks that were run.
///
/// Mapping keys are the benchmarks' descriptive names.
outputBenchmarks: Mapping<String, BenchmarkResult>?
/// The results of the parser benchmarks that were run.
///
/// Mapping keys are the benchmarks' descriptive names.
parserBenchmarks: Mapping<String, BenchmarkResult>?
/// The platform that benchmarks were run on.
platform: _platform.Platform
}
output {
value = report
renderer = new PcfRenderer {
omitNullProperties = true
converters {
// round durations to two decimal places
[Duration] = (it: Duration) -> it.value.toFixed(2).toFloat().toDuration(it.unit)
}
}
}

196
stdlib/DocPackageInfo.pkl Normal file
View File

@@ -0,0 +1,196 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Template for _doc-package-info.pkl_, the descriptor for a package.
///
/// _NOTE_: A doc package is a way to generate documentation for modules that are not published
/// via the [Project.Package] mechanism.
/// Packages published via the [Project.Package] mechanism can have their documentation
/// generated directly by passing the resulting Package URI into Pkldoc.
///
/// A documentation package is a set of related modules that are versioned together.
/// Each package must have a descriptor that
/// * amends this template
/// * is named _doc-package-info.pkl_
/// * is passed to the _pkldoc_ command together with the modules to generate documentation for.
///
/// Each module to generate documentation must declare a module name that starts with a package [name].
/// For example, the following are valid module declarations for package _com.example_:
/// * `module com.example.Birds`
/// * `module com.example.Birds.Parrot`
///
/// The part of the module name that comes after the package name
/// must match the module's relative path in its source code repository.
/// For example, module _com.example.Birds.Parrot_
/// is expected to exist at path _Birds/Parrot.pkl_ within the package root.
///
/// A typical descriptor for a package looks as follows:
///
/// ```
/// /// The overview documentation for this package.
/// /// The first paragraph is the mandatory _summary_.
/// /// Try to keep the summary short; a single sentence is common.
/// ///
/// /// Subsequent paragraphs are separated by an empty line and collapsed by default.
/// /// They can use *Markdown syntax* and Pkldoc links such as [String].
/// amends "pkl:DocPackageInfo"
///
/// name = "com.example.Birds"
/// importUri = "https://example.com/Birds"
/// authors { "pigeon@example.com" }
/// sourceCode = "https://github.com/apple/birds/"
/// sourceCodeUrlScheme = "https://github.com/apple/birds/blob/\(version)%{path}#L%{line}-%{endLine}"
/// issueTracker = "https://github.com/apple/birds/issues"
/// version = "1.7.0"
/// ```
///
/// To deprecate a package, deprecate its descriptor:
///
/// ```
/// @Deprecated { message = "Use `com.example.Birds.Parrot` instead" }
/// amends "pkl:PackageInfo"
/// ```
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.DocPackageInfo
import "pkl:reflect"
import "pkl:semver"
// used by doc comments
import "pkl:Project"
import "pkl:DocPackageInfo"
/// The name of this package.
name: PackageName
/// The version of this package.
///
/// Use `"0.0.0"` for unversioned packages.
version: PackageVersion
/// The import base URI for modules in this package.
///
/// Module import URIs are constructed from this URI as follows:
/// `"\(importUri)\(modulePath)"` where `modulePath` is
/// `moduleName.removePrefix(name).replaceAll(".", "/")`.
/// For example, if package name is `foo.bar` and module name is `foo.bar.baz.qux`,
/// then `modulePath` is `baz/qux`.
importUri: Uri(endsWith("/"))
/// The URI representing the package itself, if exists.
uri: Uri?
/// The authors' emails for this package.
///
/// Email addresses must adhere to
/// [RFC5322 mailbox](https://www.rfc-editor.org/rfc/rfc5322#section-3.4) specification.
///
/// Example:
/// ```
/// email { "Johnny Appleseed <johnny.appleseed@example.com>" }
/// ```
authors: Listing<String>
/// The source code repository for this package.
///
/// Example:
/// ```
/// sourceCode = "https://github.com/myorg/myproject"
/// ```
sourceCode: Uri?
/// The web URL of the source code for this package *version*.
///
/// The following placeholders are available:
///
/// - `%{path}`
/// absolute file path of the file to open
/// - `%{line}`
/// start line number to navigate to
/// - `%{endLine}`
/// end line number to navigate to
///
/// The `%{path}` placeholder is derived from the module's name relative to the package name.
/// The module's name is expected to be prefixed by the package name.
/// In Pkl terms, `path` can be thought of as
/// `"/" + moduleName.replaceFirst(packageName).replaceAll(".", "/") + ".pkl"`.
///
/// For example, if package name is `foo.bar` and module name is `foo.bar.baz.qux`,
/// then `%{path}` is `/baz/qux.pkl`.
///
/// Example:
///
/// ```
/// sourceCodeUrlScheme = "https://github.com/user/repo/blob/v\(version)%{path}#L%{line}-L%{endLine}"`
/// ```
sourceCodeUrlScheme: String?
/// The web URL of the issue tracker for this package.
issueTracker: Uri
/// The packages depended on by this package.
///
/// Used to display package dependencies and to create documentation links.
/// Set automatically for Pkl Hub packages.
dependencies: Listing<PackageDependency>(isDistinctBy((it) -> it.name))
/// Any extra attributes to add to the documentation.
extraAttributes: Mapping<String, String>
/// A package depended on by this package.
class PackageDependency {
/// The name of the depended-on package.
name: PackageName
/// The version of the depended-on package.
///
/// Use `"0.0.0"` for unversioned packages.
version: PackageVersion
/// The source code repository of the depended-upon package.
sourceCode: Uri(endsWith("/"))
/// The source code scheme with placeholders.
///
/// See [DocPackageInfo.sourceCodeUrlScheme] for more details.
sourceCodeUrlScheme: String?
/// The web URL of the Pkldoc page for the depended-on package *version*,
/// Only needs to be set if the depended-on package belongs to a different Pkldoc website.
documentation: Uri(endsWith("/"))?
}
/// A package name.
typealias PackageName =
String(!contains("/"))
/// A package version.
typealias PackageVersion =
String(semver.isValid(this))
@Unlisted
fixed overview: String(!isBlank) = moduleMirror.docComment ??
throw("""
Missing overview documentation for package `\(name)`.
To fix this problem, add a doc comment to `doc-package-info.pkl` (above `amends "pkl:DocPackageInfo"`).
""")
@Unlisted
fixed overviewImports: Map<String, Uri> = moduleMirror.imports
@Unlisted
fixed annotations: List<Annotation> = moduleMirror.annotations
local moduleMirror = reflect.Module(this)

50
stdlib/DocsiteInfo.pkl Normal file
View File

@@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Template for _docsite-info.pkl_, the descriptor for a Pkldoc website.
///
/// A website generated by Pkldoc can optionally have a descriptor that
/// * amends this template
/// * is named _docsite-info.pkl_
/// * is passed to the _pkldoc_ command together with the modules to generate documentation for.
///
/// A typical descriptor looks as follows:
/// ```
/// /// The optional overview documentation displayed on the main page of the website.
/// ///
/// /// Subsequent paragraphs are separated by an empty line and collapsed by default.
/// /// They can use *Markdown syntax* and Pkldoc links such as [String].
/// amends "pkl:DocsiteInfo"
///
/// title = "Title displayed in the header of each page"
/// ```
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.DocsiteInfo
import "pkl:reflect"
/// The title of this Pkldoc website.
///
/// This is displayed in the header of each page.
title: String?
@Unlisted
fixed overview: String? = moduleMirror.docComment
@Unlisted
fixed overviewImports: Map<String, Uri> = moduleMirror.imports
local moduleMirror = reflect.Module(this)

498
stdlib/Project.pkl Normal file
View File

@@ -0,0 +1,498 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A manifest that defines the presence of a project.
///
/// A project is useful for defining [dependencies], and also for defining common evaluator
/// [settings].
///
/// A project is a directory that contains a project file at its root.
/// The project file is a file named `PklProject` exactly, that amends or embeds `"pkl:Project"`.
///
/// When evaluating from the CLI, the project directory can be specified explicitly using
/// `--project-dir` flag, or is determined implicitly by walking up the working directory, looking
/// for a directory containing a `PklProject` file.
///
/// When using the API libraries (e.g. _pkl-swift_, _pkl-go_ or _pkl-config-java_), the project must be
/// explicitly stated via the evaluator builder.
///
/// ## Embedding [Project]
///
/// In a project file, instead of amending `pkl:Project`, it is possible simply set the
/// `output.value` property of a module to an instance of [Project].
/// This allows defining higher levels of abstraction that encapsulate an underlying [Project]
/// definition.
///
/// When defining an abstraction, it is important to:
/// 1. Set the module's `output.value` to the underlying project output.
/// 2. Set [projectFileUri] to the enclosing module's URI.
/// This is necessary to determine the correct project directory, as well as for resolving
/// local project dependencies correctly.
///
/// The [newInstance()] helper method exists as a convenient way to set this when embedding
/// project definitions.
///
/// Example:
/// ```
/// module MyTeamProject
///
/// import "pkl:Project"
///
/// /// The package name, to be prefixed with `myteam`.
/// packageName: String
///
/// project: Project = (Project.newInstance(module)) {
/// package {
/// name = "myteam.\(packageName)"
/// }
/// }
///
/// output {
/// value = project
/// }
/// ```
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.Project
import "pkl:Project"
import "pkl:reflect"
import "pkl:semver"
/// The details for the package represented by this project.
///
/// This section is used if publishing this project as a package.
package: Package?
/// The tests of the project.
///
/// If set, allows running `pkl test` without specifying the paths to source modules.
///
/// Relative paths are resolved against PklProject's enclosing directory.
///
/// Glob imports can be useful for defining this property.
///
/// Example:
///
/// ```
/// tests = import*("**.test.pkl").keys.toListing()
/// ```
tests: Listing<String>(isDistinct)
/// Tells if the project is a file-based module named `PklProject`.
local isLocalPklProject = (it: Project) ->
it.projectFileUri.startsWith("file:") && it.projectFileUri.endsWith("/PklProject")
/// A local dependency is another [Project] that is local to the file system.
///
/// To declare, use `import("path/to/PklProject")`
typealias LocalDependency = Project(
isLocalPklProject,
this != module,
this.package != null
)
/// The dependencies of this project.
///
/// A dependency is a group of Pkl modules and file resources that can be imported within the
/// project.
/// Within the project, a dependency can be referenced via _dependency notation_, where the name
/// is prefixed with the `@` character.
///
/// For example, given the following descriptor:
///
/// ```
/// dependencies {
/// ["birds"] {
/// uri = "package://example.com/birds@1.0.0"
/// }
/// }
/// ```
///
/// This enables the following snippet:
///
/// ```
/// import "@birds/canary.pkl" // Import a module from the `birds` dependency
///
/// birdIndex = read("@birds/index.txt") // Read a file from the `birds` dependency
/// ```
///
/// A dependency's coordinates can either be specified in the form of a [RemoteDependency]
/// descriptor, which gets fetched over the network, or an import of another PklProject file, which
/// represents a package that exists locally.
///
/// Remote dependencies are fetched over HTTPS.
/// When fetching a remote dependency, two HTTPS requests are made.
/// Given dependency URI `package://example.com/foo@0.5.0`, the following requests are made:
///
/// 1. `GET https://example.com/foo@0.5.0` to retreive the metadata JSON file.
/// 2. Given the metadata JSON file, make a GET request to the package URI ZIP archive.
///
/// If this project is published as a package, these dependencies are included within the published
/// package metadata.
///
/// ## Local project dependencies
///
/// A local project can alternatively be used as a dependency.
/// This is useful when structuring a single repository that publishes multiple packages.
///
/// To specify a local project dependency, import the relative `PklProject` file.
///
/// The local project dependency must define its own [package].
///
/// Example:
/// ```
/// dependencies {
/// ["penguins"] = import("../penguins/PklProject")
/// }
/// ```
///
/// ## Resolving dependencies
///
/// Dependencies must be _resolved_ before they can be used.
/// To resolve dependencies, run the CLI command `pkl project resolve`.
/// This will generate a `PklProject.deps.json` file next to the `PklProject` file.
///
/// ### Minimum version selection
///
/// Pkl uses the
/// [minimum version selection algorithm 1](https://research.swtch.com/vgo-mvs#algorithm_1)
/// to resolve dependencies.
/// A dependency is identfied by its package URI, as well as its major semver number.
///
/// To determine the resolved dependencies of a project, the following algorithm is applied:
/// 1. Gather all dependencies, both direct and transitive.
/// 2. For each package's major version, determine the highest declared minor version.
/// 3. Write each resolved depenency to sibling file `PklProject.deps.json`.
dependencies: Mapping<String(!contains("/")), *RemoteDependency|LocalDependency>
/// If set, controls the base evaluator settings when running the evaluator.
///
/// These settings influence the behavior of the evaluator when running the `pkl eval`, `pkl test`,
/// and `pkl repl` CLI commands.
/// Note that command line flags passed to the CLI will override any settings defined here.
///
/// Other integrations can possibly ignore these evaluator settings.
///
/// Evaluator settings do not get published as part of a package.
/// It is not possible for a package dependency to influence the evaluator settings of a project.
evaluatorSettings: EvaluatorSettings
/// The URI of the PklProject file.
///
/// This value is used to resolve relative paths when importing another local project as a
/// dependency.
projectFileUri: String = reflect.Module(module).uri
/// Instantiates a project definintion within the enclosing module.
///
/// This is a convenience method for setting [projectFileUri] to the enclosing module's URI.
///
/// Example:
/// ```
/// myProject: Project = (Project.newInstance(module)) {
/// dependencies { /* etc */ }
/// }
/// ```
function newInstance(enclosingModule: Module): Project = new {
projectFileUri = reflect.Module(enclosingModule).uri
}
local hasVersion = (it: Uri) ->
let (versionSep = it.lastIndexOf("@"))
if (versionSep == -1) false
else let (version = it.drop(versionSep + 1))
semver.parseOrNull(version) != null
typealias PackageUri = Uri(startsWith("package:"), hasVersion)
class RemoteDependency {
/// The URI that this dependency is published to.
uri: PackageUri
/// The checksums of this package.
///
/// If omitted, this is taken from the derived package coordinates.
checksums: Checksums?
}
class Checksums {
/// The [SHA-256](https://en.wikipedia.org/wiki/SHA-2) checksum value of the dependency, in hexadecimal representation.
sha256: String
}
/// An email address, conformant to the
/// [RFC5322 mailbox](https://www.rfc-editor.org/rfc/rfc5322#section-3.4) specification.
///
/// Can be in the form of an address spec, or a named address.
///
/// Examples:
/// * `"johnny.appleseed@example.com"`
/// * `"Johnny Appleseed <johnny.appleseed@example.com>"`
typealias EmailAddress = String(matches(Regex(#".+@\S+|.+<\S+@\S+>"#)))
class Package {
/// The name of this package.
///
/// The package name is only used for display purposes.
///
/// Example:
/// ```
/// name = "myproject"
/// ```
name: String
/// The URI that the package is published to, without the version part.
///
/// This, along with the version, determines the import path for modules and resources published
/// by this package.
///
/// Example:
/// ```
/// baseUri = "package://example.com/myproject"
/// ```
baseUri: Uri(startsWith("package:"))
/// The version of this package.
///
/// Must adhere to semantic versioning.
///
/// Example:
/// ```
/// version = "1.5.0"
/// ```
version: String(semver.isValid(this))
/// The HTTPS location for the zip archive for this package.
///
/// Example:
/// ```
/// packageZipUrl = "https://example.com/artifacts/myproject/\(version).zip"
/// ```
packageZipUrl: Uri(startsWith("https:"))
/// The description of this package.
description: String?
/// The maintainers' emails for this package.
///
/// Email addresses must adhere to
/// [RFC5322 mailbox](https://www.rfc-editor.org/rfc/rfc5322#section-3.4) specification.
///
/// Example:
/// ```
/// email { "Johnny Appleseed <johnny.appleseed@example.com>" }
/// ```
authors: Listing<EmailAddress>
/// The website for this package.
///
/// Example:
/// ```
/// website = "https://example.com/myproject"
/// ```
website: String?
/// The web URL of the Pkldoc documentation for this package.
documentation: Uri(!endsWith("/"))?
/// The source code repository for this package.
///
/// Example:
/// ```
/// sourceCode = "https://github.com/myorg/myproject"
/// ```
sourceCode: String?
/// The source code scheme for this package.
///
/// This is used to transform stack frames for errors arising for this package.
///
/// The following placeholders are available:
///
/// - `%{path}`
/// absolute file path of the file to open
/// - `%{line}`
/// start line number to navigate to
/// - `%{endLine}`
/// end line number to navigate to
/// - `%{column}`
/// column number to navigate to
/// - `%{endColumn}`
/// end column number to navigate to
///
/// For example, if publishing to GitHub, assuming that the version gets published as a tag:
///
/// ```
/// sourceCodeUrlScheme = "\(sourceCode)/blob/\(version)%{path}#L%{line}-L%{endLine}"
/// ```
sourceCodeUrlScheme: String?
/// The license associated with this package.
///
/// If using a common license, use its [SPDX license identifier](https://spdx.org/licenses/).
///
/// If using multiple common licenses, use a
/// [SPDX license expression syntax version 2.0 string](https://spdx.github.io/spdx-spec/v2.3/SPDX-license-expressions/).
/// For example: `"Apache-2.0 or MIT"`.
///
/// If using an uncommon license, also provide its full text in the [licenseText] property.
///
/// Example:
/// ```
/// license = "Apache-2.0"
/// ```
license: (CommonSpdxLicenseIdentifier|String)?
/// The full text of the license associated with this package.
licenseText: String?
/// The web URL of the issue tracker for this package.
issueTracker: String?
/// Paths to the tests that define the API of the package.
///
/// These tests are run as part of the `pkl project package` command.
///
/// Relative paths are resolved against PklProject's enclosing directory.
///
/// Glob imports can be useful for defining this property.
///
/// Example:
///
/// ```
/// tests = import*("**.test.pkl").keys.toListing()
/// ```
apiTests: Listing<String>(isDistinct)
/// Glob patterns describing the set of files to exclude from packaging.
///
/// By default, the project manifest files are excluded, and any paths that start with a dot.
///
/// Glob patterns follows the same glob rules as glob imports and reads.
exclude: Listing<String> = new {
"PklProject"
"PklProject.deps.json"
".**"
}
/// The effective package URI for the package represented by this project.
fixed uri: PackageUri = "\(baseUri)@\(version)"
}
class EvaluatorSettings {
/// The external properties available to Pkl, read using the `prop:` scheme.
externalProperties: Mapping<String, String>?
/// The environment variables available to Pkl, read using the `env:` scheme.
///
/// Example:
/// ```
/// env {
/// ["IS_PROD"] = "true"
/// }
/// ```
env: Mapping<String, String>?
/// The set of module URI patterns that can be imported.
///
/// Each element is a regular expression pattern that is tested against a module import.
///
/// Modules are imported either through an amends or extends clause, an import clause, or an
/// import expression.
///
/// Example:
/// ```
/// allowedModules {
/// "https:"
/// "file:"
/// "package:"
/// "projectpackage:"
/// }
/// ```
allowedModules: Listing<String(isRegex)>?
/// The set of resource URI patterns that can be imported.
///
/// Each element is a regular expression pattern that is tested against a resource read.
///
/// Example:
/// ```
/// allowedResources {
/// "https:"
/// "file:"
/// "package:"
/// "projectpackage:"
/// "env:"
/// "prop:"
/// }
/// ```
allowedResources: Listing<String(isRegex)>?
/// Disables the file system cache for `package:` modules.
///
/// When cacheing is disabled, packages are loaded over the network and stored in memory.
noCache: Boolean?
/// A collection of jars, zips, or directories to be placed into the module path.
///
/// Module path modules and resources may be read and imported using the `modulepath:` scheme.
///
/// Relative paths are resolved against PklProject's enclosing directory.
modulePath: Listing<String>?
/// The duration after which evaluation of a source module will be timed out.
///
/// Note that a timeout is treated the same as a program error in that any subsequent source modules will not be evaluated.
timeout: Duration?
/// The directory where `package:` modules are cached.
///
/// Relative paths are resolved against PklProject's enclosing directory.
moduleCacheDir: String?
/// Restricts access to file-based modules and resources to those located under this directory.
///
/// Relative paths are resolved against PklProject's enclosing directory.
rootDir: String?
}
/// Common software licenses in the [SPDX License List](https://spdx.org/licenses/).
typealias CommonSpdxLicenseIdentifier =
"Apache-2.0"
|"MIT"
|"BSD-2-Clause"
|"BSD-3-Clause"
|"ISC"
|"GPL-3.0"
|"GPL-2.0"
|"MPL-2.0"
|"MPL-1.1"
|"MPL-1.0"
|"AGPL-1.0-only"
|"AGPL-1.0-or-later"
|"AGPL-3.0-only"
|"AGPL-3.0-or-later"
|"LGPL-2.0-only"
|"LGPL-2.0-or-later"
|"LGPL-2.1-only"
|"LGPL-2.1-or-later"
|"LGPL-3.0-only"
|"LGPL-3.0-or-later"
|"EPL-1.0"
|"EPL-2.0"
|"UPL-1.0"
|"BSL-1.0"
|"Unlicense"

3145
stdlib/base.pkl Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// The Pkl standard library.
///
/// The standard library is a set of Pkl modules versioned and distributed together with the language.
///
/// To import a standard library module, use `import "pkl:<identifier>"`.
/// For example, `import "pkl:json"` imports the `pkl.json` module.
///
/// The `pkl.base` module defines the most fundamental properties, methods, and classes for using Pkl.
/// Its members are automatically available in every module and hence it does not need to be imported.
///
/// The default module allowlist (`--allowed-modules`) grants access to all standard library modules.
amends "pkl:DocPackageInfo"
import "pkl:release"
local current = release.current
name = "pkl"
version = (current.version) { build = null }.toString()
importUri = "pkl:/"
authors {
"pkl-oss@group.apple.com"
}
sourceCode =
let (commitish = if (current.version.isNormal()) current.version else current.commitId)
"https://github.com/apple/pkl/blob/\(commitish)/stdlib/"
issueTracker = "https://github.com/apple/pkl/issues"

24
stdlib/gradle.lockfile Normal file
View File

@@ -0,0 +1,24 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.github.ajalt.clikt:clikt-jvm:3.5.1=pkldoc
com.github.ajalt.clikt:clikt:3.5.1=pkldoc
com.tunnelvisionlabs:antlr4-runtime:4.9.0=pkldoc
org.commonmark:commonmark-ext-gfm-tables:0.21.0=pkldoc
org.commonmark:commonmark:0.21.0=pkldoc
org.graalvm.sdk:graal-sdk:22.3.1=pkldoc
org.graalvm.truffle:truffle-api:22.3.1=pkldoc
org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10=pkldoc
org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10=pkldoc
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10=pkldoc
org.jetbrains.kotlin:kotlin-stdlib:1.7.10=pkldoc
org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.1=pkldoc
org.jetbrains.kotlinx:kotlinx-serialization-bom:1.5.1=pkldoc
org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.5.1=pkldoc
org.jetbrains.kotlinx:kotlinx-serialization-core:1.5.1=pkldoc
org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.1=pkldoc
org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1=pkldoc
org.jetbrains:annotations:13.0=pkldoc
org.organicdesign:Paguro:3.10.3=pkldoc
org.snakeyaml:snakeyaml-engine:2.5=pkldoc
empty=archives,default

59
stdlib/json.pkl Normal file
View File

@@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A JSON parser.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.json
/// A JSON parser.
///
/// JSON values are mapped to Pkl values as follows:
///
/// | JSON type | Pkl type |
/// | ----------- | ------------------------------------------------------- |
/// | null | [Null] |
/// | Boolean | [Boolean] |
/// | Number | [Number] |
/// | String | [String] |
/// | Array | [Listing] |
/// | Object | [Dynamic] or [Mapping] depending on [Parser.useMapping] |
///
/// The element order of JSON arrays and objects is maintained.
class Parser {
/// Determines what the parser produces when parsing JSON objects.
///
/// If [true], they turn into a [Mapping].
/// Otherwise, they turn into a [Dynamic].
///
/// If [useMapping] is [false], JSON object properties named "default" will be shadowed by the
/// built-in [Dynamic.default] property.
useMapping: Boolean = false
/// Value converters to apply to parsed values.
///
/// For further information see [PcfRenderer.converters].
converters: Mapping<Class|String(!isEmpty), (unknown) -> unknown>
/// Parses [source] as a JSON document.
///
/// Throws if an error occurs during parsing.
///
/// If [source] is a [Resource], the resource URI is included in parse error messages.
external function parse(source: Resource|String): Value
}
/// Pkl representation of a JSON value.
typealias Value = Null|Boolean|Number|String|Listing|Dynamic|Mapping

108
stdlib/jsonnet.pkl Normal file
View File

@@ -0,0 +1,108 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A [Jsonnet](https://jsonnet.org) renderer.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.jsonnet
/// Constructs an [ImportStr].
function ImportStr(_path: String): ImportStr = new { path = _path }
/// Constructs an [ExtVar].
function ExtVar(_name: String): ExtVar = new { name = _name }
/// Renders values as [Jsonnet](https://jsonnet.org).
///
/// Pkl values are mapped to Jsonnet values as follows:
///
/// | Pkl type | Jsonnet type |
/// | -------------- | --------------- |
/// | [Null] | null |
/// | [Boolean] | boolean |
/// | [Int] | number |
/// | [Float] | number |
/// | [String] | string |
/// | [List] | array |
/// | [Set] | array |
/// | [Map] | object |
/// | [Listing] | array |
/// | [Mapping] | object |
/// | [Dynamic] | object or array |
/// | [Typed] | object |
///
/// Some Pkl types, such as [Duration] and [DataSize], don't have a Jsonnet equivalent.
/// To render values of such types, define _output converters_ (see [Renderer.converters]).
///
/// The output is formatted according to _jsonnetfmt_.
/// To render an `importstr` construct, use [ImportStr()].
/// To render an `std.extVar()` call, use [ExtVar()].
///
/// Example:
/// ```
/// import "pkl:jsonnet"
///
/// server {
/// name = "Pigeon"
/// port = jsonnet.ExtVar("port")
/// message = jsonnet.ImportStr("/etc/motd")
/// timeout = 5.min
/// }
///
/// output {
/// renderer = new jsonnet.Renderer {}
/// converters {
/// [Duration] = (it) -> it.value + it.unit
/// }
/// }
/// ```
class Renderer extends ValueRenderer {
extension = "jsonnet"
/// The characters to use for indenting output.
///
/// If empty (`""`), renders everything on a single line.
///
/// If non-empty, renders object fields and array elements on separate lines,
/// and strings containing newlines as `|||` multiline text blocks,
/// with the given leading line [indent].
indent: String|/*Deprecated*/Null = " "
/// Whether to omit Jsonnet object fields whose value is `null`.
omitNullProperties: Boolean = true
/// Renders [value] as a Jsonnet document.
///
/// Every Jsonnet value is a valid Jsonnet document.
external function renderDocument(value: Any): String
external function renderValue(value: Any): String
}
/// An `importstr` construct that, when evaluated by Jsonnet, returns the content of a UTF-8 text file.
///
/// To construct an [ImportStr], use method [ImportStr()].
class ImportStr {
/// The path of the file to import.
path: String
}
/// A `std.extVar()` call that, when evaluated by Jsonnet, returns the value of an external Jsonnet variable.
///
/// To construct an [ExtVar], use method [ExtVar()].
class ExtVar {
/// The external variable's name.
name: String
}

165
stdlib/math.pkl Normal file
View File

@@ -0,0 +1,165 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Basic mathematical constants and functions.
///
/// Note that some mathematical functions, such as `sign()`, `abs()`, and `round()`,
/// are directly defined in classes [Number], [Int], and [Float].
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.math
/// The minimum [Int] value: `-9223372036854775808`.
external minInt: Int
/// The minimum [Int8] value: -128.
external minInt8: Int8
/// The minimum [Int16] value: -32768.
external minInt16: Int16
/// The minimum [Int32] value: -2147483648.
external minInt32: Int32
/// The maximum [Int] value: `9223372036854775807`.
external maxInt: Int
/// The maximum [Int8] value: 127.
external maxInt8: Int8
/// The maximum [Int16] value: 32767.
external maxInt16: Int16
/// The maximum [Int32] value: 2147483647.
external maxInt32: Int32
/// The maximum [UInt] value: 9223372036854775807.
///
/// Note that [maxUInt] is equal to [maxInt],
/// not `maxInt * 2 + 1` as one might expect.
/// That is, [UInt] has half the range of [Int].
external maxUInt: UInt
/// The maximum [UInt8] value: 255.
external maxUInt8: UInt8
/// The maximum [UInt16] value: 65535.
external maxUInt16: UInt16
/// The maximum [UInt32] value: 4294967295.
external maxUInt32: UInt32
/// The minimum finite [Float] value: `-1.7976931348623157e308`.
///
/// Operations whose value is less than [minFiniteFloat] return -[infinity].
external minFiniteFloat: Float
/// The maximum finite [Float] value: `1.7976931348623157e308`.
///
/// Operations whose value is greater than [maxFiniteFloat] return [infinity].
external maxFiniteFloat: Float
/// The minimum positive [Float] value that is greater than zero: `4.9e-324`.
external minPositiveFloat: Float
/// The number [e][1].
///
/// [1]: https://en.wikipedia.org/wiki/E_(mathematical_constant)
external e: Float
/// The number [π][1].
///
/// [1]: https://en.wikipedia.org/wiki/Pi
external pi: Float
/// Returns e raised to the power of [exponent].
///
/// [1]: https://en.wikipedia.org/wiki/Exponential_function
external function exp(exponent: Number): Float
/// Returns the [square root][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Square_root
external function sqrt(x: Number): Float
/// Returns the [cube root][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Cube_root
external function cbrt(x: Number): Float
/// Returns the [natural logarithm][1] (base e logarithm) of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Natural_logarithm
external function log(x: Number): Float
/// Returns the [base 2 logarithm][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Binary_logarithm
external function log2(x: Number): Float
/// Returns the [base 10 logarithm][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Common_logarithm
external function log10(x: Number): Float
/// Returns the [sine][1] of [angle] given in radians.
///
/// [1]: https://en.wikipedia.org/wiki/Sine
external function sin(angle: Number): Float
/// Returns the [cosine][1] of [angle] given in radians.
///
/// [1]: https://en.wikipedia.org/wiki/Trigonometric_functions///cosine
external function cos(angle: Number): Float
/// Returns the [tangent][1] of [angle] given in radians.
///
/// [1]: https://en.wikipedia.org/wiki/Tangent
external function tan(angle: Number): Float
/// Returns the [arcsine][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
external function asin(x: Number): Float
/// Returns the [arccosine][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
external function acos(x: Number): Float
/// Returns the [arctangent][1] of [x].
///
/// [1]: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions
external function atan(x: Number): Float
/// Returns the [greatest common divisor][1] of [x] and [y].
///
/// [1]: https://en.wikipedia.org/wiki/Greatest_common_divisor
external function gcd(x: Int, y: Int): Int
/// Returns the [least common multiple][1] of [x] and [y].
///
/// [1]: https://en.wikipedia.org/wiki/Least_common_multiple
external function lcm(x: Int, y: Int): Int
/// Returns `true` if [x] is a power of two.
external function isPowerOfTwo(x: Number): Boolean
/// Returns the minimum of [x] and [y].
external function min(x: Number, y: Number): Number
/// Returns the maximum of [x] and [y].
external function max(x: Number, y: Number): Number

79
stdlib/platform.pkl Normal file
View File

@@ -0,0 +1,79 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Information about the platform that the current program runs on.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.platform
/// The platform that the current program runs on.
external current: Platform
/// The platform that a program runs on.
class Platform {
/// The language implementation of this platform.
language: Language
/// The language runtime of this platform.
runtime: Runtime
/// The virtual machine of this platform.
virtualMachine: VirtualMachine
/// The operating system of this platform.
operatingSystem: OperatingSystem
/// The processor of this platform.
processor: Processor
}
/// The language implementation of a platform.
class Language {
/// The version of this language implementation.
version: String
}
/// The language runtime of a platform.
class Runtime {
/// The name of this runtime.
name: String
/// The version of this runtime.
version: String
}
/// The virtual machine of a platform.
class VirtualMachine {
/// The name of this virtual machine.
name: String
/// The version of this virtual machine.
version: String
}
/// The operating system of a platform.
class OperatingSystem {
/// The name of this operating system.
name: String
/// The version of this operating system.
version: String
}
/// The processor of a platform.
class Processor {
/// The instruction set architecture of this processor.
architecture: String
}

40
stdlib/protobuf.pkl Normal file
View File

@@ -0,0 +1,40 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// 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.25.0" }
module pkl.protobuf
import "pkl:reflect"
/// A renderer for [Protocol Buffers](https://developers.google.com/protocol-buffers).
/// Note: This class is _experimental_ and not ready for production use.
///
/// As of this release, only Protocol Buffers' text format is supported.
class Renderer extends ValueRenderer {
/// The characters to use for indenting output.
///
/// Defaults to two spaces.
indent: String = " "
external function renderDocument(value: Any): String
external function renderValue(value: Any): String
/// Returns the canonical name for [type].
external function renderType(type: reflect.Type): String
}

439
stdlib/reflect.pkl Normal file
View File

@@ -0,0 +1,439 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A mirror-based reflection library.
///
/// The `pkl:reflect` module enables *introspection*,
/// the subset of reflection by which a program can examine its own structure.
///
/// The API design is based on the concept of [mirrors](https://en.wikipedia.org/wiki/Mirror_(programming)).
///
/// With the help of this module, advanced tools can be written entirely in Pkl:
///
/// - Documentation generators (such as *Pkldoc*)
/// - Code generators (such as *pkl-codegen-java* and *pkl-codegen-kotlin*)
/// - Domain-specific schema validators
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.reflect
import "pkl:base"
/// A mirror for the [Any] type.
const anyType: DeclaredType = DeclaredType(Class(Any))
/// A mirror for the [Boolean] type.
const booleanType: DeclaredType = DeclaredType(Class(Boolean))
/// A mirror for the [Int] type.
const intType: DeclaredType = DeclaredType(Class(Int))
/// A mirror for the [Int8] type.
const int8Type: DeclaredType = DeclaredType(TypeAlias(Int8))
/// A mirror for the [Int16] type.
const int16Type: DeclaredType = DeclaredType(TypeAlias(Int16))
/// A mirror for the [Int32] type.
const int32Type: DeclaredType = DeclaredType(TypeAlias(Int32))
/// A mirror for the [UInt] type.
const uintType: DeclaredType = DeclaredType(TypeAlias(UInt))
/// A mirror for the [UInt8] type.
const uint8Type: DeclaredType = DeclaredType(TypeAlias(UInt8))
/// A mirror for the [UInt16] type.
const uint16Type: DeclaredType = DeclaredType(TypeAlias(UInt16))
/// A mirror for the [UInt32] type.
const uint32Type: DeclaredType = DeclaredType(TypeAlias(UInt32))
/// A mirror for the [Float] type.
const floatType: DeclaredType = DeclaredType(Class(Float))
/// A mirror for the [String] type.
const stringType: DeclaredType = DeclaredType(Class(String))
/// A mirror for the [Duration] type.
const durationType: DeclaredType = DeclaredType(Class(Duration))
/// A mirror for the [DataSize] type.
const dataSizeType: DeclaredType = DeclaredType(Class(DataSize))
/// A mirror for the `Pair<unknown, unknown>` type.
const pairType: DeclaredType = DeclaredType(Class(Pair))
/// A mirror for the `List<unknown>` type.
const listType: DeclaredType = DeclaredType(Class(List))
/// A mirror for the `Set<unknown>` type.
const setType: DeclaredType = DeclaredType(Class(Set))
/// A mirror for the `Map<unknown, unknown>` type.
const mapType: DeclaredType = DeclaredType(Class(Map))
/// A mirror for the [Object] type.
const objectType: DeclaredType = DeclaredType(Class(Object))
/// A mirror for the [Dynamic] type.
const dynamicType: DeclaredType = DeclaredType(Class(Dynamic))
/// A mirror for the [Typed] type.
const typedType: DeclaredType = DeclaredType(Class(Type))
/// A mirror for the `Listing<unknown>` type.
const listingType: DeclaredType = DeclaredType(Class(Listing))
/// A mirror for the `Mapping<unknown, unknown>` type.
const mappingType: DeclaredType = DeclaredType(Class(Mapping))
/// A mirror for the `module` type.
external const moduleType: ModuleType
/// A mirror for the `unknown` type.
external const unknownType: UnknownType
/// A mirror for the `nothing` type.
external const nothingType: NothingType
/// Returns a mirror for [mod].
///
/// When a module is amended like an object, it is no longer a module.
/// In this case, [Module()] throws.
/// In the following example, `barnOwl` is such an object, created by amending the module `pigeon.pkl`.
///
/// ```
/// barnOwl = import("pigeon.pkl") {
/// name = "Barn Owl"
/// }
/// ```
external const function Module(mod: base.Module): Module
/// Returns a mirror [mod] if it is a module, and otherwise its closest parent that is a module.
///
/// When a module is amended like an object, it is no longer a module.
/// In this case, [moduleOf()] returns a mirror of the closest parent that is.
/// In the following example, `barnOwl` is such an object, created by amending the module `pigeon.pkl`.
///
/// ```
/// barnOwl = import("pigeon.pkl") {
/// name = "Barn Owl"
/// }
/// ```
external const function moduleOf(mod: base.Module): Module
/// Returns a mirror for [clazz].
external const function Class(clazz: base.Class): Class
/// Returns a mirror for [typeAlias].
external const function TypeAlias(typeAlias: base.TypeAlias): TypeAlias
/// Returns a mirror for the declared type for [referent].
external const function DeclaredType(referent: TypeDeclaration): DeclaredType
/// Returns a mirror for the function type with the given [parameterTypes] and [returnType].
external const function FunctionType(parameterTypes: List<Type>, returnType: Type): FunctionType
/// Returns a mirror for the string literal type for [value].
external const function StringLiteralType(value: String): StringLiteralType
/// Returns a mirror for the union of [memberTypes].
external const function UnionType(memberTypes: List<Type>): UnionType
/// Returns a mirror for a type variable for [referent].
external const function TypeVariable(referent: TypeParameter): TypeVariable
/// A program declaration.
abstract external class Declaration {
/// The source location of this declaration.
location: SourceLocation
/// The documentation comment for this declaration, if any.
docComment: String?
/// The annotations attached to this declaration.
annotations: List<Annotation>
/// The modifiers of this declaration.
modifiers: Set<Modifier>
/// The name of this declaration.
name: String
}
/// A module declaration.
external class Module extends Declaration {
hidden reflectee: base.Module
/// The URI of this module.
uri: String
/// The class of this module.
moduleClass: Class(isSubclassOf(Class(base.Module)))
/// The module amended or extended by this module, if any.
supermodule: Module?
/// Tells whether this module amends another module (namely [supermodule]).
///
/// [false] if [supermodule] is [null].
isAmend: Boolean
/// The imports declared in this module.
///
/// Map keys are the identifiers by which imports are accessed within this module.
/// Map values are the URIs of the imported modules.
///
/// Does not cover import expressions.
imports: Map<String, Uri>
/// The classes declared in this module.
///
/// Does not contain [moduleClass].
classes: Map<String, Class>
/// The type aliases declared in this module.
typeAliases: Map<String, TypeAlias>
}
/// A class or type alias declaration.
abstract external class TypeDeclaration extends Declaration {
/// The class or type alias reflected upon.
abstract hidden reflectee: base.Class|base.TypeAlias
/// The module enclosing this type declaration.
///
/// If this type declaration is a module class, [enclosingDeclaration] is the corresponding module instance.
hidden enclosingDeclaration: Module
/// The type parameters of this type declaration.
abstract typeParameters: List<TypeParameter>
}
/// A class declaration.
external class Class extends TypeDeclaration {
/// The class reflected upon.
hidden reflectee: base.Class
/// The type parameters of this class.
///
/// Only standard library classes can have type parameters.
typeParameters: List<TypeParameter>
/// The superclass of this class.
///
/// All classes except [Any] have a superclass.
superclass: Class?
/// The supertype of this class.
///
/// All classes except [Any] have a supertype.
supertype: Type?
/// The properties declared in this class.
///
/// Does not include properties declared in superclasses.
properties: Map<String, Property>
/// The methods declared in this class.
///
/// Does not include methods declared in superclasses.
methods: Map<String, Method>
/// Tells if this class is a subclass of [other].
///
/// Every class is a subclass of itself.
external function isSubclassOf(other: Class): Boolean
}
/// A type alias declaration.
external class TypeAlias extends TypeDeclaration {
/// The type alias reflected upon.
hidden reflectee: base.TypeAlias
/// The type parameters of this type alias declaration.
typeParameters: List<TypeParameter>
/// The type that this type alias stands for.
referent: Type
}
/// A property declaration.
external class Property extends Declaration {
/// The declared type of this property.
type: Type
/// The (explicit or implicit) default value of this property.
///
/// [null] if this property does not have a default value.
hidden defaultValue: Any
}
/// A method declaration.
external class Method extends Declaration {
/// The type parameters of this method.
///
/// Only standard library methods can have type parameters.
typeParameters: List<TypeParameter>
/// The parameters of this method.
parameters: Map<String, MethodParameter>
/// The return type of this method.
returnType: Type
}
/// A method parameter.
external class MethodParameter {
/// The name of this method parameter.
name: String
/// The type of this method parameter.
type: Type
}
/// A type parameter of a generic type or method declaration.
///
/// Example: `T` on the left-hand side of `typealias StringMapping<T> = Mapping<String, T>`.
external class TypeParameter {
/// The name of this type parameter.
name: String
/// The variance of this type parameter.
///
/// [null] if this type parameter is invariant.
variance: Variance?
}
/// A modifier of a [Declaration].
typealias Modifier = "abstract"|"external"|"hidden"|"open"
/// The variance of a [TypeParameter].
///
/// An "in" type parameter is contravariant.
/// An "out" type parameter is covariant.
typealias Variance = "in"|"out"
/// A type as it occurs, say, in a type annotation.
abstract external class Type {
/// The corresponding nullable type, or [this] if [this] is already a nullable type.
external nullable: NullableType
}
/// A declared type such as `String` or `Listing<String>`.
///
/// Use [DeclaredType()] to create an instance of this class.
/// For common standard library classes, this module offers predefined type mirrors
/// ([intType], [stringType], [listType], etc.).
///
/// If this type's [referent] has type parameters, the corresponding [typeArguments] default to [unknownType].
/// To override this default, use [withTypeArgument()] or [withTypeArguments()].
///
/// Examples:
/// ```
/// import "pkl:reflect"
///
/// class Person
/// pigeon: Person
/// people: List<Person>
///
/// personClass = reflect.Class(Person)
/// personType = reflect.DeclaredType(personClass)
/// reflect.Module(this).properties["pigeon"].type == personType
/// reflect.Module(this).properties["people"].type == listType.withTypeArgument(personType)
/// ```
external class DeclaredType extends Type {
/// The type declaration that this type refers to.
referent: TypeDeclaration
/// The type arguments of this type.
typeArguments: List<Type>(length == referent.typeParameters.length)
/// Returns a declared type with the same [referent] and the given [typeArgument].
external function withTypeArgument(typeArgument: Type): DeclaredType
/// Returns a declared type with the same [referent] and the given [typeArguments].
external function withTypeArguments(typeArguments: List<Type>): DeclaredType
}
/// A string literal type such as `"Pigeon"`.
///
/// Use [StringLiteralType()] to create an instance of this class.
external class StringLiteralType extends Type {
/// The string value represented by this type.
value: String
}
/// A union type such as `String|Int`.
///
/// Use [UnionType()] to create an instance of this class.
external class UnionType extends Type {
/// The members of this union type.
members: List<Type>
}
/// A nullable type such as `String?`.
///
/// Use [Type.nullable] to create an instance of this class.
external class NullableType extends Type {
/// The member of this nullable type.
member: Type
}
/// A function type such as `(String, Int) -> Duration`.
///
/// Use [FunctionType()] to create an instance of this class.
external class FunctionType extends Type {
/// The parameter types of this function type.
parameterTypes: List<Type>
/// The return type of this function type.
returnType: Type
}
/// The `module` type.
///
/// [moduleType] is an instance of this class.
class ModuleType extends Type
/// The `unknown` type.
///
/// [unknownType] is an instance of this class.
class UnknownType extends Type
/// The `nothing` type.
///
/// [nothingType] is an instance of this class.
class NothingType extends Type
/// A type variable that refers to a type parameter of a generic type or method declaration.
///
/// Example: `T` on the right-hand side of `typealias StringMapping<T> = Mapping<String, T>`.
external class TypeVariable extends Type {
referent: TypeParameter
}
/// A source location within a module.
external class SourceLocation {
/// The 1-based line number of this source location.
line: UInt
/// The 1-based column number of this source location.
column: UInt
/// The display URI of this source location.
displayUri: String
}

63
stdlib/release.pkl Normal file
View File

@@ -0,0 +1,63 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Information about the Pkl release that the current program runs on.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.release
import "pkl:semver"
/// The Pkl release that the current program runs on.
external current: Release
/// A Pkl release.
class Release {
/// The version of this release.
version: semver.Version
/// The output of `pkl --version` for this release.
versionInfo: String
/// The Git commit ID of this release.
commitId: String
/// The source code of this release.
sourceCode: SourceCode
/// The documentation of this release.
documentation: Documentation
/// The standard library of this release.
standardLibrary: StandardLibrary
}
/// The source code of a Pkl release.
class SourceCode {
/// The homepage of this source code.
homepage: Uri(endsWith("/"))
}
/// The documentation of a Pkl release.
class Documentation {
/// The homepage of this documentation.
homepage: Uri(endsWith("/"))
}
/// The standard library of a Pkl release.
class StandardLibrary {
/// The module URIs of this standard library.
modules: Set<Uri(startsWith("pkl:"))>
}

206
stdlib/semver.pkl Normal file
View File

@@ -0,0 +1,206 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Parsing, comparison, and manipulation of [semantic version](https://semver.org/spec/v2.0.0.html) numbers.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.semver
/// Tells whether [version] is a valid semantic version number.
function isValid(version: String) = parseOrNull(version) != null
/// Parses [version] as a semantic version number.
///
/// Throws if [version] is not a valid semantic version number.
///
/// Examples:
/// ```
/// semver.Version("1.2.3")
/// semver.Version("1.2.3-alpha")
/// semver.Version("1.2.3+456")
/// semver.Version("1.2.3-alpha+456")
/// ```
function Version(version: String): Version =
parseOrNull(version) ?? throw("`\(version)` is not a valid semantic version number.")
/// Parses [version] as a semantic version number.
///
/// Returns [null] if [version] is not a valid semantic version number.
///
/// Facts:
/// ```
/// semver.parseOrNull("1.2.3") == semver.Version("1.2.3")
/// semver.parseOrNull("1.2.3-alpha+456") == semver.Version("1.2.3-alpha+456")
/// semver.parseOrNull("1") == null
/// ```
function parseOrNull(version: String): Version? =
let (groups = versionRegex.matchEntire(version)?.groups)
if (groups == null) null
else
new Version {
major = groups[1].value.toInt()
minor = groups[2].value.toInt()
patch = groups[3].value.toInt()
preRelease = groups[4]?.value
build = groups[5]?.value
}
/// A version comparator for use with methods such as [List.minWith()].
comparator: (Version, Version) -> Boolean = (v1: Version, v2: Version) -> v1.isLessThan(v2)
/// A [semantic version](https://semver.org/spec/v2.0.0.html).
///
/// To test if two versions are equal according to semantic versioning rules, use [equals()] instead of `==`.
class Version {
/// Major version zero (0.y.z) is for initial development.
/// Anything MAY change at any time.
/// The public API SHOULD NOT be considered stable.
///
/// Version 1.0.0 defines the public API.
/// The way in which the version number is incremented after this release is dependent on this public API and how it changes.
///
/// Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API.
/// It MAY also include minor and patch level changes.
/// Patch and minor version MUST be reset to 0 when major version is incremented.
major: UInt
/// Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API.
/// It MUST be incremented if any public API functionality is marked as deprecated.
/// It MAY be incremented if substantial new functionality or improvements are introduced within the private code.
/// It MAY include patch level changes.
/// Patch version MUST be reset to 0 when minor version is incremented.
minor: UInt
/// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced.
/// A bug fix is defined as an internal change that fixes incorrect behavior.
patch: UInt
/// A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version.
/// Identifiers MUST comprise only ASCII alphanumerics and hyphens `[0-9A-Za-z-]`.
/// Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes.
/// Pre-release versions have a lower precedence than the associated normal version.
/// A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
///
/// Examples:
/// - `"1.0.0-alpha"`
/// - `"1.0.0-alpha.1"`
/// - `"1.0.0-0.3.7"`
/// - `"1.0.0-x.7.z.92"`
/// - `"1.0.0-x-y-z."`
preRelease: String(matches(Regex(#"(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*"#)))?
hidden fixed preReleaseIdentifiers: List<Int|String> =
if (preRelease == null) List() else preRelease.split(".").map((it) -> it.toIntOrNull() ?? it)
/// Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version.
/// Identifiers MUST comprise only ASCII alphanumerics and hyphens `[0-9A-Za-z-]`.
/// Identifiers MUST NOT be empty.
/// Build metadata MUST be ignored when determining version precedence.
/// Thus two versions that differ only in the build metadata, have the same precedence.
///
/// Examples:
/// - `"1.0.0-alpha+001"
/// - `"1.0.0+20130313144700"`
/// - `"1.0.0-beta+exp.sha.5114f85"`
/// - `"1.0.0+21AF26D3—-117B344092BD"`
///
/// Note: Unlike `==`, [equals()] and comparison methods such as [isLessThan()] ignore [build].
build: String(matches(Regex(#"[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*"#)))?
hidden fixed buildIdentifiers: List<String> =
if (build == null) List() else build.split(".")
/// Tells whether this version is equal to [other] according to semantic versioning rules.
///
/// Facts:
/// ```
/// semver.Version("1.0.0").equals(semver.Version("1.0.0"))
/// !(semver.Version("1.0.0").equals(semver.Version("1.0.1")))
/// semver.Version("1.0.0-alpha+001").equals(semver.Version("1.0.0-alpha+999"))
/// ```
///
/// Note: `version1.equals(version2)` differs from `version1 == version2` in that it ignores [build].
function equals(other: Version): Boolean =
major == other.major &&
minor == other.minor &&
patch == other.patch &&
preRelease == other.preRelease
/// Tells whether this version is less than [other] according to semantic versioning rules.
///
/// Facts:
/// ```
/// semver.Version("1.0.0").isLessThan(semver.Version("2.0.0"))
/// semver.Version("2.0.0").isLessThan(semver.Version("2.1.0"))
/// semver.Version("2.1.0").isLessThan(semver.Version("2.1.1"))
///
/// semver.Version("1.0.0-alpha").isLessThan("1.0.0")
///
/// semver.Version("1.0.0-alpha").isLessThan(semver.Version("1.0.0-alpha.1"))
/// semver.Version("1.0.0-alpha.1").isLessThan(semver.Version("1.0.0-alpha.beta"))
/// semver.Version("1.0.0-alpha.beta").isLessThan(semver.Version("1.0.0-beta"))
/// semver.Version("1.0.0-beta").isLessThan(semver.Version("1.0.0-beta.2"))
/// semver.Version("1.0.0-beta.2").isLessThan(semver.Version("1.0.0-beta.11"))
/// semver.Version("1.0.0-beta.11").isLessThan(semver.Version("1.0.0-rc.1"))
/// semver.Version("1.0.0-rc.1").isLessThan(semver.Version("1.0.0"))
/// ```
function isLessThan(other: Version): Boolean =
major < other.major ||
minor < other.minor ||
patch < other.patch ||
isPreReleaseLessThan(other)
/// Tells whether this version is less than or equal to [other] according to semantic versioning rules.
function isLessThanOrEquals(other: Version): Boolean =
isLessThan(other) || equals(other)
/// Tells whether this version is greater than [other] according to semantic versioning rules.
function isGreaterThan(other: Version): Boolean =
other.isLessThan(this)
/// Tells whether this version is greater than or equal to [other] according to semantic versioning rules.
function isGreaterThanOrEquals(other: Version): Boolean =
other.isLessThanOrEquals(this)
/// A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes.
function isNormal(): Boolean = preRelease == null && build == null
/// Tells if this version has a non-zero [major] and no [preRelease].
function isStable(): Boolean = major > 0 && preRelease == null
/// Strips [preRelease] and [build] from this version.
function toNormal(): Version = (this) { preRelease = null; build = null }
function toString() = "\(major).\(minor).\(patch)\(if (preRelease != null) "-\(preRelease)" else "")\(if (build != null) "+\(build)" else "")"
local function isPreReleaseLessThan(other: Version): Boolean =
if (preRelease == null) false
else if (other.preRelease == null) true
else if (preRelease == other.preRelease) false
else
let (result = preReleaseIdentifiers
.zip(other.preReleaseIdentifiers)
.fold(null, (result, next) ->
if (result != null) result
else
if (next.first == next.second) null
else if (next.first.getClass() == next.second.getClass()) next.first < next.second
else next.first is Int
)
) if (result != null) result else preReleaseIdentifiers.length < other.preReleaseIdentifiers.length
}
// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
local versionRegex = Regex(#"(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"#)

80
stdlib/settings.pkl Normal file
View File

@@ -0,0 +1,80 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Configuration settings for Pkl itself.
///
/// 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.25.0" }
module pkl.settings
/// The editor for viewing and editing Pkl files.
editor: Editor = System
/// The editor associated with `file:` URLs ending in `.pkl`.
hidden System: Editor = new {
urlScheme = "%{url}, line %{line}"
}
/// The [IntelliJ IDEA](https://www.jetbrains.com/idea) editor.
hidden Idea: Editor = new {
urlScheme = "idea://open?file=%{path}&line=%{line}"
}
/// The [GoLand](https://www.jetbrains.com/go/) editor.
hidden GoLand: Editor = new {
urlScheme = "goland://open?file=%{path}&line=%{line}"
}
/// The [TextMate](https://macromates.com) editor.
hidden TextMate: Editor = new {
urlScheme = "txmt://open?url=%{url}&line=%{line}&column=%{column}"
}
/// The [Sublime Text](https://www.sublimetext.com) editor.
hidden Sublime: Editor = new {
urlScheme = "subl://open?url=%{url}&line=%{line}&column=%{column}"
}
/// The [Atom](https://atom.io) editor.
hidden Atom: Editor = new {
urlScheme = "atom://open?url=%{url}&line=%{line}&column=%{column}"
}
/// The [Visual Studio Code](https://code.visualstudio.com) editor.
hidden VsCode: Editor = new {
urlScheme = "vscode://file/%{path}:%{line}:%{column}"
}
/// An editor for viewing and editing Pkl files.
class Editor {
/// The URL scheme for opening files in this editor.
/// The following placeholders are supported:
/// - `%{url}`
/// file URL of the file to open
/// - `%{path}`
/// absolute file path of the file to open
/// - `%{line}`
/// start line number to navigate to
/// - `%{endLine}`
/// end line number to navigate to
/// - `%{column}`
/// start column number to navigate to
/// - `%{endColumn}`
/// end column number to navigate to
urlScheme: String
}

37
stdlib/shell.pkl Normal file
View File

@@ -0,0 +1,37 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// Utilities for generating shell scripts.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.shell
/// Escapes [str] by enclosing it in single quotes.
///
/// Also handles single quotes occurring within [str].
function escapeWithSingleQuotes(str: String): String =
let (processChar = (acc, ch) ->
if (acc.isEmpty)
List(List(ch))
else if (acc.last.last != "'" && ch != "'")
acc.replace(acc.lastIndex, acc.last.add(ch))
else
acc.add(List(ch)))
let (grouped = str.chars.fold(List(), processChar))
grouped
.map((chSeq) ->
if (chSeq == List("'")) #"\'"#
else "'\(chSeq.join(""))'")
.join("")

75
stdlib/stdlib.gradle.kts Normal file
View File

@@ -0,0 +1,75 @@
plugins {
pklAllProjects
base
`maven-publish`
id("com.diffplug.spotless")
pklPublishLibrary
signing
}
val pkldocConfiguration: Configuration = configurations.create("pkldoc")
dependencies {
pkldocConfiguration(project(":pkl-doc"))
}
// create and publish a self-contained stdlib archive
// purpose is to provide non-jvm tools/projects with a versioned stdlib
val stdlibZip by tasks.registering(Zip::class) {
destinationDirectory.set(file("$buildDir/libs"))
archiveBaseName.set("pkl-stdlib")
archiveVersion.set(project.version as String)
into("org/pkl/stdlib") {
from(projectDir)
include("*.pkl")
}
}
tasks.assemble {
dependsOn(stdlibZip)
}
publishing {
publications {
create<MavenPublication>("stdlib") {
artifactId = "pkl-stdlib"
artifact(stdlibZip.flatMap { it.archiveFile })
pom {
description.set("Standard library for the Pkl programming language")
url.set("https://github.com/apple/pkl/tree/main/stdlib")
}
}
}
}
signing {
sign(publishing.publications["stdlib"])
}
spotless {
format("pkl") {
target("*.pkl")
licenseHeaderFile(rootProject.file("buildSrc/src/main/resources/license-header.line-comment.txt"), "/// ")
}
}
val pkldoc by tasks.registering(JavaExec::class) {
val stdlibFiles = project.fileTree(projectDir).matching {
include("*.pkl")
exclude("doc-package-info.pkl")
}
val infoFiles = project.files("doc-package-info.pkl")
inputs.files(stdlibFiles)
inputs.files(infoFiles)
outputs.dir("$buildDir/pkldoc")
classpath = pkldocConfiguration
main = "org.pkl.doc.Main"
args("--output-dir", "$buildDir/pkldoc")
args(stdlibFiles.map { "pkl:${it.name}".dropLast(4) })
args(infoFiles)
doLast {
println("Generated Standard Library API Docs at: file://$buildDir/pkldoc/index.html")
}
}

97
stdlib/test.pkl Normal file
View File

@@ -0,0 +1,97 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A template for writing tests.
///
/// To write tests, amend this module and define [facts] or [examples] (or both).
/// To run tests, evaluate the amended module.
@ModuleInfo { minPklVersion = "0.25.0" }
open module pkl.test
/// Named groups of boolean expressions that are expected to evaluate to [true].
///
/// If an expression evaluates to [false], it is reported as a test failure.
///
/// Example:
/// ```
/// // for brevity, code under test is defined here
/// function multiply(a, b) = a * b
///
/// facts {
/// ["multiply numbers"] {
/// multiply(3, 5) == 15
/// multiple(3, 0) == 1 // will be reported as a test failure
/// }
/// // more facts here
/// }
/// ```
facts: Mapping<String, Listing<Boolean>>?
/// Named groups of expressions whose results are expected to match results stored in _$filename-expected.pcf_.
///
/// If _$filename-expected.pcf_ does not exist, it is generated based on the examples' actual results.
/// After verifying the contents of this file, it should be added to version control.
///
/// If _$filename-expected.pcf_ does exist, its results are compared one-by-one to actual results.
/// If an actual result does not compare equal (according to `==`) to its expected result,
/// it is reported as a test failure, and _$filename-actual.pcf_ is generated to aid with debugging.
///
/// Example:
/// ```
/// // for brevity, code under test is defined here
/// local function createPigeon(_age) = new {
/// name = "Pigeon"
/// age = _age
/// }
///
/// examples {
/// ["create Pigeons"] {
/// createPigeon(21)
/// createPigeon(42)
/// }
/// // more examples here
/// }
/// ```
///
/// When the above code is evaluated for the first time, the following `$filename-expected.pcf` is generated:
/// ```
/// examples {
/// ["create Pigeons"] {
/// new {
/// name = "Pigeon"
/// age = 21
/// }
/// new {
/// name = "Pigeon"
/// age = 42
/// }
/// }
/// }
/// ```
///
/// To update expected results after making changes,
/// delete _$filename-expected.pcf_ and evaluate the test module again.
examples: Mapping<String, Listing<unknown>>?
/// Applies [fun] and returns the error thrown.
///
/// Throws if [fun] did not throw an error.
external const function catch(fun: () -> Any): String
/// Applies [fun] and returns the error thrown.
///
/// Returns [null] if [fun] did not throw an error.
external const function catchOrNull(fun: () -> Any): String?

109
stdlib/xml.pkl Normal file
View File

@@ -0,0 +1,109 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// An XML renderer.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.xml
/// Renders values as XML.
///
/// Values are rendered as follows depending on their type:
///
/// - `Int`, `Float`, `Boolean`, `String`: XML text node
/// - `List`, `Set`, `Listing`: sequence of XML text nodes or XML elements (depending on element types)
/// - `Map<String, ?>`, `Mapping<String, ?>`, `Typed`: sequence of XML elements (`null` values are skipped)
/// - `Dynamic`: sequence of XML text nodes and/or XML elements (depending on member types; `null` value are skipped)
///
/// For more control over XML rendering, use [Element()], [Inline], [Comment], and [CData].
/// These DOM-style objects can be used exclusively or mixed and matched with "normal" Pkl objects.
///
/// To set the name and attributes of the XML document's root element,
/// use [rootElementName] and [rootElementAttributes].
class Renderer extends ValueRenderer {
extension = "xml"
/// The characters to use for indenting output.
indent: String = " "
/// The XML version to use.
xmlVersion: *"1.0"|"1.1"
/// The name of the XML document's root element.
rootElementName: String(!isEmpty) = "root"
/// The attributes of the XML document's root element.
rootElementAttributes: Mapping<String(!isEmpty), String|Boolean|Int|Float>
external function renderDocument(value: Any): String
external function renderValue(value: Any): String
}
/// Creates an XML element with the given name.
///
/// Use this method to directly define an XML element
/// instead of relying on the default rendering of Pkl values.
///
/// To define the XML element's attributes, set the [attributes] property of the `Element` object:
/// ```
/// order = xml.Element("order") {
/// attributes {
/// ["date"] = "2020-03-21"
/// }
/// }
/// ```
///
/// To define the XML element's content, add child values (normally also called "elements") to the `Element` object:
/// ```
/// order = xml.Element("order") { // element with one child
/// xml.Element("item") { // element with two children
/// xml.Element("name") { "banana" } // element with one child
/// xml.Element("quantity") { 42 } // element with one child
/// }
/// }
/// ```
function Element(_name: String(!isEmpty)): Dynamic = new {
_isXmlElement = true
name = _name
attributes = new Mapping {}
isBlockFormat = true
}
/// Creates an [Inline] directive for [_value].
function Inline(_value: Object|Collection|Map): Inline = new { value = _value }
/// Inlines the members of [value] into the enclosing XML element,
/// without rendering an XML element for [value] itself.
class Inline {
value: Object|Collection|Map
}
/// Creates an XML [Comment] with the given [_text].
function Comment(_text: String): Comment = new { text = _text }
/// An XML comment.
class Comment {
text: String(!contains("--"))
isBlockFormat: Boolean = true
}
/// Creates an XML [CData] section with the given [_text].
function CData(_text: String): CData = new { text = _text }
/// An XML CDATA section.
class CData {
text: String
}

91
stdlib/yaml.pkl Normal file
View File

@@ -0,0 +1,91 @@
//===----------------------------------------------------------------------===//
// Copyright © 2024 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.
//===----------------------------------------------------------------------===//
/// A YAML 1.2 compliant YAML parser.
@ModuleInfo { minPklVersion = "0.25.0" }
module pkl.yaml
/// A YAML parser.
///
/// YAML values are mapped to Pkl values as follows:
///
/// | YAML type | Pkl type |
/// | ----------- | ------------------------------------------------------- |
/// | !!null | [Null] |
/// | !!bool | [Boolean] |
/// | !!int | [Int] |
/// | !!float | [Float] |
/// | !!string | [String] |
/// | !!seq | [Listing] |
/// | !!set | [Listing] |
/// | !!map | [Dynamic] or [Mapping] depending on [Parser.useMapping] |
/// | !!binary | [String] |
/// | !!timestamp | [String] |
///
/// The element order of YAML sequences, sets, and mappings is maintained.
/// YAML binary values are mapped to their original (base64) string representation.
/// YAML timestamp values are mapped to their original string representation.
///
/// If the parser encounters a YAML type not listed above, it fails with an error.
///
/// Known limitations:
/// - [Merge keys](https://yaml.org/type/merge.html) are not supported.
/// - Comments are not retained.
class Parser {
/// The YAML version used by producers of the parsed documents.
///
/// - `"compat"` - YAML 1.1 _or_ 1.2 (default)
/// - `"1.1"` - YAML 1.1
/// - `"1.2"` - YAML 1.2 (Core schema)
mode: "compat"|"1.1"|"1.2" = "compat"
/// Determines what the parser produces when parsing YAML `!!map` types.
///
/// If [true], they turn into a [Mapping].
/// Otherwise, they turn into a [Dynamic].
///
/// If [useMapping] is [false], map properties named `default` will be shadowed by the
/// built-in [Dynamic.default] property.
useMapping: Boolean = false
/// Value converters to apply to parsed values.
///
/// For further information see [PcfRenderer.converters].
converters: Mapping<Class|String(!isEmpty), (unknown) -> unknown>
/// The maximum number of aliases for collection nodes.
///
/// Limiting the number of collection aliases prevents
/// [billion laughs attacks](https://en.wikipedia.org/wiki/Billion_laughs_attack).
maxCollectionAliases: Int32(isPositive) = 50
/// Parses the single YAML document contained in [source].
///
/// Throws if an error occurs during parsing, or if [source] contains multiple YAML documents.
///
/// If [source] is a [Resource], the resource URI is included in parse error messages.
external function parse(source: Resource|String): Value
/// Parses all YAML documents contained in [source].
///
/// Throws if an error occurs during parsing.
///
/// If [source] is a [Resource], the resource URI is included in parse error messages.
external function parseAll(source: Resource|String): List<Value>
}
/// Pkl representation of a YAML value.
typealias Value = Null|Boolean|Number|String|Listing|Dynamic|Mapping