diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-11-01 21:48:11 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-11-01 21:48:11 +0000 |
| commit | 158ebdbc74e74894a32be9c8908da4b068326b67 (patch) | |
| tree | defe734b21c4cd7201c8b298e6253211ced009ec /src/main/java | |
| parent | 9f8eb523395296b5d37498d89423daedf8e0121d (diff) | |
Read tables as members from database schema
Diffstat (limited to 'src/main/java')
4 files changed, 74 insertions, 9 deletions
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 d73c245..da83e6f 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -163,16 +163,19 @@ public class TypeChecker { UntypedDatabaseSchemaDefinitionNode untyped, TypeCheckerNamespaceContext context ) { + var databaseSchema = new DatabaseSchema(context.namespaceName(), untyped.name()); var databaseSchemaInfo = new DatabaseSchemaInfo(new LinkedHashMap<>()); var typedBody = untyped.body().stream() - .map(statement -> typeCheckDatabaseSchemaStatement(statement, databaseSchemaInfo, context)) + .map(statement -> typeCheckDatabaseSchemaStatement( + statement, + databaseSchema, + databaseSchemaInfo, + context + )) .toList(); - context.defineDatabaseSchema( - new DatabaseSchema(context.namespaceName(), untyped.name()), - databaseSchemaInfo - ); + context.defineDatabaseSchema(databaseSchema, databaseSchemaInfo); return new TypedDatabaseSchemaDefinitionNode( untyped.name(), @@ -509,17 +512,24 @@ public class TypeChecker { static TypedDatabaseSchemaStatementNode typeCheckDatabaseSchemaStatement( UntypedDatabaseSchemaStatementNode statement, + DatabaseSchema databaseSchema, DatabaseSchemaInfo databaseSchemaInfo, TypeCheckerNamespaceContext context ) { return switch (statement) { case UntypedTableDefinitionNode untypedTableDefinition -> - typeCheckTableDefinition(untypedTableDefinition, databaseSchemaInfo, context); + typeCheckTableDefinition( + untypedTableDefinition, + databaseSchema, + databaseSchemaInfo, + context + ); }; } private static TypedTableDefinitionNode typeCheckTableDefinition( UntypedTableDefinitionNode untyped, + DatabaseSchema databaseSchema, DatabaseSchemaInfo databaseSchemaInfo, TypeCheckerNamespaceContext context ) { @@ -542,7 +552,8 @@ public class TypeChecker { throw new NoSuchFieldError(rowType, untyped.primaryKey(), untyped.source()); } - var tableInfo = new TableInfo(rowType, primaryKeyField.get()); + var table = new Table(databaseSchema, untyped.name()); + var tableInfo = new TableInfo(table, rowType, primaryKeyField.get()); databaseSchemaInfo.tables().put(untyped.name(), tableInfo); @@ -694,12 +705,37 @@ public class TypeChecker { case UntypedFunctionExpressionNode _ -> { throw new UnsupportedOperationException("TODO"); } - case UntypedMemberAccessNode _ -> { - throw new UnsupportedOperationException("TODO"); + case UntypedMemberAccessNode memberAccess -> { + return evalMemberAccess(memberAccess, context); } case UntypedReferenceNode reference -> { return lookupTypeLevelValue(reference.name(), reference.source(), context); } } } + + private static TypeLevelValue evalMemberAccess( + UntypedMemberAccessNode memberAccess, + TypeCheckerNamespaceContext context + ) { + var receiver = evalExpression(memberAccess.receiver(), context); + switch (receiver) { + case DatabaseSchema databaseSchema -> { + var schemaInfo = context.databaseSchemaInfo(databaseSchema); + var tableInfo = schemaInfo.tables().get(memberAccess.memberName()); + if (tableInfo != null) { + return tableInfo.table(); + } + } + + case Table _, Type _, TypeConstructor<?> _ -> { + } + } + + throw new NoSuchMemberError( + new TypeLevelValueType(receiver), + memberAccess.memberName(), + memberAccess.source() + ); + } } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java index b18769d..4a82c05 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java @@ -64,6 +64,10 @@ public class TypeCheckerNamespaceContext { this.typesInfo.defineDatabaseSchema(databaseSchema, databaseSchemaInfo); } + public DatabaseSchemaInfo databaseSchemaInfo(DatabaseSchema databaseSchema) { + return this.typesInfo.databaseSchemaInfo(databaseSchema); + } + public void defineEnumType(EnumType enumType, List<EnumVariant> enumVariants) { this.typesInfo.defineEnumType(enumType, enumVariants); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchMemberError.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchMemberError.java new file mode 100644 index 0000000..b2b1d55 --- /dev/null +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/errors/NoSuchMemberError.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 NoSuchMemberError extends SourceError { + private final Type type; + private final String memberName; + + public NoSuchMemberError(Type type, String memberName, Source source) { + super(type.describe() + " does not have a member named " + memberName, source); + this.type = type; + this.memberName = memberName; + } + + public Type type() { + return type; + } + + public String memberName() { + return memberName; + } +} diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/types/TableInfo.java b/src/main/java/org/zwobble/hobgoblin/compiler/types/TableInfo.java index 6632e51..b991b54 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/types/TableInfo.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/types/TableInfo.java @@ -1,6 +1,7 @@ package org.zwobble.hobgoblin.compiler.types; public record TableInfo( + Table table, SimpleStructType rowType, Field primaryKey ) { |
