class constants added and class instances for integral types

This commit is contained in:
Sergey Chernov 2025-05-28 14:36:04 +04:00
parent f885300d18
commit 47c061d2b4
7 changed files with 98 additions and 16 deletions

View File

@ -40,14 +40,28 @@ Class is the object, naturally, with class:
Classes can be compared: Classes can be compared:
println(1.21::class == Math.PI::class) assert(1.21::class == Math.PI::class)
println(3.14::class == 1::class) assert(3.14::class != 1::class)
println(π::class) assert(π::class == Real)
>>> true π::class
>>> false
>>> Real >>> Real
Note `Real` class: it is global variable for Real class; there are such class instances for all built-in types:
assert("Hello"::class == String)
assert(1970::class == Int)
assert(true::class == Bool)
>>> void >>> void
More complex is singleton classes, because you don't need to compare their class
instances and generally don't need them at all, these are normally just Obj:
null::class
>>> Obj
At this time, `Obj` can't be accessed as a class.
### Methods in-depth ### Methods in-depth
Regular methods are called on instances as usual `instance.method()`. The method resolution order is Regular methods are called on instances as usual `instance.method()`. The method resolution order is

25
docs/Real.md Normal file
View File

@ -0,0 +1,25 @@
# Real built-in class
Class that supports double-precision math. Woks much like double in other languages. We honor no floats, so it is '
Real'.
It's class in Ling is `Real`:
(π/2)::class
>>> Real
you can use it's class to ensure type:
1.71::class == Real
>>> true
## Member functions
| name | meaning | type |
|--------------|------------------------------------|------|
| `roundToInt` | round to nearest int like round(x) | Int |
| | | |
| | | |
| | | |
| | | |
| | | |

View File

@ -13,6 +13,12 @@ data class Arguments(val list: List<Info>): Iterable<Obj> {
return list.first().value return list.first().value
} }
inline fun <reified T: Obj>required(index: Int, context: Context): T {
if( list.size <= index ) context.raiseError("Expected at least ${index+1} argument, got ${list.size}")
return (list[index].value as? T)
?: context.raiseError("Expected type ${T::class.simpleName}, got ${list[index].value::class.simpleName}")
}
companion object { companion object {
val EMPTY = Arguments(emptyList()) val EMPTY = Arguments(emptyList())
} }

View File

@ -67,7 +67,7 @@ class Context(
} }
} }
inline fun <reified T> addConst(value: T, vararg names: String) { inline fun <reified T> addConstWithAliases(value: T, vararg names: String) {
val obj = Obj.from(value) val obj = Obj.from(value)
for (name in names) { for (name in names) {
addItem( addItem(
@ -78,6 +78,8 @@ class Context(
} }
} }
fun addConst(name: String,value: Obj) = addItem(name, false, value)
suspend fun eval(code: String): Obj = suspend fun eval(code: String): Obj =
Compiler().compile(code.toSource()).execute(this) Compiler().compile(code.toSource()).execute(this)

View File

@ -190,6 +190,13 @@ data class ObjString(val value: String) : Obj() {
} }
override fun toString(): String = value override fun toString(): String = value
override val objClass: ObjClass
get() = type
companion object {
val type = ObjClass("String")
}
} }
interface Numeric { interface Numeric {
@ -273,10 +280,14 @@ data class ObjInt(var value: Long) : Obj(), Numeric {
} }
override fun toString(): String = value.toString() override fun toString(): String = value.toString()
override val objClass: ObjClass = type
companion object {
val type = ObjClass("Int")
}
} }
@Serializable
@SerialName("bool")
data class ObjBool(val value: Boolean) : Obj() { data class ObjBool(val value: Boolean) : Obj() {
override val asStr by lazy { ObjString(value.toString()) } override val asStr by lazy { ObjString(value.toString()) }
@ -286,6 +297,12 @@ data class ObjBool(val value: Boolean) : Obj() {
} }
override fun toString(): String = value.toString() override fun toString(): String = value.toString()
override val objClass: ObjClass = type
companion object {
val type = ObjClass("Bool")
}
} }
data class ObjNamespace(val name: String) : Obj() { data class ObjNamespace(val name: String) : Obj() {
@ -300,3 +317,4 @@ open class ObjError(val context: Context, val message: String) : Obj() {
class ObjNullPointerError(context: Context) : ObjError(context, "object is null") class ObjNullPointerError(context: Context) : ObjError(context, "object is null")
class ObjAssertionError(context: Context, message: String) : ObjError(context, message)

View File

@ -21,8 +21,8 @@ class Script(
val defaultContext: Context = Context().apply { val defaultContext: Context = Context().apply {
addFn("println") { addFn("println") {
print("yn: ") print("yn: ")
for( (i,a) in args.withIndex() ) { for ((i, a) in args.withIndex()) {
if( i > 0 ) print(' ' + a.asStr.value) if (i > 0) print(' ' + a.asStr.value)
else print(a.asStr.value) else print(a.asStr.value)
} }
println() println()
@ -30,28 +30,39 @@ class Script(
} }
addFn("floor") { addFn("floor") {
val x = args.firstAndOnly() val x = args.firstAndOnly()
if( x is ObjInt ) x if (x is ObjInt) x
else ObjReal(floor(x.toDouble())) else ObjReal(floor(x.toDouble()))
} }
addFn("ceil") { addFn("ceil") {
val x = args.firstAndOnly() val x = args.firstAndOnly()
if( x is ObjInt ) x if (x is ObjInt) x
else ObjReal(ceil(x.toDouble())) else ObjReal(ceil(x.toDouble()))
} }
addFn("round") { addFn("round") {
val x = args.firstAndOnly() val x = args.firstAndOnly()
if( x is ObjInt ) x if (x is ObjInt) x
else ObjReal(round(x.toDouble())) else ObjReal(round(x.toDouble()))
} }
addFn("sin") { addFn("sin") {
sin(args.firstAndOnly().toDouble()) sin(args.firstAndOnly().toDouble())
} }
addFn("assert") {
val cond = args.required<ObjBool>(0, this)
if( !cond.value == true )
raiseError(ObjAssertionError(this,"Assertion failed"))
}
addConst("Real", ObjReal.type)
addConst("String", ObjString.type)
addConst("Int", ObjInt.type)
addConst("Bool", ObjBool.type)
val pi = ObjReal(PI) val pi = ObjReal(PI)
val z = pi.objClass val z = pi.objClass
println("PI class $z") println("PI class $z")
addConst(pi, "π") addConst("π", pi)
getOrCreateNamespace("Math").apply { getOrCreateNamespace("Math").apply {
addConst( "PI", pi) addConst("PI", pi)
} }
} }
} }

View File

@ -189,7 +189,13 @@ class BookTest {
} }
@Test @Test
fun testsFromOOPrinciples() = runTest { fun testsFromOOP() = runTest {
runDocTests("../docs/OOP.md") runDocTests("../docs/OOP.md")
} }
@Test
fun testFromReal() = runTest {
runDocTests("../docs/real.md")
}
} }