From 48f686951979f8fa8bd3b424a5139dd9150efec6 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 28 Sep 2023 10:48:27 +0100 Subject: Add struct type to context --- .../compiler/typechecker/TypeCheckSteps.java | 8 ++++++-- .../shedlang/compiler/typechecker/TypeChecker.java | 22 +++++++++++++++------ .../compiler/typechecker/TypeCheckerContext.java | 23 +++++++++++++++++----- .../java/org/shedlang/compiler/types/Types.java | 4 ++++ 4 files changed, 44 insertions(+), 13 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckSteps.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckSteps.java index 4e1e46ec..be94fb24 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckSteps.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckSteps.java @@ -1,13 +1,17 @@ package org.shedlang.compiler.typechecker; public interface TypeCheckSteps { + default TypeCheckerContext declareTypes(TypeCheckerContext context) { + return context; + } + default TypeCheckerContext declareFunctions(TypeCheckerContext context) { return context; } - TypeCheckerResult define(TypeCheckerContext context); + TypeCheckerResult finish(TypeCheckerContext context); default TypeCheckerResult typeCheckAllPhases(TypeCheckerContext context) { - return define(declareFunctions(context)); + return finish(declareFunctions(declareTypes(context))); } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index 1681ac25..1c8bbd54 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -130,7 +130,7 @@ public class TypeChecker { ) { return new TypeCheckSteps<>() { @Override - public TypeCheckerResult define(TypeCheckerContext context) { + public TypeCheckerResult finish(TypeCheckerContext context) { return typeCheckAssign(untyped, context); } }; @@ -402,7 +402,7 @@ public class TypeChecker { } @Override - public TypeCheckerResult define(TypeCheckerContext context) { + public TypeCheckerResult finish(TypeCheckerContext context) { return defineFunctionDefinition(untyped, context); } }; @@ -626,7 +626,7 @@ public class TypeChecker { namespaceEnvironment = namespaceEnvironment.addUndefined(declaredVariables); } - context = context.enterNamespace(namespaceEnvironment.build()); + context = context.enterNamespace(untyped.namespaceName(), namespaceEnvironment.build()); var typedBody = new ArrayList(); @@ -634,6 +634,10 @@ public class TypeChecker { .map(untypedStatement -> typeCheckNamespaceStatement(untypedStatement)) .toList(); + for (var typeCheckSteps : typeCheckStepSets) { + context = typeCheckSteps.declareTypes(context); + } + for (var typeCheckSteps : typeCheckStepSets) { context = typeCheckSteps.declareFunctions(context); } @@ -651,7 +655,7 @@ public class TypeChecker { context = context.enterFreeVariableCapture(); - var typedStatementResult = typeCheckSteps.define(context); + var typedStatementResult = typeCheckSteps.finish(context); var typedStatement = typedStatementResult.value(); context = typedStatementResult.context(); @@ -682,7 +686,6 @@ public class TypeChecker { } case UntypedStructDefinitionNode untypedStruct -> { - throw new UnsupportedOperationException("TODO"); } } } @@ -786,7 +789,14 @@ public class TypeChecker { ) { return new TypeCheckSteps() { @Override - public TypeCheckerResult define(TypeCheckerContext context) { + public TypeCheckerContext declareTypes(TypeCheckerContext context) { + // TODO: better error + var type = new StructType(context.namespaceName().orElseThrow(), untyped.name()); + return context.define(untyped.name(), Types.metaType(type), untyped.source()); + } + + @Override + public TypeCheckerResult finish(TypeCheckerContext context) { var fieldsResult = context.mapWithContext(untyped.fields(), (untypedField, fieldContext) -> { return fieldContext.toResult(new TypedStructFieldDefinitionNode( untypedField.name(), diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java index 1f50d24b..044f5041 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java @@ -21,6 +21,7 @@ public class TypeCheckerContext { public static final TypeCheckerContext EMPTY = new TypeCheckerContext( Empty.map(), P.stack(new LexicalContext( + Optional.empty(), Empty.map(), Effects.NONE, Optional.empty(), @@ -56,6 +57,7 @@ public class TypeCheckerContext { } private static final class LexicalContext implements StackElement { + private final Optional namespaceName; private final PMap environment; private final Effect effect; private final Optional returnType; @@ -64,6 +66,7 @@ public class TypeCheckerContext { private final PMap state; public LexicalContext( + Optional namespaceName, PMap environment, Effect effect, Optional returnType, @@ -71,6 +74,7 @@ public class TypeCheckerContext { FreeVariables.Builder freeVariables, PMap state ) { + this.namespaceName = namespaceName; this.environment = environment; this.effect = effect; this.returnType = returnType; @@ -87,6 +91,7 @@ public class TypeCheckerContext { @Override public LexicalContext withFreeVariable(String name, Source referenceSource) { return new LexicalContext( + this.namespaceName, this.environment, this.effect, this.returnType, @@ -142,11 +147,11 @@ public class TypeCheckerContext { .map(x -> Map.entry(x.getKey(), Variable.defined(x.getValue(), VariableType.VAL))) .collect(PCollectors.toMap()); - return enterNamespace(environment); + return enter(Optional.empty(), environment, Effects.NONE, Optional.empty()); } - public TypeCheckerContext enterNamespace(PMap environment) { - return enter(environment, Effects.NONE, Optional.empty()); + public TypeCheckerContext enterNamespace(NamespaceName namespaceName, PMap environment) { + return enter(Optional.of(namespaceName), environment, Effects.NONE, Optional.empty()); } public TypeCheckerContext enterFunction( @@ -154,14 +159,15 @@ public class TypeCheckerContext { Effect effect, Type returnType ) { - return enter(environment, effect, Optional.of(returnType)); + return enter(this.namespaceName(), environment, effect, Optional.of(returnType)); } public TypeCheckerContext enterBlock(PMap environment) { - return enter(environment, this.effect(), this.returnType()); + return enter(this.namespaceName(), environment, this.effect(), this.returnType()); } private TypeCheckerContext enter( + Optional newNamespaceName, PMap newEnvironment, Effect newEffect, Optional newReturnType @@ -169,6 +175,7 @@ public class TypeCheckerContext { return new TypeCheckerContext( this.namespaceTypeInfo, this.stack.plus(new LexicalContext( + newNamespaceName, this.environment().plusAll(newEnvironment), newEffect, newReturnType, @@ -235,6 +242,7 @@ public class TypeCheckerContext { public TypeCheckerContext addLexicalState(String name, Object state) { return this.updateLexicalContext( lexicalContext -> new LexicalContext( + lexicalContext.namespaceName, lexicalContext.environment, lexicalContext.effect, lexicalContext.returnType, @@ -275,6 +283,7 @@ public class TypeCheckerContext { return this.updateLexicalContext( lexicalContext -> new LexicalContext( + lexicalContext.namespaceName, lexicalContext.environment.plus(name, new Variable( Optional.of(type), variable.variableType() @@ -288,6 +297,10 @@ public class TypeCheckerContext { ); } + public Optional namespaceName() { + return currentLexicalContext().namespaceName; + } + private PMap environment() { return currentLexicalContext().environment; } diff --git a/src/main/java/org/shedlang/compiler/types/Types.java b/src/main/java/org/shedlang/compiler/types/Types.java index 2f07133a..f56f0ca7 100644 --- a/src/main/java/org/shedlang/compiler/types/Types.java +++ b/src/main/java/org/shedlang/compiler/types/Types.java @@ -14,6 +14,10 @@ public class Types { public static final Type TOP = TopType.INSTANCE; public static final Type UNIT = UnitType.INSTANCE; + public static Type struct(NamespaceName namespaceName, String name) { + return new StructType(namespaceName, name); + } + public static TupleType tuple(List elements) { return new TupleType(elements); } -- cgit v1.2.3