mirror of
https://github.com/apple/pkl.git
synced 2026-05-06 07:03:35 +02:00
Initial commit
This commit is contained in:
232
stdlib/Benchmark.pkl
Normal file
232
stdlib/Benchmark.pkl
Normal 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
196
stdlib/DocPackageInfo.pkl
Normal 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
50
stdlib/DocsiteInfo.pkl
Normal 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
498
stdlib/Project.pkl
Normal 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
3145
stdlib/base.pkl
Normal file
File diff suppressed because it is too large
Load Diff
43
stdlib/doc-package-info.pkl
Normal file
43
stdlib/doc-package-info.pkl
Normal 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
24
stdlib/gradle.lockfile
Normal 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
59
stdlib/json.pkl
Normal 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
108
stdlib/jsonnet.pkl
Normal 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
165
stdlib/math.pkl
Normal 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
79
stdlib/platform.pkl
Normal 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
40
stdlib/protobuf.pkl
Normal 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
439
stdlib/reflect.pkl
Normal 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
63
stdlib/release.pkl
Normal 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
206
stdlib/semver.pkl
Normal 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
80
stdlib/settings.pkl
Normal 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
37
stdlib/shell.pkl
Normal 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
75
stdlib/stdlib.gradle.kts
Normal 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
97
stdlib/test.pkl
Normal 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
109
stdlib/xml.pkl
Normal 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
91
stdlib/yaml.pkl
Normal 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
|
||||
Reference in New Issue
Block a user