If the object member is const, it only needs to be executed once, and all children in the prototype chain can use its cached value.
There is a possible other optimization here, not included in this PR: we can avoid adding these values to the child object's cachedMembers.
Motivation:
* fix known bugs and limitations of for-generators
* improve code health by removing complex workarounds
Changes:
* simplify AstBuilder code related to for-generators
* track for-generators via `SymbolTable.enterForGenerator()`
* add `RestoreForBindingsNode` during initial AST construction
instead of calling `MemberNode.replaceBody()` later on
* simplify some unnecessarily complex code
* remove workarounds and band-aids such as:
* `isInIterable`
* `executeAndSetEagerly`
* adding dummy slots in `AmendFunctionNode`
* overhaul implementation of for-generators
* store keys and values of for-generator iterations in regular instead of auxiliary frame slots
* set them via `TypeNode.executeAndSet()`
* `ResolveVariableNode` no longer needs to search auxiliary slots
* `Read(Enclosing)AuxiliarySlot` is no longer needed
* at the start of each for-generator iteration, create a new `VirtualFrame`
that is a copy of the current frame (arguments + slots)
and stores the iteration key and value in additional slots.
* execute for-generator iteration with the newly created frame
* `childNode.execute(newFrame)`
* Pkl objects created during the iteration will materialize this frame
* store newly created frames in `owner.extraStorage`
if their for-generator slots may be accessed when a generated member is executed
* resolving variable names to for-generator variables at parse time would make this analysis more precise
* when a generated member is executed,
* retrieve the corresponding frame stored in `owner.extraStorage`
* copy the retrieved frame's for-generator slots into slots of the current frame
Result:
* for-generators are implemented in a correct, reasonably simple, and reasonably efficient way
* complexity is fully contained within package `generator` and `AstBuilder`
* for-generator keys and values can be accessed from all nested scopes:
* key and value expressions of generated members
* condition expressions of nested when-generators
* iterable expressions of nested for-generators
* for-generator keys and values can be accessed from within objects created by the expressions listed above
* sibling for-generators can use the same key/value variable names
* parent/child for-generators can use the same key/value variable names
* fixes https://github.com/apple/pkl/issues/741
- update Kotlin from 1.7.10 to 2.0.21
- Kotlin 1.6 dependencies in Gradle lock files are expected because kotlinc,
which is also used by some tests, internally uses some 1.6 dependencies
for backwards compatibility reasons.
- update kotlinx-html and kotlinx-serialization
- adapt Kotlin code where necessary
- use Kotlin stdlib Path APIs where possible
- fix IntelliJ Kotlin inspection warnings
- reformat code with `./gradlew spotlessApply`
- ktfmt adds lots of trailing commas
- Add workaround to fix IntelliJ "unresolved reference" errors
Nested jars built by spring boot can possibly represent classpath
resource URIs as "jar:nested:".
This changes Pkl to by default trust them with the same level as
modulepath URIs.
Motivation:
- Perform same exception handling for every implementation of PklRootNode.execute().
- Avoid code duplication.
Changes:
- Change PklRootNode.execute() to be a final method that performs exception handling
and calls abstract method executeImpl(), which is implemented by subclasses.
- Remove executeBody() methods, which served a similar purpose but were more limited.
- Remove duplicate exception handling code.
Result:
- More reliable exception handling.
This should fix known problems such as misclassifying stack overflows
as internal errors and displaying errors without a stack trace.
- Less code duplication.
Motivation:
- simplify implementation of lazy type checking
- fix correctness issues of lazy type checking (#785)
Changes:
- implement listing/mapping type cast via amendment (`parent`) instead of delegation (`delegate`)
- handle type checking of *computed* elements/entries in the same way as type checking of computed properties
- ElementOrEntryNode is the equivalent of TypeCheckedPropertyNode
- remove fields VmListingOrMapping.delegate/typeNodeFrame/cachedMembers/checkedMembers
- fix#785 by executing all type casts between a member's owner and receiver
- fix#823 by storing owner and receiver directly
instead of storing the mutable frame containing them (typeNodeFrame)
- remove overrides of VmObject methods that are no longer required
- good for Truffle partial evaluation and JVM inlining
- revert a85a173faa except for added tests
- move `VmUtils.setOwner` and `VmUtils.setReceiver` and make them private
- these methods aren't generally safe to use
Result:
- simpler code with greater optimization potential
- VmListingOrMapping can now have both a type node and new members
- fewer changes to surrounding code
- smaller memory footprint
- better performance in some cases
- fixes https://github.com/apple/pkl/issues/785
- fixes https://github.com/apple/pkl/issues/823
Potential future optimizations:
- avoid lazy type checking overhead for untyped listings/mappings
- improve efficiency of forcing a typed listing/mapping
- currently, lazy type checking will traverse the parent chain once per member,
reducing the performance benefit of shallow-forcing
a listing/mapping over evaluating each member individually
- avoid creating an intermediate untyped listing/mapping in the following cases:
- `new Listing<X> {...}`
- amendment of `property: Listing<X>`
Motivation:
The following expression evaluates to 2 instead of 1:
new Listing { "value" } { [0 + 0] = "override" }.length
Changes:
- fix length computation in EntriesLiteralNode
- improve `api/listing` tests
- make snippet test failures diffable in IntelliJ
Result:
- fixes https://github.com/apple/pkl/issues/780
- improved dev experience in IntelliJ
This fixes issues when a mapping/listing delegates to another mapping/listing.
The core issue is that `cachedValues` is not guaranteed to be the complete set
of the object's members; they may be stored on the delegate instead.
Therefore, it's not correct compute hash code and equality based on `cachedValues`.
Instead, it's better to use the `getCachedValue()` method, which has the correct
logic for looking up the existing cached value.
- change line numbers from blue to faint to improve legibility on dark backgrounds
- use EnumSet throughout
- move all ANSI classes into package core.util (no need to split them over util and runtime)
- rename AnsiCodingStringBuilder to AnsiStringBuilder
Any thrown Pkl Errors are colored in the simple test report!
Also:
* Refactor `TextFormatter` to be more generic; rename to `TextFormattingStringBuilder`
* Adjust test report slightly (no emojis, add more spacing).
* Introduce `ColorTheme` class.
* Make stack frame descriptors colored as "faint"
Also: this changes the summary so it summarizes _all_ modules, rather than a summary per module.
---------
Co-authored-by: Islon Scherer <islonscherer@gmail.com>
Co-authored-by: Philip K.F. Hölzenspies <holzensp@gmail.com>
GraalVM for JDK 17.0.12 is the final Critical Patch Update
made available under the GraalVM Free Terms and Conditions license.
Subsequent Critical Patch Updates require a commercial license.
* Encapsulate message transport by removing `ExternalReaderProcess.getTransport` and adding `getModuleResolver` and `getResourceResolver` methods
* Reuse `Random` instances within `ExternalReaderProcessImpl` and module/resource resolvers
* Externalize all `ExternalReaderProcessException` messages
* Add some missing doc comments to `ModuleKeyFactories` and `ResourceReaders` methods for external readers
* Move org.pkl.core.util.Readers to org.pkl.core.Readers
There is currently a bug around resolving variables within the iterable of a for
generator or spread syntax (https://github.com/apple/pkl/issues/741)
Normally, mappings/listings are type-checked lazily. However, this results in the said
bug getting widened, for any object members declared in the iterable.
As a workaround for now, prevent the bug from being any worse by ensuring that these
object members are eagerly typechecked.
- keep implementation classes internal to their packages
- make classes final if possible
- make namespace classes non-instantiable
- throw IllegalStateException instead of ExternalReaderProcessException for use after close
- common convention already used by HttpClient etc.
- programming errors should be signaled with unchecked exceptions
- use private instead of public lock object
- polish Javadoc
- delete commented out code
- don't use star import for a single class
* Add `values` to `Mapping`
* Add `entries` to `Mapping`
* Add `containsValue` to `Mapping`
* Add `every` to `Mapping`
* Add `any` to `Mapping`
* Add `toDynamic` to `Mapping`
* Add `lastIndex` to `Listing`
* Add `getOrNull` to `Listing`
* Add `first` to `Listing`
* Add `firstOrNull` to `Listing`
* Add `last` to `Listing`
* Add `lastOrNull` to `Listing`
* Add `single` to `Listing`
* Add `singleOrNull` to `Listing`
* Add `contains` to `Listing`
* Add `any` to `Listing`
* Add `every` to `Listing`
* Fixup `any` to `Listing`
* Revert "Add `toDynamic` to `Mapping`"
This reverts commit 5551974ecd8110aa2eb8f546e992c32d3181df9b.
* Revert "Add `values` to `Mapping`"
This reverts commit 6fc78796
* Revert "Add `entries` to `Mapping`"
This reverts commit a7e8dfc4
* Annotate new members with `Since` 0.27
* Fix documentation in `base.pkl`
* Add location information to empty/single checks in `Listing` operations
* Remove additional variable for laziness preservation
* Apply spotless
* Apply suggestions from code review
Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
---------
Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
* Load `PklProject` using the same security settings and env vars passed provided via ExecutorSPIOptions
* Handle thrown `PklException` from loading `PklProject` and throw `ExecutorSPIException`
* Handle thrown `PklException` of older Pkl distributions, converting them into `ExecutorSpiException`
Changes:
* Move class `TestResults` to package `org.pkl.core`, because it is a public class (it's the result of `Evaluator#evaluateTest`)
* Change examples to treat individual examples as assertions in the same test. Previously, they were considered different tests with an incrementing number. This better aligns with how facts are treated.
* Change `TestResults` to be a record, and introduce builders.
* Remove "module" test result section (it is not really a section).
* Add javadoc to `TestResults`
* Formatting fix: prefix ✍️ emoji just like we do the ❌ and ✅ emojis
* Consider writing examples as failures, not successes. `pkl test` will exit with code 10 if the only failing tests are due to writing examples.