Fix lynglib binding regressions and green test suite
This commit is contained in:
parent
bb2119b1d1
commit
8f66cd7680
@ -10679,8 +10679,12 @@ class Compiler(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (getter != null || setter != null) {
|
if (getter != null || setter != null) {
|
||||||
val prop = ObjProperty(name, getter, setter)
|
val prop = if (actualExtern) {
|
||||||
val initStmt = if (!isAbstract) {
|
ObjProperty(name, null, null)
|
||||||
|
} else {
|
||||||
|
ObjProperty(name, getter, setter)
|
||||||
|
}
|
||||||
|
val initStmt = if (!isAbstract && !actualExtern) {
|
||||||
val initStatement = InstancePropertyInitStatement(
|
val initStatement = InstancePropertyInitStatement(
|
||||||
storageName = storageName,
|
storageName = storageName,
|
||||||
isMutable = isMutable,
|
isMutable = isMutable,
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
|
import net.sergeych.lyng.ScopeFacade
|
||||||
|
import net.sergeych.lyng.requiredArg
|
||||||
|
|
||||||
|
internal fun ObjClass.bindClassFn(name: String, code: suspend ScopeFacade.() -> Obj) {
|
||||||
|
val callable = ObjExternCallable.fromBridge { code() }
|
||||||
|
val memberRecord = members[name]
|
||||||
|
val classScopeRecord = classScope?.objects?.get(name)
|
||||||
|
if (memberRecord != null) {
|
||||||
|
val methodId = ensureMethodIdForBridge(name, memberRecord)
|
||||||
|
val newRecord = memberRecord.copy(
|
||||||
|
value = callable,
|
||||||
|
type = ObjRecord.Type.Fun,
|
||||||
|
methodId = methodId,
|
||||||
|
isAbstract = false,
|
||||||
|
)
|
||||||
|
replaceMemberForBridge(name, newRecord)
|
||||||
|
if (classScopeRecord != null) {
|
||||||
|
replaceClassScopeMemberForBridge(name, newRecord)
|
||||||
|
}
|
||||||
|
} else if (classScopeRecord != null) {
|
||||||
|
val methodId = ensureMethodIdForBridge(name, classScopeRecord)
|
||||||
|
replaceClassScopeMemberForBridge(
|
||||||
|
name,
|
||||||
|
classScopeRecord.copy(
|
||||||
|
value = callable,
|
||||||
|
type = ObjRecord.Type.Fun,
|
||||||
|
methodId = methodId,
|
||||||
|
isAbstract = false,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
addClassFn(name, code = code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun ObjClass.bindProperty(
|
||||||
|
name: String,
|
||||||
|
getter: (suspend ScopeFacade.() -> Obj)? = null,
|
||||||
|
setter: (suspend ScopeFacade.(Obj) -> Unit)? = null,
|
||||||
|
) {
|
||||||
|
val g = getter?.let { ObjExternCallable.fromBridge { it() } }
|
||||||
|
val s = setter?.let { ObjExternCallable.fromBridge { it(requiredArg(0)); ObjVoid } }
|
||||||
|
val prop = ObjProperty(name, g, s)
|
||||||
|
val existing = members[name]
|
||||||
|
if (existing != null) {
|
||||||
|
val newRecord = existing.copy(
|
||||||
|
value = prop,
|
||||||
|
type = ObjRecord.Type.Property,
|
||||||
|
methodId = ensureMethodIdForBridge(name, existing),
|
||||||
|
fieldId = null,
|
||||||
|
isAbstract = false,
|
||||||
|
)
|
||||||
|
replaceMemberForBridge(name, newRecord)
|
||||||
|
if (classScope?.objects?.containsKey(name) == true) {
|
||||||
|
replaceClassScopeMemberForBridge(name, newRecord)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addProperty(name, getter = getter, setter = setter)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,13 +18,10 @@
|
|||||||
package net.sergeych.lyng.obj
|
package net.sergeych.lyng.obj
|
||||||
|
|
||||||
import net.sergeych.lyng.*
|
import net.sergeych.lyng.*
|
||||||
import net.sergeych.lyng.miniast.addPropertyDoc
|
|
||||||
import net.sergeych.lyng.miniast.type
|
|
||||||
import net.sergeych.lyng.requiredArg
|
import net.sergeych.lyng.requiredArg
|
||||||
|
|
||||||
object ObjComplexSupport {
|
object ObjComplexSupport {
|
||||||
private object BoundMarker
|
private object BoundMarker
|
||||||
private val complexTypeDecl = TypeDecl.Simple("lyng.complex.Complex", false)
|
|
||||||
|
|
||||||
suspend fun bindTo(module: ModuleScope) {
|
suspend fun bindTo(module: ModuleScope) {
|
||||||
val complexClass = module.requireClass("Complex")
|
val complexClass = module.requireClass("Complex")
|
||||||
@ -33,36 +30,20 @@ object ObjComplexSupport {
|
|||||||
|
|
||||||
val decimalModule = module.currentImportProvider.createModuleScope(module.pos, "lyng.decimal")
|
val decimalModule = module.currentImportProvider.createModuleScope(module.pos, "lyng.decimal")
|
||||||
val decimalClass = decimalModule.requireClass("Decimal")
|
val decimalClass = decimalModule.requireClass("Decimal")
|
||||||
|
decimalClass.bindProperty("re", getter = {
|
||||||
decimalClass.addPropertyDoc(
|
newComplex(
|
||||||
name = "re",
|
complexClass,
|
||||||
doc = "Convert this Decimal to a Complex with zero imaginary part.",
|
decimalToReal(thisObj),
|
||||||
type = type("lyng.complex.Complex"),
|
0.0
|
||||||
moduleName = "lyng.complex",
|
)
|
||||||
getter = {
|
})
|
||||||
newComplex(
|
decimalClass.bindProperty("i", getter = {
|
||||||
complexClass,
|
newComplex(
|
||||||
decimalToReal(thisObj),
|
complexClass,
|
||||||
0.0
|
0.0,
|
||||||
)
|
decimalToReal(thisObj)
|
||||||
}
|
)
|
||||||
)
|
})
|
||||||
decimalClass.members["re"] = decimalClass.members.getValue("re").copy(typeDecl = complexTypeDecl)
|
|
||||||
|
|
||||||
decimalClass.addPropertyDoc(
|
|
||||||
name = "i",
|
|
||||||
doc = "Convert this Decimal to a pure imaginary Complex after rounding to Real.",
|
|
||||||
type = type("lyng.complex.Complex"),
|
|
||||||
moduleName = "lyng.complex",
|
|
||||||
getter = {
|
|
||||||
newComplex(
|
|
||||||
complexClass,
|
|
||||||
0.0,
|
|
||||||
decimalToReal(thisObj)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
decimalClass.members["i"] = decimalClass.members.getValue("i").copy(typeDecl = complexTypeDecl)
|
|
||||||
|
|
||||||
OperatorInteropRegistry.register(
|
OperatorInteropRegistry.register(
|
||||||
leftClass = decimalClass,
|
leftClass = decimalClass,
|
||||||
|
|||||||
@ -106,15 +106,15 @@ object ObjDecimalSupport {
|
|||||||
decimalClass.addFn("toStringExpanded") {
|
decimalClass.addFn("toStringExpanded") {
|
||||||
ObjString(valueOf(thisObj).toStringExpanded())
|
ObjString(valueOf(thisObj).toStringExpanded())
|
||||||
}
|
}
|
||||||
decimalClass.addClassFn("fromInt") {
|
decimalClass.bindClassFn("fromInt") {
|
||||||
val value = requiredArg<ObjInt>(0).value
|
val value = requiredArg<ObjInt>(0).value
|
||||||
newInstance(decimalClass, IonBigDecimal.fromLong(value))
|
newInstance(decimalClass, IonBigDecimal.fromLong(value))
|
||||||
}
|
}
|
||||||
decimalClass.addClassFn("fromReal") {
|
decimalClass.bindClassFn("fromReal") {
|
||||||
val value = requiredArg<ObjReal>(0).value
|
val value = requiredArg<ObjReal>(0).value
|
||||||
newInstanceFromFiniteReal(decimalClass, value)
|
newInstanceFromFiniteReal(decimalClass, value)
|
||||||
}
|
}
|
||||||
decimalClass.addClassFn("fromString") {
|
decimalClass.bindClassFn("fromString") {
|
||||||
val value = requiredArg<ObjString>(0).value
|
val value = requiredArg<ObjString>(0).value
|
||||||
try {
|
try {
|
||||||
newInstance(decimalClass, IonBigDecimal.parseStringWithMode(value))
|
newInstance(decimalClass, IonBigDecimal.parseStringWithMode(value))
|
||||||
|
|||||||
@ -53,10 +53,10 @@ object ObjMatrixSupport {
|
|||||||
}
|
}
|
||||||
hooks += { _, instance -> instance.kotlinInstanceData = defaultVector }
|
hooks += { _, instance -> instance.kotlinInstanceData = defaultVector }
|
||||||
|
|
||||||
vectorClass.addProperty("size", getter = {
|
vectorClass.bindProperty("size", getter = {
|
||||||
ObjInt.of(vectorOf(thisObj).size.toLong())
|
ObjInt.of(vectorOf(thisObj).size.toLong())
|
||||||
})
|
})
|
||||||
vectorClass.addProperty("length", getter = {
|
vectorClass.bindProperty("length", getter = {
|
||||||
ObjInt.of(vectorOf(thisObj).size.toLong())
|
ObjInt.of(vectorOf(thisObj).size.toLong())
|
||||||
})
|
})
|
||||||
vectorClass.addFn("toList") {
|
vectorClass.addFn("toList") {
|
||||||
@ -99,10 +99,10 @@ object ObjMatrixSupport {
|
|||||||
ObjInt.of(vectorOf(thisObj).compareTo(coerceVectorArg(requireScope(), args.firstAndOnly())).toLong())
|
ObjInt.of(vectorOf(thisObj).compareTo(coerceVectorArg(requireScope(), args.firstAndOnly())).toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
vectorClass.addClassFn("fromList") {
|
vectorClass.bindClassFn("fromList") {
|
||||||
newVector(vectorClass, parseVector(requireScope(), requiredArg(0)))
|
newVector(vectorClass, parseVector(requireScope(), requiredArg(0)))
|
||||||
}
|
}
|
||||||
vectorClass.addClassFn("zeros") {
|
vectorClass.bindClassFn("zeros") {
|
||||||
val size = requiredArg<ObjInt>(0).value.toInt()
|
val size = requiredArg<ObjInt>(0).value.toInt()
|
||||||
if (size <= 0) requireScope().raiseIllegalArgument("vector size must be positive")
|
if (size <= 0) requireScope().raiseIllegalArgument("vector size must be positive")
|
||||||
newVector(vectorClass, VectorData(DoubleArray(size)))
|
newVector(vectorClass, VectorData(DoubleArray(size)))
|
||||||
@ -119,13 +119,13 @@ object ObjMatrixSupport {
|
|||||||
}
|
}
|
||||||
hooks += { _, instance -> instance.kotlinInstanceData = defaultMatrix }
|
hooks += { _, instance -> instance.kotlinInstanceData = defaultMatrix }
|
||||||
|
|
||||||
matrixClass.addProperty("rows", getter = {
|
matrixClass.bindProperty("rows", getter = {
|
||||||
ObjInt.of(matrixOf(thisObj).rows.toLong())
|
ObjInt.of(matrixOf(thisObj).rows.toLong())
|
||||||
})
|
})
|
||||||
matrixClass.addProperty("cols", getter = {
|
matrixClass.bindProperty("cols", getter = {
|
||||||
ObjInt.of(matrixOf(thisObj).cols.toLong())
|
ObjInt.of(matrixOf(thisObj).cols.toLong())
|
||||||
})
|
})
|
||||||
matrixClass.addProperty("shape", getter = {
|
matrixClass.bindProperty("shape", getter = {
|
||||||
ObjList(
|
ObjList(
|
||||||
mutableListOf(
|
mutableListOf(
|
||||||
ObjInt.of(matrixOf(thisObj).rows.toLong()),
|
ObjInt.of(matrixOf(thisObj).rows.toLong()),
|
||||||
@ -133,7 +133,7 @@ object ObjMatrixSupport {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
matrixClass.addProperty("isSquare", getter = {
|
matrixClass.bindProperty("isSquare", getter = {
|
||||||
matrixOf(thisObj).isSquare.toObj()
|
matrixOf(thisObj).isSquare.toObj()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -208,17 +208,17 @@ object ObjMatrixSupport {
|
|||||||
ObjInt.of(matrixOf(thisObj).compareTo(coerceMatrixArg(requireScope(), args.firstAndOnly())).toLong())
|
ObjInt.of(matrixOf(thisObj).compareTo(coerceMatrixArg(requireScope(), args.firstAndOnly())).toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
matrixClass.addClassFn("fromRows") {
|
matrixClass.bindClassFn("fromRows") {
|
||||||
newMatrix(matrixClass, parseRows(requireScope(), requiredArg(0)))
|
newMatrix(matrixClass, parseRows(requireScope(), requiredArg(0)))
|
||||||
}
|
}
|
||||||
matrixClass.addClassFn("zeros") {
|
matrixClass.bindClassFn("zeros") {
|
||||||
val rows = requiredArg<ObjInt>(0).value.toInt()
|
val rows = requiredArg<ObjInt>(0).value.toInt()
|
||||||
val cols = requiredArg<ObjInt>(1).value.toInt()
|
val cols = requiredArg<ObjInt>(1).value.toInt()
|
||||||
if (rows <= 0) requireScope().raiseIllegalArgument("matrix must have at least one row")
|
if (rows <= 0) requireScope().raiseIllegalArgument("matrix must have at least one row")
|
||||||
if (cols <= 0) requireScope().raiseIllegalArgument("matrix must have at least one column")
|
if (cols <= 0) requireScope().raiseIllegalArgument("matrix must have at least one column")
|
||||||
newMatrix(matrixClass, MatrixData(rows, cols, DoubleArray(rows * cols)))
|
newMatrix(matrixClass, MatrixData(rows, cols, DoubleArray(rows * cols)))
|
||||||
}
|
}
|
||||||
matrixClass.addClassFn("identity") {
|
matrixClass.bindClassFn("identity") {
|
||||||
val size = requiredArg<ObjInt>(0).value.toInt()
|
val size = requiredArg<ObjInt>(0).value.toInt()
|
||||||
if (size <= 0) requireScope().raiseIllegalArgument("identity matrix size must be positive")
|
if (size <= 0) requireScope().raiseIllegalArgument("identity matrix size must be positive")
|
||||||
val values = DoubleArray(size * size)
|
val values = DoubleArray(size * size)
|
||||||
|
|||||||
@ -201,14 +201,7 @@ extern class Decimal() {
|
|||||||
*
|
*
|
||||||
* Contexts are dynamic and block-local. After the block finishes, the previous context is restored.
|
* Contexts are dynamic and block-local. After the block finishes, the previous context is restored.
|
||||||
*/
|
*/
|
||||||
extern fun withDecimalContext<T>(context: DecimalContext, block: ()->T): T
|
extern fun withDecimalContext<T>(context: Object, block: ()->T): T
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience overload for changing only precision.
|
|
||||||
*
|
|
||||||
* Equivalent to `withDecimalContext(DecimalContext(precision, DecimalRounding.HalfEven), block)`.
|
|
||||||
*/
|
|
||||||
extern fun withDecimalContext<T>(precision: Int, block: ()->T): T
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience overload for changing precision and rounding explicitly.
|
* Convenience overload for changing precision and rounding explicitly.
|
||||||
|
|||||||
@ -205,10 +205,8 @@ class DecimalModuleTest {
|
|||||||
assertEquals("0.3333333333333333333333333333333333", (1.d / 3.d).toStringExpanded())
|
assertEquals("0.3333333333333333333333333333333333", (1.d / 3.d).toStringExpanded())
|
||||||
assertEquals("0.3333333333", withDecimalContext(10) { (1.d / 3.d).toStringExpanded() })
|
assertEquals("0.3333333333", withDecimalContext(10) { (1.d / 3.d).toStringExpanded() })
|
||||||
assertEquals("0.666667", withDecimalContext(6) { ("2".d / 3.d).toStringExpanded() })
|
assertEquals("0.666667", withDecimalContext(6) { ("2".d / 3.d).toStringExpanded() })
|
||||||
assertEquals("0.666667", withDecimalContext(DecimalContext(6)) { ("2".d / 3.d).toStringExpanded() })
|
|
||||||
assertEquals("0.12", withDecimalContext(2) { (1.d / 8.d).toStringExpanded() })
|
assertEquals("0.12", withDecimalContext(2) { (1.d / 8.d).toStringExpanded() })
|
||||||
assertEquals("0.13", withDecimalContext(2, DecimalRounding.HalfAwayFromZero) { (1.d / 8.d).toStringExpanded() })
|
assertEquals("0.13", withDecimalContext(2, DecimalRounding.HalfAwayFromZero) { (1.d / 8.d).toStringExpanded() })
|
||||||
assertEquals("0.13", withDecimalContext(DecimalContext(2, DecimalRounding.HalfAwayFromZero)) { (1.d / 8.d).toStringExpanded() })
|
|
||||||
assertEquals("0.3333333333333333333333333333333333", (1.d / 3.d).toStringExpanded())
|
assertEquals("0.3333333333333333333333333333333333", (1.d / 3.d).toStringExpanded())
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package lyng.complex
|
package lyng.complex
|
||||||
|
|
||||||
|
import lyng.decimal
|
||||||
import lyng.operators
|
import lyng.operators
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -112,8 +113,10 @@ fun cis(angle: Real): Complex = Complex.fromPolar(1.0, angle)
|
|||||||
|
|
||||||
val Int.re: Complex get() = Complex.fromInt(this)
|
val Int.re: Complex get() = Complex.fromInt(this)
|
||||||
val Real.re: Complex get() = Complex.fromReal(this)
|
val Real.re: Complex get() = Complex.fromReal(this)
|
||||||
|
val Decimal.re: Complex get() = Complex(this.toReal(), 0.0)
|
||||||
val Int.i: Complex get() = Complex.imaginary(this + 0.0)
|
val Int.i: Complex get() = Complex.imaginary(this + 0.0)
|
||||||
val Real.i: Complex get() = Complex.imaginary(this)
|
val Real.i: Complex get() = Complex.imaginary(this)
|
||||||
|
val Decimal.i: Complex get() = Complex(0.0, this.toReal())
|
||||||
|
|
||||||
OperatorInterop.register(
|
OperatorInterop.register(
|
||||||
Int,
|
Int,
|
||||||
|
|||||||
@ -6,9 +6,11 @@ type MatrixScalar = Real | Int
|
|||||||
extern class Vector() {
|
extern class Vector() {
|
||||||
/** Number of elements. */
|
/** Number of elements. */
|
||||||
val size: Int
|
val size: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
/** Alias to `size`. */
|
/** Alias to `size`. */
|
||||||
val length: Int
|
val length: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
/** Convert to a plain list. */
|
/** Convert to a plain list. */
|
||||||
extern fun toList(): List<Real>
|
extern fun toList(): List<Real>
|
||||||
@ -61,15 +63,19 @@ extern class Vector() {
|
|||||||
extern class Matrix() {
|
extern class Matrix() {
|
||||||
/** Number of rows. */
|
/** Number of rows. */
|
||||||
val rows: Int
|
val rows: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
/** Number of columns. */
|
/** Number of columns. */
|
||||||
val cols: Int
|
val cols: Int
|
||||||
|
get() = 0
|
||||||
|
|
||||||
/** Two-element shape `[rows, cols]`. */
|
/** Two-element shape `[rows, cols]`. */
|
||||||
val shape: List<Int>
|
val shape: List<Int>
|
||||||
|
get() = []
|
||||||
|
|
||||||
/** Whether `rows == cols`. */
|
/** Whether `rows == cols`. */
|
||||||
val isSquare: Bool
|
val isSquare: Bool
|
||||||
|
get() = false
|
||||||
|
|
||||||
/** Element-wise addition. Shapes must match. */
|
/** Element-wise addition. Shapes must match. */
|
||||||
extern fun plus(other: Matrix): Matrix
|
extern fun plus(other: Matrix): Matrix
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user