diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/StagedCompiler.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/StagedCompiler.scala index 69723208d..abc0f97a4 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/StagedCompiler.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/StagedCompiler.scala @@ -205,7 +205,8 @@ trait StagedCompiler { byteArray(i) = v.readBufferByte(i) } val location = LocationDescription.toLocation(LocationDescription.deserialize(byteArray)) - Rql2LocationValue(location) + val publicDescription = v.asString() + Rql2LocationValue(location, publicDescription) } } diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/api/PackageExtension.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/api/PackageExtension.scala index b6b1297d4..610cda5e2 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/api/PackageExtension.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/api/PackageExtension.scala @@ -181,21 +181,19 @@ trait EntryExtensionHelper extends Rql2TypeUtils { final protected def getBoolValue(v: Arg): Boolean = { v.asInstanceOf[ValueArg].v.asInstanceOf[Rql2BoolValue].v } - private def getLocation(v: Arg): Location = { - v.asInstanceOf[ValueArg].v.asInstanceOf[Rql2LocationValue].l - } - final protected def getByteStreamLocation(v: Arg): Either[String, ByteStreamLocation] = { - getLocation(v) match { + val locationValue = v.asInstanceOf[ValueArg].v.asInstanceOf[Rql2LocationValue] + locationValue.l match { case l: ByteStreamLocation => Right(l) case _ => Left("expected a bytestream") } } final protected def locationValueToExp(v: Arg): Exp = { - val location = getLocation(v) + val locationValue = v.asInstanceOf[ValueArg].v.asInstanceOf[Rql2LocationValue] + val location = locationValue.l val locationDescription = LocationDescription.toLocationDescription(location) - LocationConst(LocationDescription.serialize(locationDescription)) + LocationConst(LocationDescription.serialize(locationDescription), locationValue.publicDescription) } final protected def getListStringValue(v: Arg): Seq[String] = { diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/api/Values.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/api/Values.scala index 8f2ff9088..cce0c35f1 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/api/Values.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/api/Values.scala @@ -38,7 +38,7 @@ final case class Rql2IntervalValue( seconds: Int, millis: Int ) extends Rql2Value -final case class Rql2LocationValue(l: Location) extends Rql2Value +final case class Rql2LocationValue(l: Location, publicDescription: String) extends Rql2Value final case class Rql2RecordValue(v: Seq[Rql2RecordAttr]) extends Rql2Value final case class Rql2RecordAttr(name: String, value: Rql2Value) final case class Rql2TryValue(v: Either[String, Rql2Value]) extends Rql2Value diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/CsvPackage.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/CsvPackage.scala index 38d268480..1891e0f96 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/CsvPackage.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/CsvPackage.scala @@ -589,7 +589,7 @@ class CsvInferAndParseEntry extends SugarEntryExtension with CsvEntryExtensionHe val codeData = getStringValue(mandatoryArgs.head) for ( inferrerProperties <- getCsvInferrerProperties( - Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData)), Rql2LocationType())), + Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData), ""), Rql2LocationType())), optionalArgs ); inputFormatDescriptor <- programContext.infer(inferrerProperties); @@ -636,7 +636,7 @@ class CsvInferAndParseEntry extends SugarEntryExtension with CsvEntryExtensionHe val r = for ( inferrerProperties <- getCsvInferrerProperties( - Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData)), Rql2LocationType())), + Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData), ""), Rql2LocationType())), optionalArgs ); inputFormatDescriptor <- programContext.infer(inferrerProperties) diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/JsonPackage.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/JsonPackage.scala index f4107577d..3be61a6b9 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/JsonPackage.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/builtin/JsonPackage.scala @@ -365,7 +365,7 @@ class InferAndParseJsonEntry extends SugarEntryExtension with JsonEntryExtension val codeData = getStringValue(mandatoryArgs.head) val preferNulls = optionalArgs.collectFirst { case a if a._1 == "preferNulls" => a._2 }.forall(getBoolValue) val inferenceDiagnostic: Either[Seq[ErrorCompilerMessage], InputFormatDescriptor] = getJsonInferrerProperties( - Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData)), Rql2LocationType())), + Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData), ""), Rql2LocationType())), optionalArgs ) .flatMap(programContext.infer) @@ -397,7 +397,7 @@ class InferAndParseJsonEntry extends SugarEntryExtension with JsonEntryExtension val inputFormatDescriptor = for ( inferrerProperties <- getJsonInferrerProperties( - Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData)), Rql2LocationType())), + Seq(ValueArg(Rql2LocationValue(new InMemoryByteStreamLocation(codeData), ""), Rql2LocationType())), optionalArgs ); inputFormatDescriptor <- programContext.infer(inferrerProperties) diff --git a/snapi-frontend/src/main/scala/raw/compiler/rql2/source/SourceTree.scala b/snapi-frontend/src/main/scala/raw/compiler/rql2/source/SourceTree.scala index 2f78aac47..5fb832feb 100644 --- a/snapi-frontend/src/main/scala/raw/compiler/rql2/source/SourceTree.scala +++ b/snapi-frontend/src/main/scala/raw/compiler/rql2/source/SourceTree.scala @@ -287,7 +287,7 @@ final case class BinaryConst(bytes: Array[Byte]) extends Const { } } -final case class LocationConst(bytes: Array[Byte]) extends Const +final case class LocationConst(bytes: Array[Byte], publicDescription: String) extends Const /** * Number Constants diff --git a/snapi-truffle/src/main/java/raw/compiler/snapi/truffle/compiler/SnapiTruffleEmitter.java b/snapi-truffle/src/main/java/raw/compiler/snapi/truffle/compiler/SnapiTruffleEmitter.java index 2905a5436..f0778b82d 100644 --- a/snapi-truffle/src/main/java/raw/compiler/snapi/truffle/compiler/SnapiTruffleEmitter.java +++ b/snapi-truffle/src/main/java/raw/compiler/snapi/truffle/compiler/SnapiTruffleEmitter.java @@ -561,7 +561,7 @@ case Exp ignored when tipe(in) instanceof PackageType || tipe(in) instanceof Pac default -> throw new RawTruffleInternalErrorException(); }; case BinaryConst bc -> new BinaryConstNode(bc.bytes()); - case LocationConst lc -> new LocationConstNode(lc.bytes()); + case LocationConst lc -> new LocationConstNode(lc.bytes(), lc.publicDescription()); case UnaryExp ue -> switch (ue.unaryOp()) { case Neg ignored -> NegNodeGen.create(recurseExp(ue.exp())); case Not ignored -> NotNodeGen.create(recurseExp(ue.exp())); diff --git a/snapi-truffle/src/main/java/raw/runtime/truffle/ast/expressions/literals/LocationConstNode.java b/snapi-truffle/src/main/java/raw/runtime/truffle/ast/expressions/literals/LocationConstNode.java index 18d7837d2..f7eb0e8f0 100644 --- a/snapi-truffle/src/main/java/raw/runtime/truffle/ast/expressions/literals/LocationConstNode.java +++ b/snapi-truffle/src/main/java/raw/runtime/truffle/ast/expressions/literals/LocationConstNode.java @@ -12,6 +12,7 @@ package raw.runtime.truffle.ast.expressions.literals; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; import raw.compiler.rql2.api.LocationDescription$; import raw.runtime.truffle.ExpressionNode; @@ -23,17 +24,23 @@ public class LocationConstNode extends ExpressionNode { private final byte[] value; + private final String publicDescription; - public LocationConstNode(byte[] value) { + public LocationConstNode(byte[] value, String publicDescription) { this.value = value; + this.publicDescription = publicDescription; } @Override public final Object executeGeneric(VirtualFrame virtualFrame) { RawSettings rawSettings = RawContext.get(this).getSettings(); - Location location = - LocationDescription$.MODULE$.toLocation( - LocationDescription$.MODULE$.deserialize(value), rawSettings); - return new LocationObject(location, ""); + Location location = getLocation(rawSettings); + return new LocationObject(location, publicDescription); + } + + @CompilerDirectives.TruffleBoundary + public Location getLocation(RawSettings rawSettings) { + return LocationDescription$.MODULE$.toLocation( + LocationDescription$.MODULE$.deserialize(value), rawSettings); } } diff --git a/snapi-truffle/src/main/java/raw/runtime/truffle/runtime/primitives/LocationObject.java b/snapi-truffle/src/main/java/raw/runtime/truffle/runtime/primitives/LocationObject.java index 8ffd0dfb1..0aa12a31f 100644 --- a/snapi-truffle/src/main/java/raw/runtime/truffle/runtime/primitives/LocationObject.java +++ b/snapi-truffle/src/main/java/raw/runtime/truffle/runtime/primitives/LocationObject.java @@ -29,6 +29,12 @@ import raw.sources.filesystem.api.FileSystemLocation; import raw.sources.jdbc.api.JdbcServerLocation; +/** + * Truffle object representing a location. + * + *

The location is represented in Interop as a serialized byte array. The public description is + * represented in Interop as a string. + */ @ExportLibrary(InteropLibrary.class) public final class LocationObject implements TruffleObject { private final Location location; @@ -89,6 +95,16 @@ public byte[] getBytes() { return byteArray; } + @ExportMessage + final boolean isString() { + return true; + } + + @ExportMessage + final String asString() { + return publicDescription; + } + @ExportMessage boolean hasArrayElements() { return true;