diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-09-28 14:58:12 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-09-28 14:58:12 +0100 |
| commit | a637fcc83f642d5320608ea7fc20a93f3ec5ab86 (patch) | |
| tree | 7d32340746ba7e053250c5ae8fd24f4f6c990f9e /src/main/java | |
| parent | 81a8685983e718f087319de8f1b27c059bbcf283 (diff) | |
Generate Patio code for defining structs
Diffstat (limited to 'src/main/java')
7 files changed, 149 insertions, 4 deletions
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<String> 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<DefineStructInstruction.Field> 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<DefineStructInstruction.Field> 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<Field> 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<NamespaceName, NamespaceTypeInfo> namespaceTypeInfos; + private final PMap<StructType, StructTypeInfo> structTypeInfos; public TypeInfos( - PMap<NamespaceName, NamespaceTypeInfo> namespaceTypeInfos + PMap<NamespaceName, NamespaceTypeInfo> namespaceTypeInfos, + PMap<StructType, StructTypeInfo> 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; + } + } } |
