Skip to content

Commit ce06670

Browse files
committed
Implement Reference<T>
1 parent b7ba6a8 commit ce06670

34 files changed

Lines changed: 1294 additions & 53 deletions

docs/modules/ROOT/partials/component-attributes.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ endif::[]
148148
:uri-stdlib-Function4: {uri-stdlib-baseModule}/Function4
149149
:uri-stdlib-Function5: {uri-stdlib-baseModule}/Function5
150150
:uri-stdlib-Bytes: {uri-stdlib-baseModule}/Bytes
151+
:uri-stdlib-Reference: {uri-stdlib-baseModule}/Reference
152+
:uri-stdlib-ReferenceAccess: {uri-stdlib-baseModule}/ReferenceAccess
151153
:uri-stdlib-Resource: {uri-stdlib-baseModule}/Resource
152154
:uri-stdlib-outputFiles: {uri-stdlib-baseModule}/ModuleOutput#files
153155
:uri-stdlib-FileOutput: {uri-stdlib-baseModule}/FileOutput

docs/modules/bindings-specification/pages/binary-encoding.adoc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,24 @@ The array's length is the number of slots that are filled. For example, xref:{ur
187187
|
188188
|
189189
|
190+
191+
|link:{uri-stdlib-Reference}[Reference]
192+
|`0x20`
193+
|`<value>`
194+
|Root value
195+
|link:{uri-messagepack-array}[array]
196+
|Array of link:{uri-stdlib-ReferenceAccess}[property access] values
197+
|
198+
|
199+
200+
|link:{uri-stdlib-ReferenceAccess}[ReferenceAccess]
201+
|`0x21`
202+
|link:{uri-messagepack-str}[str] (when a property access) or link:{uri-messagepack-str}[nil] (when a subscript access)
203+
|Property name
204+
|`<value>` or link:{uri-messagepack-str}[nil] (when a property access)
205+
|Key value
206+
|
207+
|
190208
|===
191209

192210
[[type-name-encoding]]

