Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion docs/modules/language-reference/pages/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6028,7 +6028,7 @@ Here's a realistic example of how references might be used:
import "pkl:ref"

class Domain extends ref.Domain { // <1>
function renderReference(reference: ref.Reference<Domain, Any>): String =
override function renderReference(reference: ref.Reference<Domain, Any>): String =
if (reference.getData() is Task)
let (path = reference.getPath().map((access) -> access.property ?? access.key.toString()))
"${\(reference.getData().name)/\(path.join("/"))}"
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/release-notes/pages/0.32.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Library authors describe types as `ref.Reference<D, T>`, where `D` is the _domai
import "pkl:ref"

class MyDomain extends ref.Domain { // <1>
function renderReference(ref: ref.Reference<MyDomain, Any>): String =
override function renderReference(ref: ref.Reference<MyDomain, Any>): String =
"${ " + ref.getData() + "." + ref.getPath().join(".") + " }"
}

Expand Down
8 changes: 4 additions & 4 deletions pkl-cli/src/test/kotlin/org/pkl/cli/CliCommandRunnerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class CliCommandRunnerTest {
"""
extends "pkl:Command"

options: Options
override options: Options

output {
value = options
Expand Down Expand Up @@ -822,7 +822,7 @@ class CliCommandRunnerTest {
"""
extends "pkl:Command"

options: Options
override options: Options

output {
value = (options) {
Expand Down Expand Up @@ -875,7 +875,7 @@ class CliCommandRunnerTest {
"""
extends "pkl:Command"

options: Options
override options: Options

output {
value = (options) {
Expand Down Expand Up @@ -935,7 +935,7 @@ class CliCommandRunnerTest {
extends "pkl:Command"
import "base.pkl"

options: Options
override options: Options

output {
value = (options) {
Expand Down
2 changes: 1 addition & 1 deletion pkl-cli/src/test/kotlin/org/pkl/cli/CliEvaluatorTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ result = someLib.x
class Person {
name: String

function toString() = "Person(\(name))"
override function toString() = "Person(\(name))"
}
person: Person = new { name = "Frodo" }
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1944,11 +1944,11 @@ class JavaCodeGeneratorTest {
}

open class OpenClass {
prop: Foo
open prop: Foo
}

class TheClass extends OpenClass {
prop: TheFoo
override prop: TheFoo
}
"""
.trimIndent()
Expand Down Expand Up @@ -1988,11 +1988,11 @@ class JavaCodeGeneratorTest {
}

open class OpenClass {
prop: Foo
open prop: Foo
}

class TheClass extends OpenClass {
prop: TheFoo
override prop: TheFoo
}
"""
.trimIndent(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module com.example.OverriddenProperty

abstract class BaseClass {
fixed bar: Listing<BaseBar> = new {
open fixed bar: Listing<BaseBar> = new {
new {
prop1 = "hello"
}
Expand All @@ -11,7 +11,7 @@ abstract class BaseClass {
theClass: TheClass

class TheClass extends BaseClass {
fixed bar: Listing<Bar> = new {
override fixed bar: Listing<Bar> = new {
new {
prop1 = "hello"
prop2 = "hello again"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module com.example.OverriddenProperty

abstract class BaseClass {
fixed bar: Listing<BaseBar> = new {
open fixed bar: Listing<BaseBar> = new {
new {
prop1 = "hello"
}
Expand All @@ -11,7 +11,7 @@ abstract class BaseClass {
theClass: TheClass

class TheClass extends BaseClass {
fixed bar: Listing<Bar> = new {
override fixed bar: Listing<Bar> = new {
new {
prop1 = "hello"
prop2 = "hello again"
Expand Down
13 changes: 11 additions & 2 deletions pkl-core/src/main/java/org/pkl/core/ast/VmModifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ private VmModifier() {}

public static final int CONST = 0x40;

public static final int OVERRIDE = 0x2000;

// internal modifiers

public static final int IMPORT = 0x80;
Expand Down Expand Up @@ -69,11 +71,12 @@ private VmModifier() {}

public static final int VALID_TYPE_ALIAS_MODIFIERS = LOCAL | EXTERNAL;

public static final int VALID_METHOD_MODIFIERS = ABSTRACT | LOCAL | EXTERNAL | CONST;
public static final int VALID_METHOD_MODIFIERS =
ABSTRACT | LOCAL | EXTERNAL | CONST | OPEN | OVERRIDE;

// for compat, properties may be parsed with abstract modifier but this is ignored
public static final int VALID_PROPERTY_MODIFIERS =
ABSTRACT | LOCAL | HIDDEN | EXTERNAL | FIXED | CONST;
ABSTRACT | LOCAL | HIDDEN | EXTERNAL | FIXED | CONST | OPEN | OVERRIDE;

public static final int VALID_OBJECT_MEMBER_MODIFIERS = LOCAL | CONST;

Expand Down Expand Up @@ -129,6 +132,10 @@ public static boolean isConst(int modifiers) {
return (modifiers & CONST) != 0;
}

public static boolean isOverride(int modifiers) {
return (modifiers & OVERRIDE) != 0;
}

public static boolean isAmbiguousLocality(int modifiers) {
return (modifiers & AMBIGUOUS_LOCALITY) != 0;
}
Expand Down Expand Up @@ -186,6 +193,7 @@ public static String toString(int modifier) {
case EXTERNAL -> "external";
case FIXED -> "fixed";
case CONST -> "const";
case OVERRIDE -> "override";
default ->
throw new VmExceptionBuilder()
.bug("Cannot convert internal modifier `%s` to a string.", toString(modifier))
Expand All @@ -203,6 +211,7 @@ public static VmSet getMirrors(int modifiers, boolean isClass) {
if (isExternal(modifiers) && isClass) builder.add(toString(EXTERNAL));
if (isFixed(modifiers)) builder.add(toString(FIXED));
if (isConst(modifiers)) builder.add(toString(CONST));
if (isOverride(modifiers)) builder.add(toString(OVERRIDE));

return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,7 @@ private int toModifier(Modifier modifier) {
case HIDDEN -> VmModifier.HIDDEN;
case FIXED -> VmModifier.FIXED;
case CONST -> VmModifier.CONST;
case OVERRIDE -> VmModifier.OVERRIDE;
};
}

Expand Down
56 changes: 32 additions & 24 deletions pkl-core/src/main/java/org/pkl/core/ast/member/ClassNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,37 +123,45 @@ public VmClass executeGeneric(VirtualFrame frame) {
typeParameters,
prototype);

if (unresolvedSupertypeNode != null) {
var supertypeNode = unresolvedSupertypeNode.execute(frame);
var superclass = supertypeNode.getVmClass();
var localContext = VmLanguage.get(this).localContext.get();
localContext.beginClassInit(cachedClass);

checkSupertype(supertypeNode, superclass);
cachedClass.initSupertype(supertypeNode, superclass);
}
try {
if (unresolvedSupertypeNode != null) {
var supertypeNode = unresolvedSupertypeNode.execute(frame);
var superclass = supertypeNode.getVmClass();

// The superclass resolved above may not itself have completed the below initializations yet.
// That's because these initializations may have indirectly or directly triggered
// resolution of this class, in which case the `resolveSuperclass()` call above
// will have returned the partially initialized `cachedClass` of the superclass.
// As a consequence, initializations that require a fully initialized class hierarchy
// are done lazily in VmClass rather than here.
// A fully initialized class hierarchy is only required for initialization of internal caches,
// which is guaranteed to succeed (no impact on eager vs. lazy error reporting) and easy to
// defer.
checkSupertype(supertypeNode, superclass);
cachedClass.initSupertype(supertypeNode, superclass);
}

VmUtils.evaluateAnnotations(frame, annotationNodes, annotations);
// The superclass resolved above may not itself have completed the below initializations yet.
// That's because these initializations may have indirectly or directly triggered
// resolution of this class, in which case the `resolveSuperclass()` call above
// will have returned the partially initialized `cachedClass` of the superclass.
// As a consequence, initializations that require a fully initialized class hierarchy
// are done lazily in VmClass rather than here.
// A fully initialized class hierarchy is only required for initialization of internal caches,
// which is guaranteed to succeed (no impact on eager vs. lazy error reporting) and easy to
// defer.

for (var node : unresolvedPropertyNodes) {
cachedClass.addProperty(node.execute(frame, cachedClass));
}
VmUtils.evaluateAnnotations(frame, annotationNodes, annotations);

for (var node : unresolvedMethodNodes) {
cachedClass.addMethod(node.execute(frame, cachedClass));
}
for (var node : unresolvedPropertyNodes) {
cachedClass.addProperty(node.execute(frame, cachedClass));
}

cachedClass.notifyInitialized();
for (var node : unresolvedMethodNodes) {
cachedClass.addMethod(node.execute(frame, cachedClass));
}

return cachedClass;
cachedClass.onOwnClassInitialized();
localContext.endClassInit();
return cachedClass;
} catch (Throwable e) {
localContext.clearClassInitState();
throw e;
}
}

private void checkSupertype(TypeNode supertypeNode, @Nullable VmClass superclass) {
Expand Down
8 changes: 8 additions & 0 deletions pkl-core/src/main/java/org/pkl/core/ast/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,12 @@ public final boolean isConstOrFixed() {
public final boolean isLocalOrExternalOrAbstract() {
return VmModifier.isLocalOrExternalOrAbstract(modifiers);
}

public final boolean isClosed() {
return VmModifier.isClosed(modifiers);
}

public final boolean isOverride() {
return VmModifier.isOverride(modifiers);
}
}
Loading
Loading