fixed few bugs in compiler and plugin

This commit is contained in:
Sergey Chernov 2026-03-15 02:53:33 +03:00
parent 37d093817e
commit e447c778ed
10 changed files with 243 additions and 45 deletions

View File

@ -88,9 +88,11 @@ class LyngExternalAnnotator : ExternalAnnotator<LyngExternalAnnotator.Input, Lyn
// Imports: each segment as namespace/path // Imports: each segment as namespace/path
mini?.imports?.forEach { imp -> mini?.imports?.forEach { imp ->
imp.segments.forEach { seg -> imp.segments.forEach { seg ->
val start = analysis.source.offsetOf(seg.range.start) if (seg.range.start.source === analysis.source && seg.range.end.source === analysis.source) {
val end = analysis.source.offsetOf(seg.range.end) val start = analysis.source.offsetOf(seg.range.start)
putRange(start, end, LyngHighlighterColors.NAMESPACE) val end = analysis.source.offsetOf(seg.range.end)
putRange(start, end, LyngHighlighterColors.NAMESPACE)
}
} }
} }

View File

@ -35,7 +35,7 @@ class LyngLexer : LexerBase() {
"fun", "val", "var", "class", "interface", "type", "import", "as", "fun", "val", "var", "class", "interface", "type", "import", "as",
"abstract", "closed", "override", "static", "extern", "open", "private", "protected", "abstract", "closed", "override", "static", "extern", "open", "private", "protected",
"if", "else", "for", "while", "return", "true", "false", "null", "if", "else", "for", "while", "return", "true", "false", "null",
"when", "in", "is", "break", "continue", "try", "catch", "finally", "when", "in", "is", "break", "continue", "try", "catch", "finally", "void",
"get", "set", "object", "enum", "init", "by", "step", "property", "constructor" "get", "set", "object", "enum", "init", "by", "step", "property", "constructor"
) )

View File