pkl-core/src/main/java/org/pkl/core/PClass.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ public final class PClass extends Member implements Value {
2727
private final List<TypeParameter> typeParameters;
2828
private final Map<String, Property> properties;
2929
private final Map<String, Method> methods;
30+
private final @Nullable PClass moduleClass;
3031

3132
private @Nullable PType supertype;
3233
private @Nullable PClass superclass;
@@ -42,12 +43,14 @@ public PClass(
4243
PClassInfo<?> classInfo,
4344
List<TypeParameter> typeParameters,
4445
Map<String, Property> properties,
45-
Map<String, Method> methods) {
46+
Map<String, Method> methods,
47+
@Nullable PClass moduleClass) {
4648
super(docComment, sourceLocation, modifiers, annotations, classInfo.getSimpleName());
4749
this.classInfo = classInfo;
4850
this.typeParameters = typeParameters;
4951
this.properties = properties;
5052
this.methods = methods;
53+
this.moduleClass = moduleClass;
5154
}
5255

5356
public void initSupertype(PType supertype, PClass superclass) {
@@ -119,6 +122,11 @@ public Map<String, Method> getAllMethods() {
119122
return allMethods;
120123
}
121124

125+
/** Returns the class's containing module's class, or this class if it is a module class. */
126+
public PClass getModuleClass() {
127+
return moduleClass != null ? moduleClass : this;
128+
}
129+
122130
@Override
123131
public void accept(ValueVisitor visitor) {
124132
visitor.visitClass(this);
@@ -138,6 +146,10 @@ public String toString() {
138146
return getDisplayName();
139147
}
140148

149+
public boolean isSubclassOf(PClass other) {
150+
return this == other || getSuperclass() != null && getSuperclass().isSubclassOf(other);
151+
}
152+
141153
public abstract static class ClassMember extends Member {
142154
@Serial private static final long serialVersionUID = 0L;
143155

pkl-core/src/main/java/org/pkl/core/PType.java

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818
import java.io.Serial;
1919
import java.io.Serializable;
2020
import java.util.*;
21+
import java.util.stream.Collectors;
2122

2223
/** A Pkl type as used in type annotations. */
2324
public abstract class PType implements Serializable {
@@ -27,18 +28,33 @@ public abstract class PType implements Serializable {
2728
public static final PType UNKNOWN =
2829
new PType() {
2930
@Serial private static final long serialVersionUID = 0L;
31+
32+
@Override
33+
public String toString() {
34+
return "unknown";
35+
}
3036
};
3137

3238
/** The bottom type. */
3339
public static final PType NOTHING =
3440
new PType() {
3541
@Serial private static final long serialVersionUID = 0L;
42+
43+
@Override
44+
public String toString() {
45+
return "nothing";
46+
}
3647
};
3748

3849
/** The type of the enclosing module. */
3950
public static final PType MODULE =
4051
new PType() {
4152
@Serial private static final long serialVersionUID = 0L;
53+
54+
@Override
55+
public String toString() {
56+
return "module";
57+
}
4258
};
4359

4460
private PType() {}
@@ -59,6 +75,10 @@ public StringLiteral(String literal) {
5975
public String getLiteral() {
6076
return literal;
6177
}
78+
79+
public String toString() {
80+
return ValueFormatter.basic().formatStringValue(literal, "");
81+
}
6282
}
6383

6484
public static final class Class extends PType {
@@ -92,6 +112,18 @@ public PClass getPClass() {
92112
public List<PType> getTypeArguments() {
93113
return typeArguments;
94114
}
115+
116+
@Override
117+
public String toString() {
118+
var result = pClass.getDisplayName();
119+
if (!typeArguments.isEmpty()) {
120+
result +=
121+
"<"
122+
+ typeArguments.stream().map(Object::toString).collect(Collectors.joining(", "))
123+
+ ">";
124+
}
125+
return result;
126+
}
95127
}
96128

97129
public static final class Nullable extends PType {
@@ -106,6 +138,13 @@ public Nullable(PType baseType) {
106138
public PType getBaseType() {
107139
return baseType;
108140
}
141+
142+
@Override
143+
public String toString() {
144+
return baseType instanceof Function || baseType instanceof Union
145+
? "(" + baseType + ")?"
146+
: baseType + "?";
147+
}
109148
}
110149

111150
public static final class Constrained extends PType {
@@ -126,6 +165,16 @@ public PType getBaseType() {
126165
public List<String> getConstraints() {
127166
return constraints;
128167
}
168+
169+
@Override
170+
public String toString() {
171+
return (baseType instanceof Function || baseType instanceof Union
172+
? "(" + baseType + ")"
173+
: baseType)
174+
+ "("
175+
+ String.join(", ", constraints)
176+
+ ")";
177+
}
129178
}
130179

131180
public static final class Alias extends PType {
@@ -161,6 +210,18 @@ public List<PType> getTypeArguments() {
161210
public PType getAliasedType() {
162211
return aliasedType;
163212
}
213+
214+
@Override
215+
public String toString() {
216+
var result = typeAlias.getDisplayName();
217+
if (!typeArguments.isEmpty()) {
218+
result +=
219+
"<"
220+
+ typeArguments.stream().map(Object::toString).collect(Collectors.joining(", "))
221+
+ ">";
222+
}
223+
return result;
224+
}
164225
}
165226

166227
public static final class Function extends PType {
@@ -181,6 +242,14 @@ public List<PType> getParameterTypes() {
181242
public PType getReturnType() {
182243
return returnType;
183244
}
245+
246+
@Override
247+
public String toString() {
248+
return "("
249+
+ parameterTypes.stream().map(Object::toString).collect(Collectors.joining(", "))
250+
+ ") -> "
251+
+ returnType;
252+
}
184253
}
185254

186255
public static final class Union extends PType {
@@ -195,6 +264,11 @@ public Union(List<PType> elementTypes) {
195264
public List<PType> getElementTypes() {
196265
return elementTypes;
197266
}
267+
268+
@Override
269+
public String toString() {
270+
return elementTypes.stream().map(Object::toString).collect(Collectors.joining(" | "));
271+
}
198272
}
199273

200274
public static final class TypeVariable extends PType {
@@ -213,5 +287,10 @@ public String getName() {
213287
public TypeParameter getTypeParameter() {
214288
return typeParameter;
215289
}
290+
291+
@Override
292+
public String toString() {
293+
return typeParameter.getName();
294+
}
216295
}
217296
}

pkl-core/src/main/java/org/pkl/core/TypeAlias.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@ public final class TypeAlias extends Member implements Value {
2828
private final String moduleName;
2929
private final String qualifiedName;
3030
private final List<TypeParameter> typeParameters;
31+
private final PClass moduleClass;
3132

3233
@LateInit private PType aliasedType;
3334

@@ -39,11 +40,13 @@ public TypeAlias(
3940
String simpleName,
4041
String moduleName,
4142
String qualifiedName,
42-
List<TypeParameter> typeParameters) {
43+
List<TypeParameter> typeParameters,
44+
PClass moduleClass) {
4345
super(docComment, sourceLocation, modifiers, annotations, simpleName);
4446
this.moduleName = moduleName;
4547
this.qualifiedName = qualifiedName;
4648
this.typeParameters = typeParameters;
49+
this.moduleClass = moduleClass;
4750
}
4851

4952
public void initAliasedType(PType type) {
@@ -78,6 +81,10 @@ public List<TypeParameter> getTypeParameters() {
7881
return typeParameters;
7982
}
8083

84+
public PClass getModuleClass() {
85+
return moduleClass;
86+
}
87+
8188
/** Returns the type that this type alias stands for. */
8289
public PType getAliasedType() {
8390
assert aliasedType != null;

pkl-core/src/main/java/org/pkl/core/ast/expression/binary/SubscriptNode.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -98,6 +98,20 @@ protected Object eval(
9898
return readMember(dynamic, key, callNode);
9999
}
100100

101+
@Specialization
102+
protected VmReference eval(VmReference reference, Object key) {
103+
var result = reference.withSubscriptAccess(key);
104+
if (result != null) return result;
105+
106+
CompilerDirectives.transferToInterpreter();
107+
throw exceptionBuilder()
108+
.evalError(
109+
"operatorNotDefined2", getShortName(), reference.exportType(), VmUtils.getClass(key))
110+
.withProgramValue("Left operand", reference)
111+
.withProgramValue("Right operand", key)
112+
.build();
113+
}
114+
101115
@Specialization
102116
protected long eval(VmBytes receiver, long index) {
103117
if (index < 0 || index >= receiver.getLength()) {

pkl-core/src/main/java/org/pkl/core/ast/expression/member/ReadPropertyNode.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
2+
* Copyright © 2024-2026 Apple Inc. and the Pkl project authors. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -61,6 +61,18 @@ protected ReadPropertyNode(SourceSection sourceSection, Identifier propertyName)
6161
this(sourceSection, propertyName, MemberLookupMode.EXPLICIT_RECEIVER, false);
6262
}
6363

64+
@Specialization
65+
protected VmReference evalReference(VmReference receiver) {
66+
assert lookupMode == MemberLookupMode.EXPLICIT_RECEIVER;
67+
var result = receiver.withPropertyAccess(propertyName);
68+
if (result != null) return result;
69+
70+
CompilerDirectives.transferToInterpreter();
71+
throw exceptionBuilder()
72+
.evalError("cannotFindPropertyInReference", propertyName, receiver.exportType())
73+
.build();
74+
}
75+
6476
// This method effectively covers `VmObject receiver` but is implemented in a more
6577
// efficient way. See:
6678
// https://www.graalvm.org/22.0/graalvm-as-a-platform/language-implementation-framework/TruffleLibraries/#strategy-2-java-interfaces

0 commit comments

Comments
 (0)