Add support for const object members (#678)

This adds support for adding the `const` modifier to object members.

Such object members are also required to have the `local` modifier applied.

This follows SPICE-0011.
This commit is contained in:
Daniel Chao
2024-10-21 22:00:12 -07:00
committed by GitHub
parent 5057bb5b17
commit 0ee3d37524
13 changed files with 104 additions and 5 deletions

View File

@@ -72,7 +72,7 @@ public final class VmModifier {
public static final int VALID_PROPERTY_MODIFIERS =
ABSTRACT | LOCAL | HIDDEN | EXTERNAL | FIXED | CONST;
public static final int VALID_OBJECT_MEMBER_MODIFIERS = LOCAL;
public static final int VALID_OBJECT_MEMBER_MODIFIERS = LOCAL | CONST;
public static final int TYPEALIAS_OBJECT_MEMBER = TYPE_ALIAS | CONST;

View File

@@ -721,12 +721,22 @@ public final class AstBuilder extends AbstractAstBuilder<Object> {
@Nullable TypeAnnotationContext typeAnnCtx,
@Nullable ExprContext exprCtx,
@Nullable List<? extends ObjectBodyContext> bodyCtx) {
var modifiers =
doVisitModifiers(
modifierCtxs, VmModifier.VALID_OBJECT_MEMBER_MODIFIERS, "invalidObjectMemberModifier");
if (VmModifier.isConst(modifiers) && !VmModifier.isLocal(modifiers)) {
@SuppressWarnings("OptionalGetWithoutIsPresent")
var constModifierCtx =
modifierCtxs.stream().filter((it) -> it.CONST() != null).findFirst().get();
throw exceptionBuilder()
.evalError("invalidConstObjectMemberModifier")
.withSourceSection(createSourceSection(constModifierCtx))
.build();
}
return doVisitObjectProperty(
createSourceSection(ctx),
createSourceSection(propertyName),
doVisitModifiers(
modifierCtxs, VmModifier.VALID_OBJECT_MEMBER_MODIFIERS, "invalidObjectMemberModifier"),
modifiers,
propertyName.getText(),
typeAnnCtx,
exprCtx,

View File

@@ -19,6 +19,9 @@ Modifier `{0}` is not applicable to properties.
invalidObjectMemberModifier=\
Modifier `{0}` is not applicable to object members.
invalidConstObjectMemberModifier=\
Modifier `const` can only be applied to object members that are also `local`.
objectMethodMustBeLocal=\
Method needs a `local` modifier because it is defined in an object, not a class.

View File

@@ -0,0 +1,5 @@
module Birds2
abstract class Bird
bird: Bird

View File

@@ -0,0 +1,15 @@
const baz = 15
foo {
const local bar = baz
const local bar2 = biz()
const local function biz() = baz
qux = bar
corge = biz()
corge2 = bar2
}

View File

@@ -0,0 +1,9 @@
amends ".../input-helper/modules/Birds2.pkl"
const local myBirdName = "Birdy"
local class MyBird extends Bird {
name: String = myBirdName
}
bird = new MyBird {}

View File

@@ -0,0 +1,7 @@
bar = 15
obj {
const local function foo() = bar
res = foo()
}

View File

@@ -0,0 +1,5 @@
foo {
res1 = 15
const local qux = res1
res2 = qux
}

View File

@@ -0,0 +1,6 @@
baz = 15
foo {
qux = 15
corge = 15
corge2 = 15
}

View File

@@ -0,0 +1,3 @@
bird {
name = "Birdy"
}

View File

@@ -0,0 +1,18 @@
Pkl Error
Cannot reference property `bar` from here because it is not `const`.
x | const local function foo() = bar
^^^
at constLocalMethod#obj.foo (file:///$snippetsDir/input/errors/const/constLocalMethod.pkl)
To fix, do either of:
1. Add modifier `const` to property `bar`
2. Self-import this module, and reference this property from the import.
x | res = foo()
^^^^^
at constLocalMethod#obj.res (file:///$snippetsDir/input/errors/const/constLocalMethod.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -0,0 +1,18 @@
Pkl Error
Cannot reference property `res1` from here because it is not `const`.
x | const local qux = res1
^^^^
at constLocalProperty#foo.qux (file:///$snippetsDir/input/errors/const/constLocalProperty.pkl)
To fix, do either of:
1. Add modifier `const` to property `res1`
2. Self-import this module, and reference this property from the import.
x | res2 = qux
^^^
at constLocalProperty#foo.res2 (file:///$snippetsDir/input/errors/const/constLocalProperty.pkl)
xxx | text = renderer.renderDocument(value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (pkl:base)

View File

@@ -1,5 +1,5 @@
Pkl Error
Modifier `const` is not applicable to object members.
Modifier `const` can only be applied to object members that are also `local`.
x | const foo = 10
^^^^^