@ -26,23 +26,16 @@ import com.intellij.psi.search.FilenameIndex
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import net.sergeych.lyng.binding.BindingSnapshot import net.sergeych.lyng.binding.BindingSnapshot
import net.sergeych.lyng.miniast.BuiltinDocRegistry
import net.sergeych.lyng.miniast.DocLookupUtils
import net.sergeych.lyng.miniast.MiniEnumDecl
import net.sergeych.lyng.miniast.MiniRange
import net.sergeych.lyng.miniast.MiniScript
import net.sergeych.lyng.tools.IdeLenientImportProvider
import net.sergeych.lyng.tools.LyngAnalysisRequest
import net.sergeych.lyng.tools.LyngAnalysisResult
import net.sergeych.lyng.tools.LyngDiagnostic
import net.sergeych.lyng.tools.LyngLanguageTools
import net.sergeych.lyng.idea.LyngFileType import net.sergeych.lyng.idea.LyngFileType
import net.sergeych.lyng.miniast.*
import net.sergeych.lyng.tools.*
object LyngAstManager { object LyngAstManager {
private val MINI_KEY = Key.create<MiniScript>("lyng.mini.cache") private val MINI_KEY = Key.create<MiniScript>("lyng.mini.cache")
private val BINDING_KEY = Key.create<BindingSnapshot>("lyng.binding.cache") private val BINDING_KEY = Key.create<BindingSnapshot>("lyng.binding.cache")
private val STAMP_KEY = Key.create<Long>("lyng.mini.cache.stamp") private val STAMP_KEY = Key.create<Long>("lyng.mini.cache.stamp")
private val ANALYSIS_KEY = Key.create<LyngAnalysisResult>("lyng.analysis.cache") private val ANALYSIS_KEY = Key.create<LyngAnalysisResult>("lyng.analysis.cache")
private val implicitBuiltinNames = setOf("void")
fun getMiniAst(file: PsiFile): MiniScript? = runReadAction { fun getMiniAst(file: PsiFile): MiniScript? = runReadAction {
getAnalysis(file)?.mini getAnalysis(file)?.mini
@ -217,7 +210,7 @@ object LyngAstManager {
val msg = diag.message val msg = diag.message
if (msg.startsWith("unresolved name: ")) { if (msg.startsWith("unresolved name: ")) {
val name = msg.removePrefix("unresolved name: ").trim() val name = msg.removePrefix("unresolved name: ").trim()
name in declaredTopLevel || name in builtinTopLevel name in declaredTopLevel || name in builtinTopLevel || name in implicitBuiltinNames
} else if (msg.startsWith("unresolved member: ")) { } else if (msg.startsWith("unresolved member: ")) {
val name = msg.removePrefix("unresolved member: ").trim() val name = msg.removePrefix("unresolved member: ").trim()
val range = diag.range val range = diag.range

View File

@ -124,4 +124,16 @@ class LyngDefinitionFilesTest : BasePlatformTestCase() {
assertTrue("Should not report unresolved name for Declared", messages.none { it.contains("unresolved name: Declared") }) assertTrue("Should not report unresolved name for Declared", messages.none { it.contains("unresolved name: Declared") })
assertTrue("Should not report unresolved member for greet", messages.none { it.contains("unresolved member: greet") }) assertTrue("Should not report unresolved member for greet", messages.none { it.contains("unresolved member: greet") })
} }
fun test_DiagnosticsDoNotReportVoidAsUnresolvedName() {
val code = """
fun f(): void {
return void
}
""".trimIndent()
myFixture.configureByText("main.lyng", code)
val analysis = LyngAstManager.getAnalysis(myFixture.file)
val messages = analysis?.diagnostics?.map { it.message } ?: emptyList()
assertTrue("Should not report unresolved name for void, got=$messages", messages.none { it.contains("unresolved name: void") })
}
} }

View File

@ -176,6 +176,8 @@ class Compiler(
private val lambdaCaptureEntriesByRef: MutableMap<ValueFnRef, List<net.sergeych.lyng.bytecode.LambdaCaptureEntry>> = private val lambdaCaptureEntriesByRef: MutableMap<ValueFnRef, List<net.sergeych.lyng.bytecode.LambdaCaptureEntry>> =
mutableMapOf() mutableMapOf()
private val classFieldTypesByName: MutableMap<String, MutableMap<String, ObjClass>> = mutableMapOf() private val classFieldTypesByName: MutableMap<String, MutableMap<String, ObjClass>> = mutableMapOf()
private val classMethodReturnTypeByName: MutableMap<String, MutableMap<String, ObjClass>> = mutableMapOf()
private val classMethodReturnTypeDeclByName: MutableMap<String, MutableMap<String, TypeDecl>> = mutableMapOf()
private val classScopeMembersByClassName: MutableMap<String, MutableSet<String>> = mutableMapOf() private val classScopeMembersByClassName: MutableMap<String, MutableSet<String>> = mutableMapOf()
private val classScopeCallableMembersByClassName: MutableMap<String, MutableSet<String>> = mutableMapOf() private val classScopeCallableMembersByClassName: MutableMap<String, MutableSet<String>> = mutableMapOf()
private val encodedPayloadTypeByScopeId: MutableMap<Int, MutableMap<Int, ObjClass>> = mutableMapOf() private val encodedPayloadTypeByScopeId: MutableMap<Int, MutableMap<Int, ObjClass>> = mutableMapOf()
@ -2614,7 +2616,34 @@ class Compiler(
} }
Token.Type.NOT -> { Token.Type.NOT -> {
if (operand != null) throw ScriptError(t.pos, "unexpected operator not '!' ") if (operand != null) {
val save = cc.savePos()
val next = cc.next()
if (next.type == Token.Type.NOT) {
val operandRef = operand
val receiverClass = resolveReceiverClassForMember(operandRef)
val inferredType = resolveReceiverTypeDecl(operandRef)
?: receiverClass?.let { TypeDecl.Simple(it.className, false) }
if (inferredType == null) {
operand = operandRef
continue
}
if (inferredType == TypeDecl.TypeAny || inferredType == TypeDecl.TypeNullableAny) {
operand = operandRef
continue
}
val nonNullType = makeTypeDeclNonNullable(inferredType)
operand = CastRef(
operandRef,
TypeDeclRef(nonNullType, t.pos),
isNullable = false,
atPos = t.pos
)
continue
}
cc.restorePos(save)
throw ScriptError(t.pos, "unexpected operator not '!' ")
}
val op = parseTerm() ?: throw ScriptError(t.pos, "Expecting expression") val op = parseTerm() ?: throw ScriptError(t.pos, "Expecting expression")
operand = UnaryOpRef(UnaryOp.NOT, op) operand = UnaryOpRef(UnaryOp.NOT, op)
} }
@ -3821,6 +3850,21 @@ class Compiler(
} }
} }
private fun makeTypeDeclNonNullable(type: TypeDecl): TypeDecl {
if (!type.isNullable) return type
return when (type) {
TypeDecl.TypeAny -> type
TypeDecl.TypeNullableAny -> TypeDecl.TypeAny
is TypeDecl.Function -> type.copy(nullable = false)
is TypeDecl.Ellipsis -> type.copy(nullable = false)
is TypeDecl.TypeVar -> type.copy(nullable = false)
is TypeDecl.Union -> type.copy(nullable = false)
is TypeDecl.Intersection -> type.copy(nullable = false)
is TypeDecl.Simple -> TypeDecl.Simple(type.name, false)
is TypeDecl.Generic -> TypeDecl.Generic(type.name, type.args, false)
}
}
private fun makeMiniTypeNullable(type: MiniTypeRef): MiniTypeRef { private fun makeMiniTypeNullable(type: MiniTypeRef): MiniTypeRef {
return when (type) { return when (type) {
is MiniTypeName -> type.copy(nullable = true) is MiniTypeName -> type.copy(nullable = true)
@ -4491,6 +4535,48 @@ class Compiler(
is TypeDecl.Intersection -> "I:${type.options.joinToString("&") { typeDeclKey(it) }}" is TypeDecl.Intersection -> "I:${type.options.joinToString("&") { typeDeclKey(it) }}"
} }
private fun classMethodReturnTypeDecl(targetClass: ObjClass?, name: String): TypeDecl? {
if (targetClass == null) return null
if (targetClass == ObjDynamic.type) return TypeDecl.TypeAny
val member = targetClass.getInstanceMemberOrNull(name, includeAbstract = true)
val declaringName = member?.declaringClass?.className
if (declaringName != null) {
classMethodReturnTypeDeclByName[declaringName]?.get(name)?.let { return it }
classMethodReturnTypeByName[declaringName]?.get(name)?.let {
return TypeDecl.Simple(it.className, false)
}
}
classMethodReturnTypeDeclByName[targetClass.className]?.get(name)?.let { return it }
classMethodReturnTypeByName[targetClass.className]?.get(name)?.let {
return TypeDecl.Simple(it.className, false)
}
member?.typeDecl?.let { declaredType ->
if (declaredType is TypeDecl.Function) return declaredType.returnType
return declaredType
}
return null
}
private fun classMethodReturnClass(targetClass: ObjClass?, name: String): ObjClass? {
if (targetClass == null) return null
if (targetClass == ObjDynamic.type) return ObjDynamic.type
classMethodReturnTypeDecl(targetClass, name)?.let { declared ->
resolveTypeDeclObjClass(declared)?.let { return it }
if (declared is TypeDecl.TypeVar) return Obj.rootObjectType
}
val member = targetClass.getInstanceMemberOrNull(name, includeAbstract = true)
val declaringName = member?.declaringClass?.className
if (declaringName != null) {
classMethodReturnTypeByName[declaringName]?.get(name)?.let { return it }
}
classMethodReturnTypeByName[targetClass.className]?.get(name)?.let { return it }
val declaredType = member?.typeDecl
if (declaredType is TypeDecl.Function) {
resolveTypeDeclObjClass(declaredType.returnType)?.let { return it }
}
return null
}
private fun inferObjClassFromRef(ref: ObjRef): ObjClass? = when (ref) { private fun inferObjClassFromRef(ref: ObjRef): ObjClass? = when (ref) {
is ConstRef -> ref.constValue as? ObjClass ?: ref.constValue.objClass is ConstRef -> ref.constValue as? ObjClass ?: ref.constValue.objClass
is LocalVarRef -> nameObjClass[ref.name] ?: resolveClassByName(ref.name) is LocalVarRef -> nameObjClass[ref.name] ?: resolveClassByName(ref.name)
@ -4511,6 +4597,11 @@ class Compiler(
is RangeRef -> ObjRange.type is RangeRef -> ObjRange.type
is ClassOperatorRef -> ObjClassType is ClassOperatorRef -> ObjClassType
is CastRef -> resolveTypeRefClass(ref.castTypeRef()) is CastRef -> resolveTypeRefClass(ref.castTypeRef())
is IndexRef -> {
val targetClass = resolveReceiverClassForMember(ref.targetRef)
classMethodReturnClass(targetClass, "getAt")
?: inferFieldReturnClass(targetClass, "getAt")
}
else -> null else -> null
} }
@ -4547,6 +4638,12 @@ class Compiler(
else -> TypeDecl.TypeVar("${typeDeclName(targetDecl)}.${ref.name}", false) else -> TypeDecl.TypeVar("${typeDeclName(targetDecl)}.${ref.name}", false)
} }
} }
is IndexRef -> {
val targetDecl = resolveReceiverTypeDecl(ref.targetRef)
inferMethodCallReturnTypeDecl("getAt", targetDecl)?.let { return it }
val targetClass = resolveReceiverClassForMember(ref.targetRef)
classMethodReturnTypeDecl(targetClass, "getAt")
}
is MethodCallRef -> methodReturnTypeDeclByRef[ref] is MethodCallRef -> methodReturnTypeDeclByRef[ref]
is CallRef -> callReturnTypeDeclByRef[ref] is CallRef -> callReturnTypeDeclByRef[ref]
is StatementRef -> (ref.statement as? ExpressionStatement)?.let { resolveReceiverTypeDecl(it.ref) } is StatementRef -> (ref.statement as? ExpressionStatement)?.let { resolveReceiverTypeDecl(it.ref) }
@ -4616,6 +4713,12 @@ class Compiler(
val targetClass = resolveReceiverClassForMember(ref.target) val targetClass = resolveReceiverClassForMember(ref.target)
inferFieldReturnClass(targetClass, ref.name) inferFieldReturnClass(targetClass, ref.name)
} }
is IndexRef -> {
val targetClass = resolveReceiverClassForMember(ref.targetRef)
classMethodReturnClass(targetClass, "getAt")
?: inferFieldReturnClass(targetClass, "getAt")
?: inferMethodCallReturnClass("getAt")
}
else -> null else -> null
} }
} }
@ -5102,6 +5205,7 @@ class Compiler(
} }
private fun resolveTypeRefClass(ref: ObjRef): ObjClass? = when (ref) { private fun resolveTypeRefClass(ref: ObjRef): ObjClass? = when (ref) {
is TypeDeclRef -> resolveTypeDeclObjClass(ref.decl())
is ConstRef -> ref.constValue as? ObjClass is ConstRef -> ref.constValue as? ObjClass
is LocalSlotRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name] is LocalSlotRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name]
is LocalVarRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name] is LocalVarRef -> resolveTypeDeclObjClass(TypeDecl.Simple(ref.name, false)) ?: nameObjClass[ref.name]
@ -7885,6 +7989,23 @@ class Compiler(
val rawFnStatements = parsedFnStatements?.let { unwrapBytecodeDeep(it) } val rawFnStatements = parsedFnStatements?.let { unwrapBytecodeDeep(it) }
val inferredReturnClass = returnTypeDecl?.let { resolveTypeDeclObjClass(it) } val inferredReturnClass = returnTypeDecl?.let { resolveTypeDeclObjClass(it) }
?: inferReturnClassFromStatement(rawFnStatements) ?: inferReturnClassFromStatement(rawFnStatements)
if (declKind == SymbolKind.MEMBER && extTypeName == null) {
val ownerClassName = (parentContext as? CodeContext.ClassBody)?.name
if (ownerClassName != null) {
val returnDecl = returnTypeDecl
?: inferredReturnClass?.let { TypeDecl.Simple(it.className, false) }
if (returnDecl != null) {
classMethodReturnTypeDeclByName
.getOrPut(ownerClassName) { mutableMapOf() }[name] = returnDecl
resolveTypeDeclObjClass(returnDecl)?.let { returnClass ->
classMethodReturnTypeByName
.getOrPut(ownerClassName) { mutableMapOf() }[name] = returnClass
classFieldTypesByName
.getOrPut(ownerClassName) { mutableMapOf() }[name] = returnClass
}
}
}
}
if (declKind != SymbolKind.MEMBER && inferredReturnClass != null) { if (declKind != SymbolKind.MEMBER && inferredReturnClass != null) {
callableReturnTypeByName[name] = inferredReturnClass callableReturnTypeByName[name] = inferredReturnClass
val slotLoc = lookupSlotLocation(name, includeModule = true) val slotLoc = lookupSlotLocation(name, includeModule = true)

View File

@ -46,7 +46,7 @@ private val fallbackKeywordIds = setOf(
"private", "protected", "static", "open", "extern", "init", "get", "set", "by", "step", "private", "protected", "static", "open", "extern", "init", "get", "set", "by", "step",
// control flow and misc // control flow and misc
"if", "else", "when", "while", "do", "for", "try", "catch", "finally", "if", "else", "when", "while", "do", "for", "try", "catch", "finally",
"throw", "return", "break", "continue", "this", "null", "true", "false", "unset" "throw", "return", "break", "continue", "this", "null", "true", "false", "unset", "void"
) )
/** Maps lexer token type (and sometimes value) to a [HighlightKind]. */ /** Maps lexer token type (and sometimes value) to a [HighlightKind]. */

View File

@ -179,6 +179,7 @@ object LyngLanguageTools {
val source = analysis.source val source = analysis.source
val out = ArrayList<LyngSemanticSpan>(128) val out = ArrayList<LyngSemanticSpan>(128)
val covered = HashSet<Pair<Int, Int>>() val covered = HashSet<Pair<Int, Int>>()
fun isCurrentSource(pos: Pos): Boolean = pos.source === source
fun addRange(start: Int, end: Int, kind: LyngSemanticKind) { fun addRange(start: Int, end: Int, kind: LyngSemanticKind) {
if (start < 0 || end <= start || end > analysis.text.length) return if (start < 0 || end <= start || end > analysis.text.length) return
@ -187,6 +188,7 @@ object LyngLanguageTools {
} }
fun addName(pos: Pos, name: String, kind: LyngSemanticKind) { fun addName(pos: Pos, name: String, kind: LyngSemanticKind) {
if (!isCurrentSource(pos)) return
val s = source.offsetOf(pos) val s = source.offsetOf(pos)
addRange(s, s + name.length, kind) addRange(s, s + name.length, kind)
} }
@ -206,7 +208,9 @@ object LyngLanguageTools {
addTypeSegments(t.returnType) addTypeSegments(t.returnType)
} }
is MiniTypeVar -> { is MiniTypeVar -> {
addRange(source.offsetOf(t.range.start), source.offsetOf(t.range.end), LyngSemanticKind.TypeRef) if (isCurrentSource(t.range.start) && isCurrentSource(t.range.end)) {
addRange(source.offsetOf(t.range.start), source.offsetOf(t.range.end), LyngSemanticKind.TypeRef)
}
} }
is MiniTypeUnion -> { is MiniTypeUnion -> {
t.options.forEach { addTypeSegments(it) } t.options.forEach { addTypeSegments(it) }
@ -262,7 +266,9 @@ object LyngLanguageTools {
mini.imports.forEach { imp -> mini.imports.forEach { imp ->
imp.segments.forEach { seg -> imp.segments.forEach { seg ->
addRange(source.offsetOf(seg.range.start), source.offsetOf(seg.range.end), LyngSemanticKind.TypeRef) if (isCurrentSource(seg.range.start) && isCurrentSource(seg.range.end)) {
addRange(source.offsetOf(seg.range.start), source.offsetOf(seg.range.end), LyngSemanticKind.TypeRef)
}
} }
} }

View File

@ -565,19 +565,6 @@ class TypesTest {
""".trimIndent()) """.trimIndent())
} }
// @Test
// fun testNullableGenericTypes() = runTest {
// eval("""
// fun t<T>(): String =
// when(T) {
// is Object -> "%s is Object"(T::class.name)
// else -> throw "It should not happen"
// }
// assert( Int is Object)
// assertEquals( t<Int>(), "Class is Object")
// """.trimIndent())
// }
@Test fun testIndexer() = runTest { @Test fun testIndexer() = runTest {
eval(""" eval("""
class Greeter { class Greeter {
@ -596,6 +583,38 @@ class TypesTest {
""".trimIndent()) """.trimIndent())
} }
@Test fun testIndexer2() = runTest {
eval("""
class Foo(bar)
class Greeter {
override fun getAt(name): Foo = Foo("Hello, %s!"(name))
}
assertEquals("Hello, Bob!",Greeter()["Bob"].bar)
val g = Greeter()
assertEquals("Hello, Bob!",g["Bob"].bar)
// it should work with objects too:
object Polite {
override fun getAt(name): Foo? = Foo("How do you do, %s?"(name))
}
assertEquals("How do you do, Bob?",Polite["Bob"].bar)
assertEquals("How do you do, Bob?",Polite["Bob"]?.bar)
assertEquals("How do you do, Bob?",Polite["Bob"]!!.bar)
class Greeter2 {
override fun getAt(name): Foo? = Foo("How do you do, %s?"(name))
}
val g2 = Greeter2()
assertEquals("How do you do, Bob?",g2["Bob"]?.bar)
val g2v: Foo = g2["Bob"]!!
assertEquals("How do you do, Bob?",g2v.bar)
assertEquals("How do you do, Bob?",Greeter2()["Bob"].bar)
""".trimIndent())
}
// @Test fun nonTrivialOperatorsTest() = runTest { // @Test fun nonTrivialOperatorsTest() = runTest {
// val s = Script.newScope() // val s = Script.newScope()
// s.eval(""" // s.eval("""

View File

@ -18,8 +18,9 @@
package net.sergeych.lyng.tools package net.sergeych.lyng.tools
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import net.sergeych.lyng.miniast.MiniClassDecl import net.sergeych.lyng.Pos
import net.sergeych.lyng.miniast.MiniMemberTypeAliasDecl import net.sergeych.lyng.Source
import net.sergeych.lyng.miniast.*
import net.sergeych.lyng.stdlib_included.rootLyng import net.sergeych.lyng.stdlib_included.rootLyng
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -127,4 +128,48 @@ class LyngLanguageToolsTest {
val dis = LyngLanguageTools.disassembleSymbol(code, "add") val dis = LyngLanguageTools.disassembleSymbol(code, "add")
assertTrue(!dis.contains("not a compiled body"), "Disassembly should be produced, got: $dis") assertTrue(!dis.contains("not a compiled body"), "Disassembly should be produced, got: $dis")
} }
@Test
fun languageTools_semanticHighlights_ignore_foreign_sources() {
val localSource = Source("local.lyng", "val x = 1")
val foreignSource = Source("defs.lyng.d", "val y = 2")
val localStart = Pos(localSource, 0, 0)
val foreignStart = Pos(foreignSource, 0, 0)
val mini = MiniScript(
range = MiniRange(localStart, localStart),
declarations = mutableListOf(
MiniValDecl(
range = MiniRange(foreignStart, foreignStart),
name = "y",
mutable = false,
type = null,
initRange = null,
doc = null,
nameStart = foreignStart
)
),
imports = mutableListOf(
MiniImport(
range = MiniRange(foreignStart, foreignStart),
segments = listOf(
MiniImport.Segment("defs", MiniRange(foreignStart, foreignStart))
)
)
)
)
val analysis = LyngAnalysisResult(
source = localSource,
text = localSource.text,
mini = mini,
binding = null,
resolution = null,
importedModules = emptyList(),
diagnostics = emptyList(),
lexicalHighlights = emptyList()
)
val spans = LyngLanguageTools.semanticHighlights(analysis)
assertTrue(spans.isEmpty(), "Semantic spans should ignore positions from foreign sources, got $spans")
}
} }

View File

@ -1,6 +1,6 @@
package lyng.stdlib package lyng.stdlib
extern fun flow(builder: FlowBuilder.()->Void): Flow extern fun flow(builder: FlowBuilder.()->void): Flow
/* Built-in exception type. */ /* Built-in exception type. */
extern class Exception extern class Exception
@ -9,7 +9,7 @@ extern class NotImplementedException
extern class Delegate extern class Delegate
extern class Iterable<T> { extern class Iterable<T> {
fun iterator(): Iterator<T> fun iterator(): Iterator<T>
fun forEach(action: (T)->Void): Void fun forEach(action: (T)->void): void
fun map<R>(transform: (T)->R): List<R> fun map<R>(transform: (T)->R): List<R>
fun toList(): List<T> fun toList(): List<T>
fun toImmutableList(): ImmutableList<T> fun toImmutableList(): ImmutableList<T>
@ -22,7 +22,7 @@ extern class Iterable<T> {
extern class Iterator<T> { extern class Iterator<T> {
fun hasNext(): Bool fun hasNext(): Bool
fun next(): T fun next(): T
fun cancelIteration(): Void fun cancelIteration(): void
fun toList(): List<T> fun toList(): List<T>
} }
@ -44,14 +44,14 @@ extern class ImmutableList<T> : Array<T> {
} }
extern class List<T> : Array<T> { extern class List<T> : Array<T> {
fun add(value: T, more...): Void fun add(value: T, more...): void
fun toImmutable(): ImmutableList<T> fun toImmutable(): ImmutableList<T>
} }
extern class RingBuffer<T> : Iterable<T> { extern class RingBuffer<T> : Iterable<T> {
val size: Int val size: Int
fun first(): T fun first(): T
fun add(value: T): Void fun add(value: T): void
} }
extern class Set<T> : Collection<T> { extern class Set<T> : Collection<T> {
@ -337,17 +337,17 @@ override fun List<T>.toString() {
} }
/* Sort list in-place by key selector. */ /* Sort list in-place by key selector. */
fun List<T>.sortBy<R>(predicate: (T)->R): Void { fun List<T>.sortBy<R>(predicate: (T)->R): void {
sortWith { a, b -> predicate(a) <=> predicate(b) } sortWith { a, b -> predicate(a) <=> predicate(b) }
} }
/* Sort list in-place by natural order. */ /* Sort list in-place by natural order. */
fun List<T>.sort(): Void { fun List<T>.sort(): void {
sortWith { a, b -> a <=> b } sortWith { a, b -> a <=> b }
} }
/* Print this exception and its stack trace to standard output. */ /* Print this exception and its stack trace to standard output. */
fun Exception.printStackTrace(): Void { fun Exception.printStackTrace(): void {
println(this) println(this)
for( entry in stackTrace ) { for( entry in stackTrace ) {
println("\tat "+entry.toString()) println("\tat "+entry.toString())
@ -357,7 +357,7 @@ fun Exception.printStackTrace(): Void {
/* Compile this string into a regular expression. */ /* Compile this string into a regular expression. */
val String.re: Regex get() = Regex(this) val String.re: Regex get() = Regex(this)
fun TODO(message: Object?=null): Void { fun TODO(message: Object?=null): void {
throw "not implemented" throw "not implemented"
} }
@ -376,12 +376,12 @@ enum DelegateAccess {
Implementing this interface is optional as Lyng uses dynamic dispatch, Implementing this interface is optional as Lyng uses dynamic dispatch,
but it is recommended for documentation and clarity. but it is recommended for documentation and clarity.
*/ */
interface Delegate<T,ThisRefType=Void> { interface Delegate<T,ThisRefType=void> {
/* Called when a delegated 'val' or 'var' is read. */ /* Called when a delegated 'val' or 'var' is read. */
fun getValue(thisRef: ThisRefType, name: String): T = TODO("delegate getter is not implemented") fun getValue(thisRef: ThisRefType, name: String): T = TODO("delegate getter is not implemented")
/* Called when a delegated 'var' is written. */ /* Called when a delegated 'var' is written. */
fun setValue(thisRef: ThisRefType, name: String, newValue: T): Void = TODO("delegate setter is not implemented") fun setValue(thisRef: ThisRefType, name: String, newValue: T): void = TODO("delegate setter is not implemented")
/* Called when a delegated function is invoked. */ /* Called when a delegated function is invoked. */
fun invoke(thisRef: ThisRefType, name: String, args...): Object = TODO("delegate invoke is not implemented") fun invoke(thisRef: ThisRefType, name: String, args...): Object = TODO("delegate invoke is not implemented")