Compare commits
2 Commits
c3c0a3292b
...
8a560f5417
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a560f5417 | |||
| 966b6a31ae |
@ -172,6 +172,7 @@ class Compiler(
|
|||||||
private val callReturnTypeDeclByRef: MutableMap<CallRef, TypeDecl> = mutableMapOf()
|
private val callReturnTypeDeclByRef: MutableMap<CallRef, TypeDecl> = mutableMapOf()
|
||||||
private val callableReturnTypeByScopeId: MutableMap<Int, MutableMap<Int, ObjClass>> = mutableMapOf()
|
private val callableReturnTypeByScopeId: MutableMap<Int, MutableMap<Int, ObjClass>> = mutableMapOf()
|
||||||
private val callableReturnTypeByName: MutableMap<String, ObjClass> = mutableMapOf()
|
private val callableReturnTypeByName: MutableMap<String, ObjClass> = mutableMapOf()
|
||||||
|
private val callableReturnTypeDeclByName: MutableMap<String, TypeDecl> = mutableMapOf()
|
||||||
private val lambdaReturnTypeByRef: MutableMap<ObjRef, ObjClass> = mutableMapOf()
|
private val lambdaReturnTypeByRef: MutableMap<ObjRef, ObjClass> = mutableMapOf()
|
||||||
private val lambdaCaptureEntriesByRef: MutableMap<ValueFnRef, List<net.sergeych.lyng.bytecode.LambdaCaptureEntry>> =
|
private val lambdaCaptureEntriesByRef: MutableMap<ValueFnRef, List<net.sergeych.lyng.bytecode.LambdaCaptureEntry>> =
|
||||||
mutableMapOf()
|
mutableMapOf()
|
||||||
@ -4313,14 +4314,17 @@ class Compiler(
|
|||||||
is MapLiteralRef -> inferMapLiteralTypeDecl(ref)
|
is MapLiteralRef -> inferMapLiteralTypeDecl(ref)
|
||||||
is ConstRef -> inferTypeDeclFromConst(ref.constValue)
|
is ConstRef -> inferTypeDeclFromConst(ref.constValue)
|
||||||
is CallRef -> {
|
is CallRef -> {
|
||||||
inferCallReturnClass(ref)?.let { TypeDecl.Simple(it.className, false) }
|
|
||||||
?: run {
|
|
||||||
val targetName = when (val target = ref.target) {
|
val targetName = when (val target = ref.target) {
|
||||||
is LocalVarRef -> target.name
|
is LocalVarRef -> target.name
|
||||||
is FastLocalVarRef -> target.name
|
is FastLocalVarRef -> target.name
|
||||||
is LocalSlotRef -> target.name
|
is LocalSlotRef -> target.name
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
if (targetName != null) {
|
||||||
|
callableReturnTypeDeclByName[targetName]?.let { return it }
|
||||||
|
}
|
||||||
|
inferCallReturnClass(ref)?.let { TypeDecl.Simple(it.className, false) }
|
||||||
|
?: run {
|
||||||
if (targetName != null && targetName.firstOrNull()?.isUpperCase() == true) {
|
if (targetName != null && targetName.firstOrNull()?.isUpperCase() == true) {
|
||||||
TypeDecl.Simple(targetName, false)
|
TypeDecl.Simple(targetName, false)
|
||||||
} else {
|
} else {
|
||||||
@ -8157,6 +8161,10 @@ class Compiler(
|
|||||||
inferredReturnClass
|
inferredReturnClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val inferredReturnDecl = returnTypeDecl ?: inferredReturnClass?.let { TypeDecl.Simple(it.className, false) }
|
||||||
|
if (declKind != SymbolKind.MEMBER && inferredReturnDecl != null) {
|
||||||
|
callableReturnTypeDeclByName[name] = inferredReturnDecl
|
||||||
|
}
|
||||||
val fnStatements = rawFnStatements?.let { stmt ->
|
val fnStatements = rawFnStatements?.let { stmt ->
|
||||||
if (!compileBytecode) return@let stmt
|
if (!compileBytecode) return@let stmt
|
||||||
val paramKnownClasses = mutableMapOf<String, ObjClass>()
|
val paramKnownClasses = mutableMapOf<String, ObjClass>()
|
||||||
|
|||||||
@ -732,7 +732,8 @@ private class Parser(fromPos: Pos, private val interpolationEnabled: Boolean = t
|
|||||||
}
|
}
|
||||||
val expanded = mutableListOf<Token>()
|
val expanded = mutableListOf<Token>()
|
||||||
expanded += Token("(", tokenPos, Token.Type.LPAREN)
|
expanded += Token("(", tokenPos, Token.Type.LPAREN)
|
||||||
var emittedPieces = 0
|
expanded += Token("", tokenPos, Token.Type.STRING)
|
||||||
|
var emittedPieces = 1
|
||||||
for (chunk in chunks) {
|
for (chunk in chunks) {
|
||||||
val pieceTokens = when (chunk) {
|
val pieceTokens = when (chunk) {
|
||||||
is StringChunk.Literal -> {
|
is StringChunk.Literal -> {
|
||||||
@ -755,9 +756,6 @@ private class Parser(fromPos: Pos, private val interpolationEnabled: Boolean = t
|
|||||||
expanded += pieceTokens
|
expanded += pieceTokens
|
||||||
emittedPieces++
|
emittedPieces++
|
||||||
}
|
}
|
||||||
if (emittedPieces == 0) {
|
|
||||||
expanded += Token("", tokenPos, Token.Type.STRING)
|
|
||||||
}
|
|
||||||
expanded += Token(")", tokenPos, Token.Type.RPAREN)
|
expanded += Token(")", tokenPos, Token.Type.RPAREN)
|
||||||
|
|
||||||
val first = expanded.first()
|
val first = expanded.first()
|
||||||
@ -766,10 +764,21 @@ private class Parser(fromPos: Pos, private val interpolationEnabled: Boolean = t
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseEmbeddedExpressionTokens(text: String, exprPos: Pos): List<Token> {
|
private fun parseEmbeddedExpressionTokens(text: String, exprPos: Pos): List<Token> {
|
||||||
val tokens = parseLyng(Source(exprPos.source.fileName, text), interpolationEnabled)
|
val tokens = try {
|
||||||
|
parseLyng(Source(exprPos.source.fileName, text), interpolationEnabled)
|
||||||
|
} catch (e: ScriptError) {
|
||||||
|
throw ScriptError(remapEmbeddedPos(exprPos, e.pos), e.errorMessage, e)
|
||||||
|
}
|
||||||
if (tokens.isEmpty()) return emptyList()
|
if (tokens.isEmpty()) return emptyList()
|
||||||
val withoutEof = if (tokens.last().type == Token.Type.EOF) tokens.dropLast(1) else tokens
|
val withoutEof = if (tokens.last().type == Token.Type.EOF) tokens.dropLast(1) else tokens
|
||||||
return withoutEof
|
return withoutEof.map { it.copy(pos = remapEmbeddedPos(exprPos, it.pos)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun remapEmbeddedPos(exprPos: Pos, embeddedPos: Pos): Pos {
|
||||||
|
if (embeddedPos.line < 0 || embeddedPos.column < 0) return exprPos
|
||||||
|
val line = exprPos.line + embeddedPos.line
|
||||||
|
val column = if (embeddedPos.line == 0) exprPos.column + embeddedPos.column else embeddedPos.column
|
||||||
|
return Pos(exprPos.source, line, column)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readInterpolationExprText(start: Pos): String {
|
private fun readInterpolationExprText(start: Pos): String {
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import com.ionspin.kotlin.bignum.decimal.BigDecimal
|
|||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class DecimalModuleTest {
|
class DecimalModuleTest {
|
||||||
@Test
|
@Test
|
||||||
@ -266,4 +267,32 @@ class DecimalModuleTest {
|
|||||||
assert(X == 42)
|
assert(X == 42)
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecimalStringInterpolation() = runTest {
|
||||||
|
eval(
|
||||||
|
$$"""
|
||||||
|
import lyng.decimal
|
||||||
|
var X = "2".d
|
||||||
|
var re = 50.d
|
||||||
|
var im = X
|
||||||
|
val s = "$re + ${im}i"
|
||||||
|
assertEquals("50 + 2i", s)
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDecimalInterpolationSyntaxErrorKeepsOriginalSourcePosition() = runTest {
|
||||||
|
val ex = assertFailsWith<ScriptError> {
|
||||||
|
eval(
|
||||||
|
$$"""
|
||||||
|
import lyng.decimal
|
||||||
|
var re = 50.d
|
||||||
|
val s = "${re + }"
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(2, ex.pos.line)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user