From a637fcc83f642d5320608ea7fc20a93f3ec5ab86 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 28 Sep 2023 14:58:12 +0100 Subject: Generate Patio code for defining structs --- .../org/shedlang/compiler/patio/PatioCodeGen.java | 20 ++++- .../compiler/patio/PatioCodeGenContext.java | 10 +++ .../compiler/patio/PatioCodeGenLocalSpace.java | 3 + .../compiler/patio/PatioCodeGenStructs.java | 98 ++++++++++++++++++++++ .../instructions/DefineStructInstruction.java | 1 + .../compiler/typechecker/TypeCheckerContext.java | 2 +- .../shedlang/compiler/typechecker/TypeInfos.java | 19 ++++- 7 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java index e4a72194..0c6f94f2 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java @@ -223,7 +223,25 @@ public class PatioCodeGen { } case DefineStructInstruction defineStruct -> { - throw new UnsupportedOperationException("TODO"); + var targetResult = context.allocateVal( + PatioCodeGenLocalSpace.STRUCT_TYPE, + defineStruct.type().name(), + PatioCodeGenTypes.VALUE_TYPE + ); + var target = targetResult.value(); + context = targetResult.context(); + + context = PatioCodeGenStructs.createType( + target, + defineStruct.type(), + defineStruct.fields(), + defineStruct.source(), + context + ); + + context = context.temporaryPush(target); + + yield context; } case DiscardInstruction discard -> diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java index fb176c1e..a0822d7e 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java @@ -15,6 +15,8 @@ import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.typechecker.TypeInfos; import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.NamespaceTypeInfo; +import org.shedlang.compiler.types.StructType; +import org.shedlang.compiler.types.StructTypeInfo; import org.shedlang.compiler.util.P; import java.util.ArrayList; @@ -36,6 +38,10 @@ public record PatioCodeGenContext( return typeInfos.namespaceTypeInfo(namespaceName); } + public StructTypeInfo structTypeInfo(StructType type) { + return typeInfos.structTypeInfo(type); + } + public static final CompilationUnitContext EMPTY = forTypeInfos(TypeInfos.EMPTY); public static CompilationUnitContext forTypeInfos(TypeInfos typeInfos) { @@ -240,6 +246,10 @@ public record PatioCodeGenContext( return this.compilationUnitContext.namespaceTypeInfo(namespaceName); } + public StructTypeInfo structTypeInfo(StructType type) { + return this.compilationUnitContext.structTypeInfo(type); + } + public PatioCodeGenResult allocateCompilationUnitElementName( PatioCodeGenCompilationUnitElementSpace space, String name diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java index 63cb25e2..6a5f40e1 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenLocalSpace.java @@ -14,6 +14,9 @@ public enum PatioCodeGenLocalSpace { LOCAL("local"), RECEIVER("receiver"), STRING("string"), + STRUCT_TYPE("structType"), + STRUCT_VALUE("structValue"), + STRUCT_VALUE_POINTER("structValuePointer"), TEMPORARY("tmp"), TUPLE("tuple"), TUPLE_ELEMENT("tupleElement"), diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java new file mode 100644 index 00000000..d99f3ce6 --- /dev/null +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java @@ -0,0 +1,98 @@ +package org.shedlang.compiler.patio; + +import org.shedlang.compiler.ast.typed.FreeVariables; +import org.shedlang.compiler.patio.ast.instructions.PatioAllocHeap; +import org.shedlang.compiler.patio.ast.instructions.PatioDataPtrToInt; +import org.shedlang.compiler.patio.ast.instructions.PatioMemoryStore; +import org.shedlang.compiler.patio.ast.instructions.PatioReturn; +import org.shedlang.compiler.patio.ast.operands.PatioLocalRef; +import org.shedlang.compiler.patio.ast.types.PatioDataLayout; +import org.shedlang.compiler.patio.ast.types.PatioDataLayouts; +import org.shedlang.compiler.patio.ast.types.PatioTypes; +import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.stackir.instructions.DefineFunctionInstruction; +import org.shedlang.compiler.stackir.instructions.DefineStructInstruction; +import org.shedlang.compiler.types.StructType; +import org.shedlang.compiler.util.Lists; + +import java.util.List; + +public class PatioCodeGenStructs { + private PatioCodeGenStructs() { + } + + public static PatioCodeGenContext createType( + PatioLocalRef target, + StructType type, + List fields, + Source source, + PatioCodeGenContext context + ) { + return PatioCodeGenClosures.create( + target, + type.name(), + List.of(), + fields.stream() + .map(field -> new DefineFunctionInstruction.Param(field.name(), field.source())) + .toList(), + FreeVariables.empty(), + bodyContext -> { + var valuePointerResult = bodyContext.allocateVal( + PatioCodeGenLocalSpace.STRUCT_VALUE_POINTER, + PatioTypes.DATA_POINTER + ); + var valuePointer = valuePointerResult.value(); + bodyContext = valuePointerResult.context(); + + var structDataLayout = structDataLayout(fields); + + bodyContext = bodyContext.addInstruction(new PatioAllocHeap( + valuePointer, + structDataLayout, + source + )); + + for (var fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { + var field = fields.get(fieldIndex); + + bodyContext = bodyContext + .addInstruction(new PatioMemoryStore( + valuePointer, + structDataLayout, + List.of(fieldIndex), + bodyContext.stackIrLocalNameToLocal(field.name()), + source + )); + } + + var valueResult = bodyContext.allocateVal( + PatioCodeGenLocalSpace.STRUCT_VALUE, + PatioCodeGenTypes.VALUE_TYPE + ); + var value = valueResult.value(); + bodyContext = valueResult.context(); + + bodyContext = bodyContext.addInstruction(new PatioDataPtrToInt( + value, + valuePointer, + source + )); + + bodyContext = bodyContext.addInstruction(new PatioReturn(value, source)); + + return bodyContext; + }, + source, + context + ); + } + + private static PatioDataLayout structDataLayout( + List fields + ) { + return PatioDataLayouts.struct(Lists.repeat( + PatioDataLayouts.INT, + fields.size() + )); + } +} diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/DefineStructInstruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/DefineStructInstruction.java index bafa51bf..1d91a1a5 100644 --- a/src/main/java/org/shedlang/compiler/stackir/instructions/DefineStructInstruction.java +++ b/src/main/java/org/shedlang/compiler/stackir/instructions/DefineStructInstruction.java @@ -10,6 +10,7 @@ import java.util.List; */ public record DefineStructInstruction( StructType type, + // TODO: remove fields? We should have fields from the type info. List fields, Source source ) implements Instruction { diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java index c62b4e48..2223309d 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeCheckerContext.java @@ -392,6 +392,6 @@ public class TypeCheckerContext { } public TypeInfos toTypeInfos() { - return new TypeInfos(namespaceTypeInfos); + return new TypeInfos(namespaceTypeInfos, structTypeInfos); } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java b/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java index 7331ee07..7cd03cb4 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeInfos.java @@ -4,16 +4,21 @@ import org.pcollections.Empty; import org.pcollections.PMap; import org.shedlang.compiler.types.NamespaceName; import org.shedlang.compiler.types.NamespaceTypeInfo; +import org.shedlang.compiler.types.StructType; +import org.shedlang.compiler.types.StructTypeInfo; public class TypeInfos { - public static final TypeInfos EMPTY = new TypeInfos(Empty.map()); + public static final TypeInfos EMPTY = new TypeInfos(Empty.map(), Empty.map()); private final PMap namespaceTypeInfos; + private final PMap structTypeInfos; public TypeInfos( - PMap namespaceTypeInfos + PMap namespaceTypeInfos, + PMap structTypeInfos ) { this.namespaceTypeInfos = namespaceTypeInfos; + this.structTypeInfos = structTypeInfos; } public NamespaceTypeInfo namespaceTypeInfo(NamespaceName namespaceName) { @@ -25,4 +30,14 @@ public class TypeInfos { return typeInfo; } } + + public StructTypeInfo structTypeInfo(StructType type) { + // TODO: throw better error + var typeInfo = structTypeInfos.get(type); + if (typeInfo == null) { + throw new RuntimeException("No type info for: " + type); + } else { + return typeInfo; + } + } } -- cgit v1.2.3