package org.shedlang.compiler.shidtopatio; import org.shedlang.compiler.patio.instructions.*; import org.shedlang.compiler.patio.operands.PatioIntConst; import org.shedlang.compiler.patio.operands.PatioLocalRef; import org.shedlang.compiler.patio.operands.PatioOperand; import org.shedlang.compiler.patio.types.PatioDataLayout; import org.shedlang.compiler.patio.types.PatioDataLayouts; import org.shedlang.compiler.patio.types.PatioTypes; import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.util.Lists; import java.util.List; public class ShidToPatioTuples { private ShidToPatioTuples() { } private record TupleRuntimeType(int elementCount) implements RuntimeType { @Override public PatioDataLayout layout() { return ShidToPatioGc.gcObjectDataLayout(PatioDataLayouts.struct(Lists.repeat( PatioDataLayouts.INT, elementCount ))); } private static final List GC_CHILDREN_OFFSET = ShidToPatioGc.gcObjectOffset(List.of()); @Override public List gcChildrenOffset() { return GC_CHILDREN_OFFSET; } @Override public int gcChildrenCount() { return elementCount; } public List elementOffset(int elementIndex) { return ShidToPatioGc.gcObjectOffset(List.of(elementIndex)); } } public static ShidToPatioResult create( List elements, Source source, ShidToPatioContext context ) { var tupleResult = context.allocateVal( ShidToPatioLocalSpace.TUPLE, ShidToPatioTypes.VALUE_TYPE ); var tuple = tupleResult.value(); context = tupleResult.context(); if (elements.size() == 0) { context = context.addInstruction(new PatioLocalStore( tuple, PatioIntConst.of(0), source )); return context.toResult(tuple); } var tuplePointerResult = context.allocateVal( ShidToPatioLocalSpace.TUPLE_POINTER, PatioTypes.DATA_PTR ); var tuplePointer = tuplePointerResult.value(); context = tuplePointerResult.context(); var tupleRuntimeType = new TupleRuntimeType(elements.size()); context = ShidToPatioGc.alloc( tuplePointer, tupleRuntimeType, source, context ); for (var elementIndex = 0; elementIndex < elements.size(); elementIndex++) { var element = elements.get(elementIndex); context = context.addInstruction(new PatioMemoryStore( tuplePointer, tupleRuntimeType.layout(), tupleRuntimeType.elementOffset(elementIndex), element, source )); } context = context.addInstruction(new PatioDataPtrToInt( tuple, tuplePointer, source )); return context.toResult(tuple); } public static ShidToPatioResult get( PatioOperand tuple, int elementIndex, int elementCount, Source source, ShidToPatioContext context ) { var tuplePointerResult = context.allocateVal( ShidToPatioLocalSpace.TUPLE, PatioTypes.DATA_PTR ); var tuplePointer = tuplePointerResult.value(); context = tuplePointerResult.context(); context = context.addInstruction(new PatioIntToDataPtr( tuplePointer, tuple, source )); var destinationResult = context.allocateVal( ShidToPatioLocalSpace.TUPLE_ELEMENT, Integer.toString(elementIndex), ShidToPatioTypes.VALUE_TYPE ); var destination = destinationResult.value(); context = destinationResult.context(); var tupleRuntimeType = new TupleRuntimeType(elementCount); context = context.addInstruction(new PatioMemoryLoad( destination, tuplePointer, tupleRuntimeType.layout(), tupleRuntimeType.elementOffset(elementIndex), source )); return context.toResult(destination); } }