diff options
Diffstat (limited to 'src/main/java/org/zwobble')
14 files changed, 170 insertions, 111 deletions
diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java index dc9a8fe..f2e6b97 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/typed/TypedStructDefinitionNode.java @@ -5,10 +5,11 @@ import org.zwobble.hobgoblin.compiler.sources.Source; import org.zwobble.hobgoblin.compiler.types.StructType; import java.util.List; +import java.util.Optional; public record TypedStructDefinitionNode( StructType type, - List<TypedStructFieldDefinitionNode> fields, + Optional<List<TypedStructFieldDefinitionNode>> fields, DocComment docComment, Source source ) implements TypedNamespaceStatementNode { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java index 72f45eb..0239ff8 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/ast/untyped/UntypedStructDefinitionNode.java @@ -7,17 +7,17 @@ package org.zwobble.hobgoblin.compiler.ast.untyped; public record UntypedStructDefinitionNode( String name, - java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields, + java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment, org.zwobble.hobgoblin.compiler.sources.Source source ) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode { public static org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder arbitrary() { - return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder("", java.util.List.of(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource()); + return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder("", java.util.Optional.empty(), org.zwobble.hobgoblin.compiler.ast.HobgoblinNativeAst.arbitraryDocComment(), org.zwobble.hobgoblin.compiler.sources.HobgoblinNativeSources.arbitrarySource()); } public record Builder( String name, - java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields, + java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields, org.zwobble.hobgoblin.compiler.ast.DocComment docComment, org.zwobble.hobgoblin.compiler.sources.Source source ) implements org.zwobble.hobgoblin.compiler.ast.untyped.UntypedNamespaceStatementNode.Builder { @@ -29,20 +29,12 @@ public record UntypedStructDefinitionNode( return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source); } - public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields) { - return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source); - } - - public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder addField(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode field) { - var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>(this.fields); - fields.add(field); + public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.Optional<java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>> fields) { return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source); } - public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder addField(org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode.Builder field) { - var fields = new java.util.ArrayList<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode>(this.fields); - fields.add(field.build()); - return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, fields, docComment, source); + public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withFields(java.util.List<org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructFieldDefinitionNode> fields) { + return new org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder(name, java.util.Optional.of(fields), docComment, source); } public org.zwobble.hobgoblin.compiler.ast.untyped.UntypedStructDefinitionNode.Builder withDocComment(org.zwobble.hobgoblin.compiler.ast.DocComment docComment) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java index d7f4bb0..35bb931 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/java/JavaGenerator.java @@ -15,6 +15,8 @@ import java.util.Set; import java.util.stream.Collectors; public class JavaGenerator { + public static final JavaIdentifier INSTANCE_FIELD_NAME = JavaIdentifier.of("INSTANCE"); + private final JavaGeneratorConfig config; public JavaGenerator(JavaGeneratorConfig config) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java index 72f6339..1069f4a 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javapreciselymatchers/JavaPreciselyMatchersGenerator.java @@ -195,7 +195,7 @@ public class JavaPreciselyMatchersGenerator implements Generator { ) )); - for (var field : structDefinition.fields()) { + for (var field : structDefinition.fields().orElse(List.of())) { var fieldType = field.type().value(); var javaFieldTypeRef = this.javaGenerator.generateReferenceTypeRef(fieldType); var javaFieldName = this.javaGenerator.generateFieldName(field.name()); @@ -258,10 +258,6 @@ public class JavaPreciselyMatchersGenerator implements Generator { this.typesInfo = typesInfo; } - public List<Field> fieldsOf(StructType type) { - return this.typesInfo.fieldsOf(type); - } - public List<SumType> variantOf(StructType type) { return this.typesInfo.variantOf(type); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java index d8a0f5f..1c7c962 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatransient0/JavaTransient0Generator.java @@ -492,7 +492,7 @@ public class JavaTransient0Generator implements Generator { return generateEncodeMethod( structDefinition.type(), new JavaBlock( - structDefinition.fields().stream() + structDefinition.fields().orElse(List.of()).stream() .flatMap(field -> generateEncode( new JavaMethodCall( new JavaRef(VALUE_NAME), @@ -512,19 +512,23 @@ public class JavaTransient0Generator implements Generator { return generateDecodeMethod( structDefinition.type(), new JavaBlock( - Stream.concat( - structDefinition.fields().stream() - .flatMap(field -> generateDecode( - this.javaGenerator.generateFieldName(field.name()), - field.type().value() - ).stream()), - Stream.of(new JavaReturn(new JavaNewExpression( - structJavaTypeRef, - structDefinition.fields().stream() - .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name()))) - .toList() - ))) - ).toList() + structDefinition.fields().isEmpty() + ? List.of(new JavaReturn( + new JavaStaticFieldAccess(structJavaTypeRef, JavaGenerator.INSTANCE_FIELD_NAME) + )) + : Stream.concat( + structDefinition.fields().get().stream() + .flatMap(field -> generateDecode( + this.javaGenerator.generateFieldName(field.name()), + field.type().value() + ).stream()), + Stream.of(new JavaReturn(new JavaNewExpression( + structJavaTypeRef, + structDefinition.fields().get().stream() + .<JavaExpression>map(field -> new JavaRef(this.javaGenerator.generateFieldName(field.name()))) + .toList() + ))) + ).toList() ) ); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java index 62c73ff..e8ecaa7 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/javatypes/JavaTypesGenerator.java @@ -122,7 +122,7 @@ public class JavaTypesGenerator implements Generator { TypedStructDefinitionNode structDefinition, Context context ) { - var components = structDefinition.fields().stream() + var components = structDefinition.fields().orElse(List.of()).stream() .map(field -> new JavaRecordComponent( generateTypeRef(field.type(), context), generateFieldName(field.name()) @@ -135,31 +135,51 @@ public class JavaTypesGenerator implements Generator { var builderJavaTypeRef = generateBuilderTypeRef(structDefinition.type()); - var arbitraryComponentValues = structDefinition.fields().stream() - .map(field -> arbitraryValue(field.type(), context)) - .toList(); + var arbitraryValueExpression = new JavaNewExpression( + builderJavaTypeRef, + structDefinition.fields().orElse(List.of()).stream() + .map(field -> arbitraryValue(field.type(), context)) + .toList() + ); + + var body = new ArrayList<JavaClassBodyDeclaration>(); + + if (structDefinition.fields().isEmpty()) { + body.add(new JavaFieldDeclaration( + JavaVisibility.PUBLIC, + JavaMemberKind.STATIC, + this.generateTypeRef(structDefinition.type(), context), + JavaGenerator.INSTANCE_FIELD_NAME, + Optional.of(new JavaNewExpression( + generateTypeRef(structDefinition.type(), context), + List.of() + )) + )); + } + + body.add(new JavaMethodDeclaration( + ARBITRARY_METHOD_NAME, + JavaVisibility.PUBLIC, + JavaMemberKind.STATIC, + builderJavaTypeRef, + List.of(), + List.of(), + new JavaBlock(List.of( + new JavaReturn(arbitraryValueExpression) + )) + )); + + body.add(generateStructDefinitionBuilder( + structDefinition, + components, + context + )); return new JavaRecordDeclaration( generateTypeRef(structDefinition.type(), context), components, implementsTypes, - List.of( - new JavaMethodDeclaration( - ARBITRARY_METHOD_NAME, - JavaVisibility.PUBLIC, - JavaMemberKind.STATIC, - builderJavaTypeRef, - List.of(), - List.of(), - new JavaBlock(List.of( - new JavaReturn(new JavaNewExpression( - builderJavaTypeRef, - arbitraryComponentValues - )) - )) - ), - generateStructDefinitionBuilder(structDefinition, components, context) - ), + body, structDefinition.docComment() ); } @@ -169,9 +189,11 @@ public class JavaTypesGenerator implements Generator { List<JavaRecordComponent> components, Context context ) { - var builderJavaTypeRef = generateBuilderTypeRef(structDefinition.type()); + var structType = structDefinition.type(); - var implementsTypes = context.variantOf(structDefinition.type()).stream() + var builderJavaTypeRef = generateBuilderTypeRef(structType); + + var implementsTypes = context.variantOf(structType).stream() .map(sumType -> this.generateBuilderTypeRef(sumType)) .toList(); @@ -180,18 +202,22 @@ public class JavaTypesGenerator implements Generator { BUILD_METHOD_NAME, JavaVisibility.PUBLIC, JavaMemberKind.INSTANCE, - generateTypeRef(structDefinition.type(), context), + generateTypeRef(structType, context), List.of(), List.of(), new JavaBlock(List.of( - new JavaReturn(new JavaNewExpression( - generateTypeRef(structDefinition.type(), context), - components.stream().<JavaExpression>map(component -> new JavaRef(component.name())).toList() - )) + new JavaReturn( + structDefinition.fields().isPresent() + ? new JavaNewExpression( + generateTypeRef(structType, context), + components.stream().<JavaExpression>map(component -> new JavaRef(component.name())).toList() + ) + : new JavaStaticFieldAccess(this.generateTypeRef(structType, context), JavaGenerator.INSTANCE_FIELD_NAME) + ) )) )); - for (var field : structDefinition.fields()) { + for (var field : structDefinition.fields().orElse(List.of())) { body.addAll(generateBuilderMethodsForField(field, components, builderJavaTypeRef, context)); } @@ -585,9 +611,9 @@ public class JavaTypesGenerator implements Generator { case StructType structType -> { var newSeenTypes = new HashSet<>(seenTypes); newSeenTypes.add(type); - var result = context.fieldsOf(structType).stream() + var fields = context.fieldsOf(structType); + yield fields.orElse(List.of()).stream() .allMatch(field -> isNonRecursivelyConstructable(field.type(), newSeenTypes, context)); - yield result; } case SumType sumType -> { @@ -633,7 +659,7 @@ public class JavaTypesGenerator implements Generator { return this.typesInfo.enumVariants(type); } - public List<Field> fieldsOf(StructType type) { + public Optional<List<Field>> fieldsOf(StructType type) { return this.typesInfo.fieldsOf(type); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java index 15e9e9d..1401b83 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttransient0/RustTransient0Generator.java @@ -386,7 +386,7 @@ public class RustTransient0Generator implements Generator { private RustItem generateEncodeStructFunction(TypedStructDefinitionNode structDefinition) { return generateEncodeFunction( structDefinition.type(), - structDefinition.fields().stream() + structDefinition.fields().orElse(List.of()).stream() .map(field -> generateEncode( new RustPrefixExpression( RustPrefixOperator.BORROW, @@ -406,24 +406,26 @@ public class RustTransient0Generator implements Generator { return generateDecodeFunction( structDefinition.type(), - new RustBlockExpression( - structDefinition.fields().stream() - .<RustStatement>map(field -> new RustLetStatement( - this.rustGenerator.generateFieldName(field.name()), - false, - generateDecode(field.type().value()) - )) - .toList(), - Optional.of(new RustStructExpression( - rustType, - structDefinition.fields().stream() - .map(field -> new RustStructExprField( + structDefinition.fields().isEmpty() + ? new RustBlockExpression(List.of(), Optional.of(rustType)) + : new RustBlockExpression( + structDefinition.fields().get().stream() + .<RustStatement>map(field -> new RustLetStatement( this.rustGenerator.generateFieldName(field.name()), - RustPath.of(this.rustGenerator.generateFieldName(field.name())) + false, + generateDecode(field.type().value()) )) - .toList() - )) - ) + .toList(), + Optional.of(new RustStructExpression( + rustType, + structDefinition.fields().get().stream() + .map(field -> new RustStructExprField( + this.rustGenerator.generateFieldName(field.name()), + RustPath.of(this.rustGenerator.generateFieldName(field.name())) + )) + .toList() + )) + ) ); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java index 99b4208..8ed9d9e 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/output/generators/rusttypes/RustTypesGenerator.java @@ -127,7 +127,7 @@ public class RustTypesGenerator implements Generator { var rustStructName = this.rustGenerator.generateTypeName(structDefinition.name()); - var rustFields = structDefinition.fields().stream() + var rustFields = structDefinition.fields().orElse(List.of()).stream() .map(field -> new RustStructField( this.rustGenerator.generateFieldName(field.name()), generateRustTypeExpression(field.type(), context) diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java index 47a8095..e312f30 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/Parser.java @@ -210,11 +210,7 @@ public class Parser { var name = tokens.next(TokenType.IDENTIFIER); tokens.skip(TokenType.SYMBOL_BRACE_OPEN); - var fields = parseMany( - () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE), - () -> parseStructFieldDefinition(tokens), - () -> true - ); + var fields = parseStructDefinitionFields(tokens); tokens.skip(TokenType.SYMBOL_BRACE_CLOSE); @@ -229,6 +225,21 @@ public class Parser { ); } + private static Optional<List<UntypedStructFieldDefinitionNode>> parseStructDefinitionFields(TokenIterator tokens) { + var isSingleton = tokens.trySkip(TokenType.IDENTIFIER, "singleton"); + if (isSingleton) { + tokens.skip(TokenType.SYMBOL_SEMICOLON); + return Optional.empty(); + } else { + var fields = parseMany( + () -> tokens.isNext(TokenType.SYMBOL_BRACE_CLOSE), + () -> parseStructFieldDefinition(tokens), + () -> true + ); + return Optional.of(fields); + } + } + private static UntypedStructFieldDefinitionNode parseStructFieldDefinition( TokenIterator tokens ) { diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java index 55edd97..43705a1 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/parser/TokenIterator.java @@ -54,6 +54,16 @@ class TokenIterator { } } + public boolean trySkip(TokenType tokenType, String value) { + var token = peek(); + if (token.tokenType().equals(tokenType) && value.contentEquals(token.charSequence())) { + this.tokenIndex++; + return true; + } else { + return false; + } + } + private Token getAbsolute(int index) { if (index < this.tokens.size()) { return this.tokens.get(index); 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 d55c490..f03f979 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeChecker.java @@ -8,6 +8,7 @@ import org.zwobble.hobgoblin.compiler.types.*; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import static org.zwobble.hobgoblin.compiler.typechecker.NamespaceNameResolution.resolveNamespaceName; import static org.zwobble.hobgoblin.compiler.typechecker.TypeCheckerSubtyping.isSubtype; @@ -180,9 +181,13 @@ public class TypeChecker { ) { var structType = (StructType) lookupMetaType(untyped.name(), untyped.source(), context); - var typeCheckedFieldDefinitions = typeCheckFieldDefinitions(untyped.fields(), context); + var typeCheckedFieldDefinitions = untyped.fields().isPresent() + ? Optional.of(typeCheckFieldDefinitions(untyped.fields().get(), context)) + : Optional.<TypeCheckFieldDefinitionsResult>empty(); + var typedFields = typeCheckedFieldDefinitions.map(TypeCheckFieldDefinitionsResult::fields); + var typedFieldNodes = typeCheckedFieldDefinitions.map(TypeCheckFieldDefinitionsResult::typedFieldNodes); - context.defineStructType(structType, typeCheckedFieldDefinitions.fields()); + context.defineStructType(structType, typedFields); for (var sumType : context.variantOf(structType)) { var sumTypeFields = context.fieldsOf(sumType); @@ -190,14 +195,14 @@ public class TypeChecker { sumType, sumTypeFields, structType, - typeCheckedFieldDefinitions.fields, + typedFields, context.toTypesInfo() ); } return new TypedStructDefinitionNode( structType, - typeCheckedFieldDefinitions.typedFieldNodes(), + typedFieldNodes, untyped.docComment(), untyped.source() ); @@ -303,13 +308,15 @@ public class TypeChecker { SumType sumType, List<Field> sumTypeFields, StructType variantType, - List<Field> variantTypeFields, + Optional<List<Field>> variantTypeFields, TypesInfo typesInfo ) { for (var sumTypeField : sumTypeFields) { - var variantTypeField = variantTypeFields.stream() - .filter(field -> field.name().equals(sumTypeField.name())) - .findFirst(); + var variantTypeField = variantTypeFields.flatMap( + fields -> fields.stream() + .filter(field -> field.name().equals(sumTypeField.name())) + .findFirst() + ); if (variantTypeField.isEmpty()) { throw new SubtypeIsMissingFieldError(sumType, variantType, sumTypeField.name(), sumTypeField.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 0a61de7..5484904 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypeCheckerNamespaceContext.java @@ -61,7 +61,7 @@ public class TypeCheckerNamespaceContext { this.typesInfo.defineEnumType(enumType, enumVariants); } - public void defineStructType(StructType structType, List<Field> fields) { + public void defineStructType(StructType structType, Optional<List<Field>> fields) { this.typesInfo.defineStructType(structType, fields); } @@ -69,7 +69,7 @@ public class TypeCheckerNamespaceContext { return this.typesInfo.isDefined(type); } - public List<Field> fieldsOf(StructType type) { + public Optional<List<Field>> fieldsOf(StructType type) { return this.typesInfo.fieldsOf(type); } diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java index 814466c..697be9b 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfo.java @@ -3,12 +3,13 @@ package org.zwobble.hobgoblin.compiler.typechecker; import org.zwobble.hobgoblin.compiler.types.*; import java.util.List; +import java.util.Optional; public interface TypesInfo { TypesInfo EMPTY = TypesInfoInMemory.empty(); boolean isDefined(StructType type); - List<Field> fieldsOf(StructType structType); + Optional<List<Field>> fieldsOf(StructType structType); List<SumType> variantOf(StructType variantType); List<Type> sumVariants(SumType type); diff --git a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java index d9c0c85..821238b 100644 --- a/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java +++ b/src/main/java/org/zwobble/hobgoblin/compiler/typechecker/TypesInfoInMemory.java @@ -6,27 +6,32 @@ import org.zwobble.hobgoblin.compiler.util.ManyToMany; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; public class TypesInfoInMemory implements TypesInfo { public static TypesInfoInMemory empty() { return new TypesInfoInMemory( new HashMap<>(), new HashMap<>(), + new HashMap<>(), new ManyToMany<>() ); } private final Map<EnumType, List<EnumVariant>> enumVariants; - private final Map<Type, List<Field>> fieldsOf; + private final Map<Type, Optional<List<Field>>> structFields; + private final Map<Type, List<Field>> sumFields; private final ManyToMany<SumType, Type> sumVariants; public TypesInfoInMemory( Map<EnumType, List<EnumVariant>> enumVariants, - Map<Type, List<Field>> fieldsOf, + Map<Type, Optional<List<Field>>> structFields, + Map<Type, List<Field>> sumFields, ManyToMany<SumType, Type> sumVariants ) { this.enumVariants = enumVariants; - this.fieldsOf = fieldsOf; + this.structFields = structFields; + this.sumFields = sumFields; this.sumVariants = sumVariants; } @@ -38,19 +43,21 @@ public class TypesInfoInMemory implements TypesInfo { return this.enumVariants.get(enumType); } - public void defineStructType(StructType structType, List<Field> fields) { - this.fieldsOf.put(structType, fields); + public void defineStructType(StructType structType, Optional<List<Field>> fields) { + this.structFields.put(structType, fields); } @Override public boolean isDefined(StructType type) { - return this.fieldsOf.containsKey(type); + return this.structFields.containsKey(type); } - public List<Field> fieldsOf(StructType structType) { - var fields = this.fieldsOf.get(structType); + @Override + public Optional<List<Field>> fieldsOf(StructType structType) { + var fields = this.structFields.get(structType); if (fields == null) { - return List.of(); + // TODO: better error + throw new RuntimeException("struct not defined"); } else { return fields; } @@ -64,7 +71,7 @@ public class TypesInfoInMemory implements TypesInfo { for (var variantType : variantTypes) { this.sumVariants.add(sumType, variantType); } - this.fieldsOf.put(sumType, fields); + this.sumFields.put(sumType, fields); } public List<SumType> variantOf(StructType variantType) { @@ -76,7 +83,7 @@ public class TypesInfoInMemory implements TypesInfo { } public List<Field> fieldsOf(SumType sumType) { - var fields = this.fieldsOf.get(sumType); + var fields = this.sumFields.get(sumType); if (fields == null) { return List.of(); } else { |
