From 37623ba6964acf573e100903fbdd1453d69d2e26 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Thu, 28 Sep 2023 15:13:55 +0100 Subject: Add Patio code gen for struct field accesses --- .../org/shedlang/compiler/patio/PatioCodeGen.java | 9 +++- .../compiler/patio/PatioCodeGenStructs.java | 51 +++++++++++++++++++--- .../shedlang/compiler/typechecker/TypeChecker.java | 7 ++- .../shedlang/compiler/types/StructTypeInfo.java | 17 ++++++-- .../org/shedlang/compiler/util/POrderedMap.java | 13 +++++- 5 files changed, 81 insertions(+), 16 deletions(-) (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 0c6f94f2..9382eab7 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java @@ -281,7 +281,14 @@ public class PatioCodeGen { } case FieldLoadInstruction.Receiver.Struct receiverStruct -> { - throw new UnsupportedOperationException("TODO"); + context = PatioCodeGenStructs.fieldLoad( + target, + receiver, + receiverStruct.type(), + fieldLoad.fieldName(), + fieldLoad.source(), + context + ); } } diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java index d99f3ce6..4d6ece42 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenStructs.java @@ -1,10 +1,7 @@ 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.instructions.*; import org.shedlang.compiler.patio.ast.operands.PatioLocalRef; import org.shedlang.compiler.patio.ast.types.PatioDataLayout; import org.shedlang.compiler.patio.ast.types.PatioDataLayouts; @@ -44,7 +41,7 @@ public class PatioCodeGenStructs { var valuePointer = valuePointerResult.value(); bodyContext = valuePointerResult.context(); - var structDataLayout = structDataLayout(fields); + var structDataLayout = structDataLayout(type, context); bodyContext = bodyContext.addInstruction(new PatioAllocHeap( valuePointer, @@ -87,12 +84,52 @@ public class PatioCodeGenStructs { ); } + public static PatioCodeGenContext fieldLoad( + PatioLocalRef target, + PatioLocalRef receiver, + StructType type, + String fieldName, + Source source, + PatioCodeGenContext context + ) { + var valuePointerResult = context.allocateVal( + PatioCodeGenLocalSpace.STRUCT_VALUE_POINTER, + PatioTypes.DATA_POINTER + ); + var valuePointer = valuePointerResult.value(); + context = valuePointerResult.context(); + + context = context.addInstruction(new PatioIntToDataPtr( + valuePointer, + receiver, + source + )); + + var structDataLayout = structDataLayout(type, context); + + var structTypeInfo = context.structTypeInfo(type); + var fieldIndex = structTypeInfo.fieldIndex(fieldName); + + context = context.addInstruction(new PatioMemoryLoad( + target, + valuePointer, + structDataLayout, + List.of(fieldIndex), + source + )); + + return context; + } + private static PatioDataLayout structDataLayout( - List fields + StructType type, + PatioCodeGenContext context ) { + var structTypeInfo = context.structTypeInfo(type); + return PatioDataLayouts.struct(Lists.repeat( PatioDataLayouts.INT, - fields.size() + structTypeInfo.fields().size() )); } } diff --git a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java index dc25bfc3..81917dfb 100644 --- a/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java +++ b/src/main/java/org/shedlang/compiler/typechecker/TypeChecker.java @@ -1,11 +1,10 @@ package org.shedlang.compiler.typechecker; -import org.pcollections.OrderedPMap; import org.shedlang.compiler.ast.typed.*; import org.shedlang.compiler.ast.untyped.*; import org.shedlang.compiler.sources.Source; -import org.shedlang.compiler.typechecker.errors.*; import org.shedlang.compiler.typechecker.errors.NoSuchFieldError; +import org.shedlang.compiler.typechecker.errors.*; import org.shedlang.compiler.typechecker.typesets.TypeSetTypeLevelValue; import org.shedlang.compiler.typechecker.typesets.TypeSets; import org.shedlang.compiler.types.*; @@ -323,7 +322,7 @@ public class TypeChecker { ) { var structTypeInfo = context.structTypeInfo(structType, typedReceiver.source()); - var namedParams = structTypeInfo.fields().entrySet().stream() + var namedParams = structTypeInfo.fields().entryStream() .map(field -> { var name = field.getKey(); var type = field.getValue(); @@ -859,7 +858,7 @@ public class TypeChecker { @Override public TypeCheckerContext defineTypes(TypeCheckerContext context) { var typedFieldNodes = new ArrayList(); - var fieldTypes = OrderedPMap.empty(); + var fieldTypes = P.orderedMap(); for (var untypedField : untyped.fields()) { var typedFieldNode = new TypedStructFieldDefinitionNode( diff --git a/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java b/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java index f0c3eff7..7a95a234 100644 --- a/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java +++ b/src/main/java/org/shedlang/compiler/types/StructTypeInfo.java @@ -1,11 +1,22 @@ package org.shedlang.compiler.types; -import org.pcollections.OrderedPMap; +import org.shedlang.compiler.util.POrderedMap; import java.util.Optional; -public record StructTypeInfo(OrderedPMap fields) { +public record StructTypeInfo(POrderedMap fields) { public Optional fieldType(String fieldName) { - return Optional.ofNullable(this.fields.get(fieldName)); + return this.fields.get(fieldName); + } + + public int fieldIndex(String fieldName) { + // TODO: extract common field set from namespace type info + var fieldIndex = fields.keys().indexOf(fieldName); + + if (fieldIndex == -1) { + throw new NoSuchFieldInternalError(fieldName); + } else { + return fieldIndex; + } } } diff --git a/src/main/java/org/shedlang/compiler/util/POrderedMap.java b/src/main/java/org/shedlang/compiler/util/POrderedMap.java index 3ab74270..4a8780ad 100644 --- a/src/main/java/org/shedlang/compiler/util/POrderedMap.java +++ b/src/main/java/org/shedlang/compiler/util/POrderedMap.java @@ -4,7 +4,9 @@ import org.pcollections.Empty; import org.pcollections.PMap; import org.pcollections.PVector; -import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; public class POrderedMap { public static POrderedMap empty() { @@ -42,6 +44,10 @@ public class POrderedMap { return keys; } + public Optional get(K key) { + return Optional.ofNullable(map.get(key)); + } + public PVector toValues() { return keys.stream() .map(key -> map.get(key)) @@ -52,6 +58,11 @@ public class POrderedMap { return keys.size(); } + public Stream> entryStream() { + return keys.stream() + .map(key -> Map.entry(key, map.get(key))); + } + @Override public boolean equals(Object other) { if (this == other) { -- cgit v1.2.3