Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/dto/Convert.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.jacodb.ets.model.EtsBitOrExpr
import org.jacodb.ets.model.EtsBitXorExpr
import org.jacodb.ets.model.EtsBlockCfg
import org.jacodb.ets.model.EtsBooleanConstant
import org.jacodb.ets.model.EtsBooleanLiteralType
import org.jacodb.ets.model.EtsBooleanType
import org.jacodb.ets.model.EtsCallExpr
import org.jacodb.ets.model.EtsCallStmt
Expand Down Expand Up @@ -75,7 +76,6 @@ import org.jacodb.ets.model.EtsInstanceOfExpr
import org.jacodb.ets.model.EtsIntersectionType
import org.jacodb.ets.model.EtsLeftShiftExpr
import org.jacodb.ets.model.EtsLexicalEnvType
import org.jacodb.ets.model.EtsLiteralType
import org.jacodb.ets.model.EtsLocal
import org.jacodb.ets.model.EtsLocalSignature
import org.jacodb.ets.model.EtsLtEqExpr
Expand All @@ -99,6 +99,7 @@ import org.jacodb.ets.model.EtsNullConstant
import org.jacodb.ets.model.EtsNullType
import org.jacodb.ets.model.EtsNullishCoalescingExpr
import org.jacodb.ets.model.EtsNumberConstant
import org.jacodb.ets.model.EtsNumberLiteralType
import org.jacodb.ets.model.EtsNumberType
import org.jacodb.ets.model.EtsOrExpr
import org.jacodb.ets.model.EtsParameterRef
Expand All @@ -118,6 +119,7 @@ import org.jacodb.ets.model.EtsStmtLocation
import org.jacodb.ets.model.EtsStrictEqExpr
import org.jacodb.ets.model.EtsStrictNotEqExpr
import org.jacodb.ets.model.EtsStringConstant
import org.jacodb.ets.model.EtsStringLiteralType
import org.jacodb.ets.model.EtsStringType
import org.jacodb.ets.model.EtsSubExpr
import org.jacodb.ets.model.EtsThis
Expand Down Expand Up @@ -544,9 +546,11 @@ fun TypeDto.toEtsType(): EtsType = when (this) {
closures = closures.map { it.toEtsLocal() },
)

is LiteralTypeDto -> EtsLiteralType(
literalTypeName = literal.toString(),
)
is LiteralTypeDto -> when (val literalValue = literal) {
is PrimitiveLiteralDto.StringLiteral -> EtsStringLiteralType(literalValue.value)
is PrimitiveLiteralDto.NumberLiteral -> EtsNumberLiteralType(literalValue.value)
is PrimitiveLiteralDto.BooleanLiteral -> EtsBooleanLiteralType(literalValue.value)
}

NeverTypeDto -> EtsNeverType

