Compare commits
2 Commits
961228ca0b
...
f338c54632
Author | SHA1 | Date | |
---|---|---|---|
f338c54632 | |||
3ef80616d8 |
@ -402,7 +402,9 @@ class Compiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class AccessType(val isMutable: Boolean) {
|
enum class AccessType(val isMutable: Boolean) {
|
||||||
Val(false), Var(true), Initialization(false)
|
Val(false), Var(true),
|
||||||
|
@Suppress("unused")
|
||||||
|
Initialization(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Visibility {
|
enum class Visibility {
|
||||||
@ -713,7 +715,6 @@ class Compiler(
|
|||||||
cc.skipTokenOfType(Token.Type.NEWLINE, isOptional = true)
|
cc.skipTokenOfType(Token.Type.NEWLINE, isOptional = true)
|
||||||
val t = cc.next()
|
val t = cc.next()
|
||||||
|
|
||||||
var extraInit: Statement? = null
|
|
||||||
val bodyInit: Statement? = if (t.type == Token.Type.LBRACE) {
|
val bodyInit: Statement? = if (t.type == Token.Type.LBRACE) {
|
||||||
// parse body
|
// parse body
|
||||||
parseScript(t.pos, cc).also {
|
parseScript(t.pos, cc).also {
|
||||||
@ -726,10 +727,9 @@ class Compiler(
|
|||||||
|
|
||||||
// create class
|
// create class
|
||||||
val className = nameToken.value
|
val className = nameToken.value
|
||||||
lateinit var classContext: Context
|
|
||||||
|
|
||||||
val defaultAccess = if (isStruct) AccessType.Var else AccessType.Initialization
|
@Suppress("UNUSED_VARIABLE") val defaultAccess = if (isStruct) AccessType.Var else AccessType.Initialization
|
||||||
val defaultVisibility = Visibility.Public
|
@Suppress("UNUSED_VARIABLE") val defaultVisibility = Visibility.Public
|
||||||
|
|
||||||
// create instance constructor
|
// create instance constructor
|
||||||
// create custom objClass with all fields and instance constructor
|
// create custom objClass with all fields and instance constructor
|
||||||
@ -741,14 +741,11 @@ class Compiler(
|
|||||||
|
|
||||||
// the context now is a "class creation context", we must use its args to initialize
|
// the context now is a "class creation context", we must use its args to initialize
|
||||||
// fields. Note that 'this' is already set by class
|
// fields. Note that 'this' is already set by class
|
||||||
constructorArgsDeclaration?.let { cad ->
|
constructorArgsDeclaration?.assignToContext(this)
|
||||||
cad.assignToContext(this)
|
|
||||||
// note that accessors are created in ObjClass instance, not during instance
|
|
||||||
// initialization (not here)
|
|
||||||
}
|
|
||||||
bodyInit?.execute(this)
|
bodyInit?.execute(this)
|
||||||
// export public
|
// export public
|
||||||
for( (name,record) in objects ) {
|
for( (name,record) in objects ) {
|
||||||
|
println("-- $name $record")
|
||||||
when(record.visibility) {
|
when(record.visibility) {
|
||||||
Visibility.Public -> {
|
Visibility.Public -> {
|
||||||
thisObj.publicFields += name
|
thisObj.publicFields += name
|
||||||
|
@ -27,6 +27,7 @@ class Context(
|
|||||||
|
|
||||||
fun raiseClassCastError(msg: String): Nothing = raiseError(ObjClassCastError(this, msg))
|
fun raiseClassCastError(msg: String): Nothing = raiseError(ObjClassCastError(this, msg))
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
fun raiseSymbolNotFound(name: String): Nothing = raiseError(ObjSymbolNotDefinedError(this, "symbol is not defined: $name"))
|
fun raiseSymbolNotFound(name: String): Nothing = raiseError(ObjSymbolNotDefinedError(this, "symbol is not defined: $name"))
|
||||||
|
|
||||||
fun raiseError(message: String): Nothing {
|
fun raiseError(message: String): Nothing {
|
||||||
@ -78,7 +79,7 @@ class Context(
|
|||||||
|
|
||||||
fun getOrCreateNamespace(name: String): ObjClass {
|
fun getOrCreateNamespace(name: String): ObjClass {
|
||||||
val ns = objects.getOrPut(name) { ObjRecord(ObjNamespace(name), isMutable = false) }.value
|
val ns = objects.getOrPut(name) { ObjRecord(ObjNamespace(name), isMutable = false) }.value
|
||||||
return ns!!.objClass
|
return ns.objClass
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun addVoidFn(vararg names: String, crossinline fn: suspend Context.() -> Unit) {
|
inline fun addVoidFn(vararg names: String, crossinline fn: suspend Context.() -> Unit) {
|
||||||
|
@ -69,7 +69,7 @@ open class Obj {
|
|||||||
args: Arguments = Arguments.EMPTY
|
args: Arguments = Arguments.EMPTY
|
||||||
): T = invokeInstanceMethod(context, name, args) as T
|
): T = invokeInstanceMethod(context, name, args) as T
|
||||||
|
|
||||||
suspend fun invokeInstanceMethod(
|
open suspend fun invokeInstanceMethod(
|
||||||
context: Context,
|
context: Context,
|
||||||
name: String,
|
name: String,
|
||||||
args: Arguments = Arguments.EMPTY
|
args: Arguments = Arguments.EMPTY
|
||||||
|
@ -46,7 +46,7 @@ class ObjClass(
|
|||||||
) {
|
) {
|
||||||
if (name in members || allParentsSet.any { name in it.members } == true)
|
if (name in members || allParentsSet.any { name in it.members } == true)
|
||||||
throw ScriptError(pos, "$name is already defined in $objClass or one of its supertypes")
|
throw ScriptError(pos, "$name is already defined in $objClass or one of its supertypes")
|
||||||
members[name] = ObjRecord(initialValue, isMutable)
|
members[name] = ObjRecord(initialValue, isMutable, visibility)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addFn(name: String, isOpen: Boolean = false, code: suspend Context.() -> Obj) {
|
fun addFn(name: String, isOpen: Boolean = false, code: suspend Context.() -> Obj) {
|
||||||
@ -151,25 +151,3 @@ val ObjArray by lazy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ObjInstance(override val objClass: ObjClass) : Obj() {
|
|
||||||
|
|
||||||
internal val publicFields = mutableSetOf<String>()
|
|
||||||
internal val protectedFields = mutableSetOf<String>()
|
|
||||||
|
|
||||||
internal lateinit var instanceContext: Context
|
|
||||||
|
|
||||||
override suspend fun readField(context: Context, name: String): ObjRecord {
|
|
||||||
return if( name in publicFields ) instanceContext[name]!!
|
|
||||||
else super.readField(context, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun writeField(context: Context, name: String, newValue: Obj) {
|
|
||||||
if( name in publicFields ) {
|
|
||||||
val f = instanceContext[name]!!
|
|
||||||
if( !f.isMutable ) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
|
|
||||||
if( f.value.assign(context, newValue) == null)
|
|
||||||
f.value = newValue
|
|
||||||
}
|
|
||||||
else super.writeField(context, name, newValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package net.sergeych.lyng
|
||||||
|
|
||||||
|
class ObjInstance(override val objClass: ObjClass) : Obj() {
|
||||||
|
|
||||||
|
internal val publicFields = mutableSetOf<String>()
|
||||||
|
internal val protectedFields = mutableSetOf<String>()
|
||||||
|
|
||||||
|
internal lateinit var instanceContext: Context
|
||||||
|
|
||||||
|
override suspend fun readField(context: Context, name: String): ObjRecord {
|
||||||
|
return if( name in publicFields ) instanceContext[name]!!
|
||||||
|
else super.readField(context, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun writeField(context: Context, name: String, newValue: Obj) {
|
||||||
|
if( name in publicFields ) {
|
||||||
|
val f = instanceContext[name]!!
|
||||||
|
if( !f.isMutable ) ObjIllegalAssignmentError(context, "can't reassign val $name").raise()
|
||||||
|
if( f.value.assign(context, newValue) == null)
|
||||||
|
f.value = newValue
|
||||||
|
}
|
||||||
|
else super.writeField(context, name, newValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun invokeInstanceMethod(context: Context, name: String, args: Arguments): Obj {
|
||||||
|
if( name in publicFields ) return instanceContext[name]!!.value.invoke(context, this, args)
|
||||||
|
return super.invokeInstanceMethod(context, name, args)
|
||||||
|
}
|
||||||
|
}
|
@ -1435,4 +1435,22 @@ class ScriptTest {
|
|||||||
assert( p.length == 5 )
|
assert( p.length == 5 )
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testStructBodyFun() = runTest {
|
||||||
|
val c = Context()
|
||||||
|
c.eval("""
|
||||||
|
struct Point(x,y) {
|
||||||
|
fun length() {
|
||||||
|
sqrt(x*x+y*y)
|
||||||
|
}
|
||||||
|
var foo = "zero"
|
||||||
|
}
|
||||||
|
val p = Point(3,4)
|
||||||
|
assertEquals(5, p.length())
|
||||||
|
p.y = 10
|
||||||
|
println(p.length())
|
||||||
|
assertEquals(sqrt(109), p.length())
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user