summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-10-16 08:44:55 +0100
committerMichael Williamson <mike@zwobble.org>2026-10-16 08:44:55 +0100
commit77c708cbb7a4fb49db50a8917bdcdd777eff6ccb (patch)
tree4aeb55e2ff372c980e3893302a0f0166f656d67c /src/main/java
parent8fe3ffe8c7aad4c3270b889bce0efaf4ab912157 (diff)
Check primary key field exists
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedTableDefinitionNode.java8
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java16
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchFieldError.java24
-rw-r--r--src/main/java/org/zwobble/hobgoblin/compiler/types/HobgoblinNativeTypes.java6
4 files changed, 47 insertions, 7 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedTableDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedTableDefinitionNode.java
index 315aeef..9a9f98b 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedTableDefinitionNode.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedTableDefinitionNode.java
@@ -8,18 +8,18 @@ package org.zwobble.hobgoblin.compiler.ast.typed;
public record TypedTableDefinitionNode(
String name,
org.zwobble.hobgoblin.compiler.types.StructType rowType,
- String primaryKey,
+ org.zwobble.hobgoblin.compiler.types.Field primaryKey,
org.zwobble.hobgoblin.compiler.ast.DocComment docComment,
org.zwobble.hobgoblin.compiler.sources.Source source
) implements org.zwobble.hobgoblin.compiler.ast.typed.TypedDatabaseSchemaStatementNode {
public static org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder arbitrary() {
- return new org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder("", org.zwobble.hobgoblin.compiler.types.HobgoblinNativeTypes.arbitraryStructType(), "", org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource());
+ return new org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder("", org.zwobble.hobgoblin.compiler.types.HobgoblinNativeTypes.arbitraryStructType(), org.zwobble.hobgoblin.compiler.types.HobgoblinNativeTypes.arbitraryField(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource());
}
public record Builder(
String name,
org.zwobble.hobgoblin.compiler.types.StructType rowType,
- String primaryKey,
+ org.zwobble.hobgoblin.compiler.types.Field primaryKey,
org.zwobble.hobgoblin.compiler.ast.DocComment docComment,
org.zwobble.hobgoblin.compiler.sources.Source source
) implements org.zwobble.hobgoblin.compiler.ast.typed.TypedDatabaseSchemaStatementNode.Builder {
@@ -35,7 +35,7 @@ public record TypedTableDefinitionNode(
return new org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder(name, rowType, primaryKey, docComment, source);
}
- public org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder withPrimaryKey(String primaryKey) {
+ public org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder withPrimaryKey(org.zwobble.hobgoblin.compiler.types.Field primaryKey) {
return new org.zwobble.hobgoblin.compiler.ast.typed.TypedTableDefinitionNode.Builder(name, rowType, primaryKey, docComment, source);
}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
index 211726b..c8dfc05 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java
@@ -5,6 +5,7 @@ import org.zwobble.hobgoblin.compiler.ast.untyped.*;
import org.zwobble.hobgoblin.compiler.builtins.NativeTypes;
import org.zwobble.hobgoblin.compiler.sources.Source;
import org.zwobble.hobgoblin.compiler.typechecker.errors.*;
+import org.zwobble.hobgoblin.compiler.typechecker.errors.NoSuchFieldError;
import org.zwobble.hobgoblin.compiler.types.*;
import java.util.ArrayList;
@@ -470,18 +471,27 @@ public class TypeChecker {
) {
var rowTypeTypedNode = typeCheckMetaType(untyped.rowType(), context);
- if (!(rowTypeTypedNode.value() instanceof StructType rowType)) {
+ // TODO: allow constructed struct types
+ if (!(rowTypeTypedNode.value() instanceof SimpleStructType rowType)) {
throw new TableRowTypeMustBeStructError(
rowTypeTypedNode.value(),
rowTypeTypedNode.source()
);
}
+ var fields = context.fieldsOf(rowType).orElse(List.of());
+ var primaryKeyField = fields.stream()
+ .filter(field -> field.name().equals(untyped.primaryKey()))
+ .findFirst();
+ if (primaryKeyField.isEmpty()) {
+ // TODO: more precise source.
+ throw new NoSuchFieldError(rowType, untyped.primaryKey(), untyped.source());
+ }
+
return new TypedTableDefinitionNode(
untyped.name(),
rowType,
- // TODO: check primary key is valid.
- untyped.primaryKey(),
+ primaryKeyField.get(),
untyped.docComment(),
untyped.source()
);
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchFieldError.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchFieldError.java
new file mode 100644
index 0000000..635ea6f
--- /dev/null
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchFieldError.java
@@ -0,0 +1,24 @@
+package org.zwobble.hobgoblin.compiler.typechecker.errors;
+
+import org.zwobble.hobgoblin.compiler.errors.SourceError;
+import org.zwobble.hobgoblin.compiler.sources.Source;
+import org.zwobble.hobgoblin.compiler.types.Type;
+
+public class NoSuchFieldError extends SourceError {
+ private final Type type;
+ private final String fieldName;
+
+ public NoSuchFieldError(Type type, String fieldName, Source source) {
+ super(type.describe() + " does not have a field named " + fieldName, source);
+ this.type = type;
+ this.fieldName = fieldName;
+ }
+
+ public Type type() {
+ return type;
+ }
+
+ public String fieldName() {
+ return fieldName;
+ }
+}
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/HobgoblinNativeTypes.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/HobgoblinNativeTypes.java
index 37e6935..96efbd2 100644
--- a/src/main/java/org/zwobble/hobgoblin/compiler/types/HobgoblinNativeTypes.java
+++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/HobgoblinNativeTypes.java
@@ -1,5 +1,7 @@
package org.zwobble.hobgoblin.compiler.types;
+import org.zwobble.hobgoblin.compiler.sources.NullSource;
+
import java.util.function.Supplier;
public class HobgoblinNativeTypes {
@@ -34,4 +36,8 @@ public class HobgoblinNativeTypes {
public static <T extends ConstructibleType> TypeOrConstructor<T> arbitraryTypeOrConstructor(Supplier<T> type) {
return TypeOrConstructor.type(type.get());
}
+
+ public static Field arbitraryField() {
+ return new Field("", arbitraryType(), NullSource.INSTANCE);
+ }
}