Skip to content

Commit 956582a

Browse files
committed
review feedback round 2
1 parent 29018e2 commit 956582a

36 files changed

Lines changed: 515 additions & 127 deletions

pkl-core/src/main/java/org/pkl/core/ast/internal/ToStringNode.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717

1818
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
1919
import com.oracle.truffle.api.dsl.Cached;
20+
import com.oracle.truffle.api.dsl.Cached.Shared;
2021
import com.oracle.truffle.api.dsl.Fallback;
2122
import com.oracle.truffle.api.dsl.Specialization;
2223
import com.oracle.truffle.api.frame.VirtualFrame;
2324
import com.oracle.truffle.api.source.SourceSection;
24-
import org.pkl.core.ast.ConstantValueNode;
2525
import org.pkl.core.ast.ExpressionNode;
2626
import org.pkl.core.ast.MemberLookupMode;
2727
import org.pkl.core.ast.expression.member.InvokeMethodVirtualNode;
@@ -61,14 +61,17 @@ protected String evalBoolean(boolean value) {
6161
protected String evalTyped(
6262
VirtualFrame frame,
6363
VmTyped value,
64-
@Cached(value = "createInvokeNode()", neverDefault = true)
64+
@Shared("invokeToString") @Cached(value = "createInvokeNode()", neverDefault = true)
6565
InvokeMethodVirtualNode invokeNode) {
6666
return (String) invokeNode.executeWith(frame, value, value.getVmClass());
6767
}
6868

6969
@Specialization
70-
protected String evalReference(VirtualFrame frame, VmReference value, @Cached(value = "createInvokeNode()", neverDefault = true)
71-
InvokeMethodVirtualNode invokeNode) {
70+
protected String evalReference(
71+
VirtualFrame frame,
72+
VmReference value,
73+
@Shared("invokeToString") @Cached(value = "createInvokeNode()", neverDefault = true)
74+
InvokeMethodVirtualNode invokeNode) {
7275
return (String) invokeNode.executeWith(frame, value, value.getVmClass());
7376
}
7477

pkl-core/src/main/java/org/pkl/core/ast/type/TypeNode.java

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,26 +2137,11 @@ public ReferenceTypeNode(
21372137
this.domainTypeNode = domainTypeNode;
21382138
this.referentTypeNode = referentTypeNode;
21392139
this.getModuleNode = new GetModuleNode(sourceSection);
2140+
validateTypeArguments(sourceSection);
21402141
}
21412142

21422143
@Specialization(guards = "value.getVmClass() == getReferenceClass()")
21432144
protected Object eval(VirtualFrame frame, VmReference value) {
2144-
// constraints may not be used in Reference type annotation referents
2145-
// walk the type and throw if any part of the referent is constrained
2146-
// perform this check at eval-time instead of init-time
2147-
// because type aliases can replace nodes between init and eval
2148-
referentTypeNode.acceptTypeNode(
2149-
true,
2150-
(typeNode) -> {
2151-
if (typeNode instanceof ConstrainedTypeNode) {
2152-
throw exceptionBuilder()
2153-
.evalError("invalidReferenceTypeAnnotationWithConstraint")
2154-
.withLocation(this)
2155-
.build();
2156-
}
2157-
return true;
2158-
});
2159-
21602145
if (referentTypeNode.isNoopTypeCheck()) {
21612146
return value;
21622147
}
@@ -2178,6 +2163,30 @@ protected Object eval(VirtualFrame frame, VmReference value) {
21782163
throw new VmTypeMismatchException.Reference(sourceSection, value, domainType, referentType);
21792164
}
21802165

2166+
public void validateTypeArguments(@Nullable SourceSection aliasSourceSection) {
2167+
// constraints may not be used in Reference type annotation referents
2168+
// walk the type and throw if any part of the referent is constrained
2169+
2170+
// TODO improve error message when this type node and/or referent constraint are behind type
2171+
// aliases
2172+
referentTypeNode.acceptTypeNode(
2173+
true,
2174+
(typeNode) -> {
2175+
if (typeNode instanceof ConstrainedTypeNode) {
2176+
CompilerDirectives.transferToInterpreter();
2177+
var err =
2178+
exceptionBuilder()
2179+
.evalError("invalidReferenceTypeAnnotationWithConstraint")
2180+
.withLocation(this);
2181+
if (aliasSourceSection != null) {
2182+
err.withSourceSection(aliasSourceSection);
2183+
}
2184+
throw err.build();
2185+
}
2186+
return true;
2187+
});
2188+
}
2189+
21812190
@Fallback
21822191
protected Object fallback(Object value) {
21832192
throw typeMismatch(value, RefModule.getReferenceClass());
@@ -2680,7 +2689,7 @@ public TypeAliasTypeNode(
26802689

26812690
this.typeAlias = typeAlias;
26822691
this.typeArgumentNodes = typeArgumentNodes;
2683-
aliasedTypeNode = typeAlias.instantiate(typeArgumentNodes);
2692+
aliasedTypeNode = typeAlias.instantiate(typeArgumentNodes, sourceSection);
26842693
}
26852694

26862695
public TypeNode getAliasedTypeNode() {

pkl-core/src/main/java/org/pkl/core/runtime/VmReference.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package org.pkl.core.runtime;
1717

18+
import com.oracle.truffle.api.frame.VirtualFrame;
19+
import com.oracle.truffle.api.source.SourceSection;
1820
import java.util.ArrayList;
1921
import java.util.HashSet;
2022
import java.util.List;
@@ -27,6 +29,9 @@
2729
import org.pkl.core.PType;
2830
import org.pkl.core.Reference;
2931
import org.pkl.core.TypeAlias;
32+
import org.pkl.core.ast.ExpressionNode;
33+
import org.pkl.core.ast.MemberLookupMode;
34+
import org.pkl.core.ast.expression.member.InvokeMethodVirtualNodeGen;
3035
import org.pkl.core.stdlib.VmObjectFactory;
3136
import org.pkl.core.util.Nullable;
3237

@@ -226,7 +231,7 @@ private static void getCandidateSubscriptType(PType type, Object key, Set<PType>
226231
for (var kt : keyTypes) {
227232
if (kt == PType.UNKNOWN
228233
|| (kt instanceof PType.Class klazz
229-
&& klazz.getPClass().getInfo() == PClassInfo.forValue(key))
234+
&& klazz.getPClass().getInfo() == PClassInfo.forValue(VmValue.export(key)))
230235
|| (kt instanceof PType.StringLiteral stringLiteral
231236
&& stringLiteral.getLiteral().equals(key))) {
232237
normalizeTypes(typeArgs.get(1), clazz.getPClass().getModuleClass(), result);
@@ -414,4 +419,23 @@ public int hashCode() {
414419
result = 31 * result + candidateTypes.hashCode();
415420
return result;
416421
}
422+
423+
public String toPklString(@Nullable VirtualFrame frame, @Nullable SourceSection sourceSection) {
424+
if (frame == null) {
425+
frame = VmUtils.createEmptyMaterializedFrame();
426+
}
427+
if (sourceSection == null) {
428+
sourceSection = VmUtils.unavailableSourceSection();
429+
}
430+
431+
return (String)
432+
InvokeMethodVirtualNodeGen.create(
433+
sourceSection,
434+
Identifier.TO_STRING,
435+
new ExpressionNode[] {},
436+
MemberLookupMode.EXPLICIT_RECEIVER,
437+
null,
438+
null)
439+
.executeWith(frame, this, getVmClass());
440+
}
417441
}

pkl-core/src/main/java/org/pkl/core/runtime/VmTypeAlias.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.pkl.core.ast.VmModifier;
3232
import org.pkl.core.ast.type.TypeNode;
3333
import org.pkl.core.ast.type.TypeNode.ConstrainedTypeNode;
34+
import org.pkl.core.ast.type.TypeNode.ReferenceTypeNode;
3435
import org.pkl.core.ast.type.TypeNode.TypeVariableNode;
3536
import org.pkl.core.ast.type.TypeNode.UnknownTypeNode;
3637
import org.pkl.core.util.LateInit;
@@ -177,7 +178,8 @@ public Frame getEnclosingFrame() {
177178
}
178179

179180
@TruffleBoundary
180-
public TypeNode instantiate(TypeNode[] typeArgumentNodes) {
181+
public TypeNode instantiate(
182+
TypeNode[] typeArgumentNodes, SourceSection typeAliasTypeNodeSourceSection) {
181183
// Cloning the type node means that the entire type check remains within a single root node,
182184
// which should be good for interpreted and compiled performance alike:
183185
// * Fewer root nodes to call
@@ -199,6 +201,13 @@ public TypeNode instantiate(TypeNode[] typeArgumentNodes) {
199201
}
200202
return true;
201203
});
204+
clone.accept(
205+
node -> {
206+
if (node instanceof ReferenceTypeNode referenceTypeNode) {
207+
referenceTypeNode.validateTypeArguments(typeAliasTypeNodeSourceSection);
208+
}
209+
return true;
210+
});
202211

203212
return clone;
204213
}

pkl-core/src/main/java/org/pkl/core/stdlib/AbstractStringRenderer.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.pkl.core.runtime.VmClass;
1919
import org.pkl.core.runtime.VmFunction;
20+
import org.pkl.core.runtime.VmReference;
2021
import org.pkl.core.runtime.VmTypeAlias;
2122

2223
/** Base class for renderers that are part of the standard library. */
@@ -51,6 +52,11 @@ protected void decreaseIndent() {
5152
currIndent.setLength(currIndent.length() - indent.length());
5253
}
5354

55+
@Override
56+
public void visitReference(VmReference value) {
57+
visitString(value.toPklString(null, currSourceSection));
58+
}
59+
5460
// override these to mark them final
5561

5662
@Override

pkl-core/src/test/files/LanguageSnippetTests/input/api/reference.pkl

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class A extends Resource {
2727
/// Test doc comment
2828
class AProperties {
2929
foo: Int
30-
someMapping: Mapping<String, Int>
31-
someMap: Map<Int, Int>
30+
someMapping: Mapping<String, Int?>
31+
someMap: Map<MapKey, Int>
3232
someListing: Listing<Int>
3333
someList: List<Int>
3434
nonInt: String
@@ -42,20 +42,26 @@ class B extends Resource {
4242

4343
class BProperties {
4444
foo: String
45-
someMapping: Mapping<String, String>
46-
someMap: Map<Int, String>
45+
someMapping: Mapping<String, String?>
46+
someMap: Map<MapKey, String>
4747
someListing: Listing<String>
4848
someList: List<String>
4949
nonString: Int
5050
}
5151

52+
class MapKey {
53+
k: Int
54+
55+
function toString(): String = "key:\(k)"
56+
}
57+
5258
class K {
5359
aId: String | *Ref<String>?
5460
bId: String | *Ref<String>?
5561
aProperties: AProperties | *Ref<AProperties>?
5662
bProperties: BProperties | *Ref<BProperties>?
57-
aValues: Listing<Int | Ref<Int>>?
58-
bValues: Listing<String | Ref<String>>?
63+
aValues: Listing<Int | Ref<Int?>>?
64+
bValues: Listing<String | Ref<String?>>?
5965
splitUnion: Ref<Listing<String> | Listing<Int>>?
6066
}
6167

@@ -84,15 +90,15 @@ k: K = new {
8490
aValues {
8591
aRef.outputs.foo
8692
aRef.outputs.someMapping["key"]
87-
aRef.outputs.someMap[123]
93+
aRef.outputs.someMap[new MapKey { k = 123 }]
8894
aRef.outputs.someListing[0]
8995
aRef.outputs.someList[math.maxInt]
9096
bRef.outputs.nonString
9197
}
9298
bValues {
9399
bRef.outputs.foo
94100
bRef.outputs.someMapping["key"]
95-
bRef.outputs.someMap[123]
101+
bRef.outputs.someMap[new MapKey { k = 123 }]
96102
bRef.outputs.someListing[0]
97103
bRef.outputs.someList[math.maxInt]
98104
aRef.outputs.nonInt
@@ -105,16 +111,5 @@ j: K = new {
105111
splitUnion = unknownRef.outputs.someListing
106112
}
107113

108-
local x: UInt = 0
109-
local y = ref.Reference(d, UInt, x)
110-
local z = y
111-
112114
refInterpolation = "\(aRef.outputs.someListing[1])"
113-
114-
output {
115-
renderer {
116-
converters {
117-
[ref.Reference] = (it) -> it.toString()
118-
}
119-
}
120-
}
115+
kInterpolation = "\(k)"

pkl-core/src/test/files/LanguageSnippetTests/input/api/reference2.pkl

Lines changed: 0 additions & 19 deletions
This file was deleted.

pkl-core/src/test/files/LanguageSnippetTests/input/api/reference3.pkl

Lines changed: 0 additions & 38 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import "pkl:ref"
2+
3+
class D extends ref.Domain {
4+
function referenceToString(data: Any, path: List<ref.Access>): String = throw("not supported")
5+
}
6+
local d: D = new {}
7+
typealias Ref<T> = ref.Reference<D, T>
8+
9+
test = ref.Reference(d, String, "") as Ref<Int>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import "pkl:ref"
2+
3+
class D extends ref.Domain {
4+
function referenceToString(data: Any, path: List<ref.Access>): String = throw("not supported")
5+
}
6+
typealias Ref<T> = ref.Reference<D, T>
7+
local d: D = new {}
8+
9+
test = ref.Reference(d, String, "") as Ref<Listing<String(true)>>

0 commit comments

Comments
 (0)