Expand Down
47 changes: 41 additions & 6 deletions jacodb-ets/src/main/kotlin/org/jacodb/ets/model/Type.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ interface EtsType : TypeName, CommonType {
fun visit(type: EtsUndefinedType): R
fun visit(type: EtsVoidType): R
fun visit(type: EtsNeverType): R
fun visit(type: EtsLiteralType): R

// Literal
fun visit(type: EtsStringLiteralType): R
fun visit(type: EtsNumberLiteralType): R
fun visit(type: EtsBooleanLiteralType): R

// Ref
fun visit(type: EtsClassType): R
Expand Down Expand Up @@ -74,7 +78,10 @@ interface EtsType : TypeName, CommonType {
override fun visit(type: EtsUndefinedType): R = defaultVisit(type)
override fun visit(type: EtsVoidType): R = defaultVisit(type)
override fun visit(type: EtsNeverType): R = defaultVisit(type)
override fun visit(type: EtsLiteralType): R = defaultVisit(type)

override fun visit(type: EtsStringLiteralType): R = defaultVisit(type)
override fun visit(type: EtsNumberLiteralType): R = defaultVisit(type)
override fun visit(type: EtsBooleanLiteralType): R = defaultVisit(type)

override fun visit(type: EtsClassType): R = defaultVisit(type)
override fun visit(type: EtsUnclearRefType): R = defaultVisit(type)
Expand Down Expand Up @@ -277,11 +284,39 @@ object EtsNeverType : EtsPrimitiveType {
}
}

data class EtsLiteralType(
val literalTypeName: String,
) : EtsPrimitiveType {
sealed interface EtsLiteralType : EtsPrimitiveType

data class EtsStringLiteralType(
val value: String,
) : EtsLiteralType {
override val typeName: String
get() = "\"$value\""

override fun toString(): String = typeName

override fun <R> accept(visitor: EtsType.Visitor<R>): R {
return visitor.visit(this)
}
}

data class EtsNumberLiteralType(
val value: Double,
) : EtsLiteralType {
override val typeName: String
get() = value.toString()

override fun toString(): String = typeName

override fun <R> accept(visitor: EtsType.Visitor<R>): R {
return visitor.visit(this)
}
}

data class EtsBooleanLiteralType(
val value: Boolean,
) : EtsLiteralType {
override val typeName: String
get() = literalTypeName
get() = value.toString()

override fun toString(): String = typeName

Expand Down
120 changes: 120 additions & 0 deletions jacodb-ets/src/test/kotlin/org/jacodb/ets/test/EtsFromJsonTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,126 @@ class EtsFromJsonTest {
assertEquals(PrimitiveLiteralDto.StringLiteral("hello"), typeDto.literal)
}

@Test
fun testLoadNumberLiteralTypeFromJson() {
// TS: `let x: 42 = 42;`
val jsonString = """
{
"_": "LiteralType",
"literal": 42
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.NumberLiteral(42.0), typeDto.literal)
}

@Test
fun testLoadFloatLiteralTypeFromJson() {
// TS: `let x: 3.14 = 3.14;`
val jsonString = """
{
"_": "LiteralType",
"literal": 3.14
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.NumberLiteral(3.14), typeDto.literal)
}

@Test
fun testLoadNegativeNumberLiteralTypeFromJson() {
// TS: `let x: -5 = -5;`
val jsonString = """
{
"_": "LiteralType",
"literal": -5
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.NumberLiteral(-5.0), typeDto.literal)
}

@Test
fun testLoadBooleanTrueLiteralTypeFromJson() {
// TS: `let x: true = true;`
val jsonString = """
{
"_": "LiteralType",
"literal": true
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.BooleanLiteral(true), typeDto.literal)
}

@Test
fun testLoadBooleanFalseLiteralTypeFromJson() {
// TS: `let x: false = false;`
val jsonString = """
{
"_": "LiteralType",
"literal": false
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.BooleanLiteral(false), typeDto.literal)
}

@Test
fun testLoadEmptyStringLiteralTypeFromJson() {
// TS: `let x: "" = "";`
val jsonString = """
{
"_": "LiteralType",
"literal": ""
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.StringLiteral(""), typeDto.literal)
}

@Test
fun testLoadStringLiteralWithSpecialCharactersFromJson() {
// TS: `let x: "Hello\nWorld\t!" = "Hello\nWorld\t!";`
val jsonString = """
{
"_": "LiteralType",
"literal": "Hello\nWorld\t!"
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.StringLiteral("Hello\nWorld\t!"), typeDto.literal)
}

@Test
fun testLoadZeroLiteralTypeFromJson() {
// TS: `let x: 0 = 0;`
val jsonString = """
{
"_": "LiteralType",
"literal": 0
}
""".trimIndent()
val typeDto = Json.decodeFromString<TypeDto>(jsonString)
logger.info { "typeDto = $typeDto" }
assertIs<LiteralTypeDto>(typeDto)
assertEquals(PrimitiveLiteralDto.NumberLiteral(0.0), typeDto.literal)
}

@Test
fun testLoadRawTypeFromJson() {
val jsonString = """
Expand Down
Loading