heroic attempt to fix kotlin 3.2.0 wasmJS compiler
(incomplete)
This commit is contained in:
1 parent
7b1ba71ef0
commit
f9ae00b7f4
50 files changed
+3815
-2913
No files matched your search
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2025 Sergey S. Chernov real.sergeych@gmail.com
|
||||
* Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,9 +23,11 @@ package net.sergeych.lyng.io.fs
|
||||
|
||||
import net.sergeych.lyng.ModuleScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScopeCallable
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.pacman.ModuleBuilder
|
||||
import net.sergeych.lyngio.fs.LyngFS
|
||||
import net.sergeych.lyngio.fs.LyngFs
|
||||
import net.sergeych.lyngio.fs.LyngPath
|
||||
@@ -50,9 +52,11 @@ fun createFsModule(policy: FsAccessPolicy, manager: ImportManager): Boolean {
|
||||
// Avoid re-registering in this ImportManager
|
||||
if (manager.packageNames.contains(name)) return false
|
||||
|
||||
manager.addPackage(name) { module ->
|
||||
buildFsModule(module, policy)
|
||||
}
|
||||
manager.addPackage(name, object : ModuleBuilder {
|
||||
override suspend fun build(module: ModuleScope) {
|
||||
buildFsModule(module, policy)
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -78,322 +82,394 @@ private suspend fun buildFsModule(module: ModuleScope, policy: FsAccessPolicy) {
|
||||
name = "name",
|
||||
doc = "Base name of the path (last segment).",
|
||||
returns = type("lyng.String"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val self = thisAs<ObjPath>()
|
||||
self.path.name.toObj()
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjPath>()
|
||||
return self.path.name.toObj()
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "parent",
|
||||
doc = "Parent directory as a Path or null if none.",
|
||||
returns = type("Path", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val self = thisAs<ObjPath>()
|
||||
self.path.parent?.let {
|
||||
ObjPath( this@apply, self.secured, it)
|
||||
} ?: ObjNull
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjPath>()
|
||||
return self.path.parent?.let {
|
||||
ObjPath(this@apply, self.secured, it)
|
||||
} ?: ObjNull
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "segments",
|
||||
doc = "List of path segments.",
|
||||
// returns: List<String>
|
||||
returns = TypeGenericDoc(type("lyng.List"), listOf(type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val self = thisAs<ObjPath>()
|
||||
ObjList(self.path.segments.map { ObjString(it) }.toMutableList())
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjPath>()
|
||||
return ObjList(self.path.segments.map { ObjString(it) }.toMutableList())
|
||||
}
|
||||
}
|
||||
)
|
||||
// exists(): Bool
|
||||
addFnDoc(
|
||||
name = "exists",
|
||||
doc = "Check whether this path exists.",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
(self.secured.exists(self.path)).toObj()
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
(self.secured.exists(self.path)).toObj()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// isFile(): Bool — cached metadata
|
||||
addFnDoc(
|
||||
name = "isFile",
|
||||
doc = "True if this path is a regular file (based on cached metadata).",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
self.ensureMetadata().let { ObjBool(it.isRegularFile) }
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
self.ensureMetadata().let { ObjBool(it.isRegularFile) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// isDirectory(): Bool — cached metadata
|
||||
addFnDoc(
|
||||
name = "isDirectory",
|
||||
doc = "True if this path is a directory (based on cached metadata).",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
self.ensureMetadata().let { ObjBool(it.isDirectory) }
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
self.ensureMetadata().let { ObjBool(it.isDirectory) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// size(): Int? — null when unavailable
|
||||
addFnDoc(
|
||||
name = "size",
|
||||
doc = "File size in bytes, or null when unavailable.",
|
||||
returns = type("lyng.Int", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.size?.let { ObjInt(it) } ?: ObjNull
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.size?.let { ObjInt(it) } ?: ObjNull
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// createdAt(): Instant? — Lyng Instant, null when unavailable
|
||||
addFnDoc(
|
||||
name = "createdAt",
|
||||
doc = "Creation time as `Instant`, or null when unavailable.",
|
||||
returns = type("lyng.Instant", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.createdAtMillis?.let { ObjInstant(kotlin.time.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.createdAtMillis?.let { ObjInstant(kotlin.time.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// createdAtMillis(): Int? — milliseconds since epoch or null
|
||||
addFnDoc(
|
||||
name = "createdAtMillis",
|
||||
doc = "Creation time in milliseconds since epoch, or null when unavailable.",
|
||||
returns = type("lyng.Int", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.createdAtMillis?.let { ObjInt(it) } ?: ObjNull
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.createdAtMillis?.let { ObjInt(it) } ?: ObjNull
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// modifiedAt(): Instant? — Lyng Instant, null when unavailable
|
||||
addFnDoc(
|
||||
name = "modifiedAt",
|
||||
doc = "Last modification time as `Instant`, or null when unavailable.",
|
||||
returns = type("lyng.Instant", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.modifiedAtMillis?.let { ObjInstant(kotlinx.datetime.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.modifiedAtMillis?.let { ObjInstant(kotlinx.datetime.Instant.fromEpochMilliseconds(it)) } ?: ObjNull
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// modifiedAtMillis(): Int? — milliseconds since epoch or null
|
||||
addFnDoc(
|
||||
name = "modifiedAtMillis",
|
||||
doc = "Last modification time in milliseconds since epoch, or null when unavailable.",
|
||||
returns = type("lyng.Int", nullable = true),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.modifiedAtMillis?.let { ObjInt(it) } ?: ObjNull
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.ensureMetadata()
|
||||
m.modifiedAtMillis?.let { ObjInt(it) } ?: ObjNull
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// list(): List<Path>
|
||||
addFnDoc(
|
||||
name = "list",
|
||||
doc = "List directory entries as `Path` objects.",
|
||||
returns = TypeGenericDoc(type("lyng.List"), listOf(type("Path"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val items = self.secured.list(self.path).map { ObjPath(self.objClass, self.secured, it) }
|
||||
ObjList(items.toMutableList())
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val items = self.secured.list(self.path).map { ObjPath(self.objClass, self.secured, it) }
|
||||
ObjList(items.toMutableList())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// readBytes(): Buffer
|
||||
addFnDoc(
|
||||
name = "readBytes",
|
||||
doc = "Read the file into a binary buffer.",
|
||||
returns = type("lyng.Buffer"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val bytes = self.secured.readBytes(self.path)
|
||||
ObjBuffer(bytes.asUByteArray())
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val bytes = self.secured.readBytes(self.path)
|
||||
ObjBuffer(bytes.asUByteArray())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// writeBytes(bytes: Buffer)
|
||||
addFnDoc(
|
||||
name = "writeBytes",
|
||||
doc = "Write a binary buffer to the file, replacing content.",
|
||||
params = listOf(ParamDoc("bytes", type("lyng.Buffer"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val buf = requiredArg<ObjBuffer>(0)
|
||||
self.secured.writeBytes(self.path, buf.byteArray.asByteArray(), append = false)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val buf = scp.requiredArg<ObjBuffer>(0)
|
||||
self.secured.writeBytes(self.path, buf.byteArray.asByteArray(), append = false)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// appendBytes(bytes: Buffer)
|
||||
addFnDoc(
|
||||
name = "appendBytes",
|
||||
doc = "Append a binary buffer to the end of the file.",
|
||||
params = listOf(ParamDoc("bytes", type("lyng.Buffer"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val buf = requiredArg<ObjBuffer>(0)
|
||||
self.secured.writeBytes(self.path, buf.byteArray.asByteArray(), append = true)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val buf = scp.requiredArg<ObjBuffer>(0)
|
||||
self.secured.writeBytes(self.path, buf.byteArray.asByteArray(), append = true)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// readUtf8(): String
|
||||
addFnDoc(
|
||||
name = "readUtf8",
|
||||
doc = "Read the file as a UTF-8 string.",
|
||||
returns = type("lyng.String"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
self.secured.readUtf8(self.path).toObj()
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
self.secured.readUtf8(self.path).toObj()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// writeUtf8(text: String)
|
||||
addFnDoc(
|
||||
name = "writeUtf8",
|
||||
doc = "Write a UTF-8 string to the file, replacing content.",
|
||||
params = listOf(ParamDoc("text", type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val text = requireOnlyArg<ObjString>().value
|
||||
self.secured.writeUtf8(self.path, text, append = false)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val text = scp.requireOnlyArg<ObjString>().value
|
||||
self.secured.writeUtf8(self.path, text, append = false)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// appendUtf8(text: String)
|
||||
addFnDoc(
|
||||
name = "appendUtf8",
|
||||
doc = "Append UTF-8 text to the end of the file.",
|
||||
params = listOf(ParamDoc("text", type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val text = requireOnlyArg<ObjString>().value
|
||||
self.secured.writeUtf8(self.path, text, append = true)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val text = scp.requireOnlyArg<ObjString>().value
|
||||
self.secured.writeUtf8(self.path, text, append = true)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// metadata(): Map
|
||||
addFnDoc(
|
||||
name = "metadata",
|
||||
doc = "Fetch cached metadata as a map of fields: `isFile`, `isDirectory`, `size`, `createdAtMillis`, `modifiedAtMillis`, `isSymlink`.",
|
||||
returns = TypeGenericDoc(type("lyng.Map"), listOf(type("lyng.String"), type("lyng.Any"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val m = self.secured.metadata(self.path)
|
||||
ObjMap(mutableMapOf(
|
||||
ObjString("isFile") to ObjBool(m.isRegularFile),
|
||||
ObjString("isDirectory") to ObjBool(m.isDirectory),
|
||||
ObjString("size") to (m.size?.toLong() ?: 0L).toObj(),
|
||||
ObjString("createdAtMillis") to ((m.createdAtMillis ?: 0L)).toObj(),
|
||||
ObjString("modifiedAtMillis") to ((m.modifiedAtMillis ?: 0L)).toObj(),
|
||||
ObjString("isSymlink") to ObjBool(m.isSymlink),
|
||||
))
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val m = self.secured.metadata(self.path)
|
||||
ObjMap(mutableMapOf(
|
||||
ObjString("isFile") to ObjBool(m.isRegularFile),
|
||||
ObjString("isDirectory") to ObjBool(m.isDirectory),
|
||||
ObjString("size") to (m.size?.toLong() ?: 0L).toObj(),
|
||||
ObjString("createdAtMillis") to ((m.createdAtMillis ?: 0L)).toObj(),
|
||||
ObjString("modifiedAtMillis") to ((m.modifiedAtMillis ?: 0L)).toObj(),
|
||||
ObjString("isSymlink") to ObjBool(m.isSymlink),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// mkdirs(mustCreate: Bool=false)
|
||||
addFnDoc(
|
||||
name = "mkdirs",
|
||||
doc = "Create directories (like `mkdir -p`). If `mustCreate` is true and the path already exists, the call fails. Otherwise it is a no‑op when the directory exists.",
|
||||
params = listOf(ParamDoc("mustCreate", type("lyng.Bool"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val mustCreate = args.list.getOrNull(0)?.toBool() ?: false
|
||||
self.secured.createDirectories(self.path, mustCreate)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val mustCreate = scp.args.list.getOrNull(0)?.toBool() ?: false
|
||||
self.secured.createDirectories(self.path, mustCreate)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// move(to: Path|String, overwrite: Bool=false)
|
||||
addFnDoc(
|
||||
name = "move",
|
||||
doc = "Move this path to a new location. `to` may be a `Path` or `String`. When `overwrite` is false and the target exists, the operation fails (provider may throw `AccessDeniedException`).",
|
||||
// types vary; keep generic description in doc
|
||||
params = listOf(ParamDoc("to"), ParamDoc("overwrite", type("lyng.Bool"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val toPath = parsePathArg(this, self, requiredArg<Obj>(0))
|
||||
val overwrite = args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.move(self.path, toPath, overwrite)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val toPath = parsePathArg(scp, self, scp.requiredArg<Obj>(0))
|
||||
val overwrite = scp.args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.move(self.path, toPath, overwrite)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// delete(mustExist: Bool=false, recursively: Bool=false)
|
||||
addFnDoc(
|
||||
name = "delete",
|
||||
doc = "Delete this path. `mustExist=true` causes failure if the path does not exist. `recursively=true` removes directories with their contents. Providers can throw `AccessDeniedException` on policy violations.",
|
||||
params = listOf(ParamDoc("mustExist", type("lyng.Bool")), ParamDoc("recursively", type("lyng.Bool"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val mustExist = args.list.getOrNull(0)?.toBool() ?: false
|
||||
val recursively = args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.delete(self.path, mustExist, recursively)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val mustExist = scp.args.list.getOrNull(0)?.toBool() ?: false
|
||||
val recursively = scp.args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.delete(self.path, mustExist, recursively)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// copy(to: Path|String, overwrite: Bool=false)
|
||||
addFnDoc(
|
||||
name = "copy",
|
||||
doc = "Copy this path to a new location. `to` may be a `Path` or `String`. When `overwrite` is false and the target exists, the operation fails (provider may throw `AccessDeniedException`).",
|
||||
params = listOf(ParamDoc("to"), ParamDoc("overwrite", type("lyng.Bool"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val toPath = parsePathArg(this, self, requiredArg<Obj>(0))
|
||||
val overwrite = args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.copy(self.path, toPath, overwrite)
|
||||
ObjVoid
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val toPath = parsePathArg(scp, self, scp.requiredArg<Obj>(0))
|
||||
val overwrite = scp.args.list.getOrNull(1)?.toBool() ?: false
|
||||
self.secured.copy(self.path, toPath, overwrite)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
// glob(pattern: String): List<Path>
|
||||
addFnDoc(
|
||||
name = "glob",
|
||||
doc = "List entries matching a glob pattern (no recursion).",
|
||||
params = listOf(ParamDoc("pattern", type("lyng.String"))),
|
||||
returns = TypeGenericDoc(type("lyng.List"), listOf(type("Path"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val pattern = requireOnlyArg<ObjString>().value
|
||||
val matches = self.secured.glob(self.path, pattern)
|
||||
ObjList(matches.map { ObjPath(self.objClass, self.secured, it) }.toMutableList())
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val pattern = scp.requireOnlyArg<ObjString>().value
|
||||
val matches = self.secured.glob(self.path, pattern)
|
||||
ObjList(matches.map { ObjPath(self.objClass, self.secured, it) }.toMutableList())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// --- streaming readers (initial version: chunk from whole content, API stable) ---
|
||||
|
||||
@@ -403,15 +479,18 @@ private suspend fun buildFsModule(module: ModuleScope, policy: FsAccessPolicy) {
|
||||
doc = "Read file in fixed-size chunks as an iterator of `Buffer`.",
|
||||
params = listOf(ParamDoc("size", type("lyng.Int"))),
|
||||
returns = TypeGenericDoc(type("lyng.Iterator"), listOf(type("lyng.Buffer"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val size = args.list.getOrNull(0)?.toInt() ?: 65536
|
||||
val bytes = self.secured.readBytes(self.path)
|
||||
ObjFsBytesIterator(bytes, size)
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val size = scp.args.list.getOrNull(0)?.toInt() ?: 65536
|
||||
val bytes = self.secured.readBytes(self.path)
|
||||
ObjFsBytesIterator(bytes, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// readUtf8Chunks(size: Int = 65536) -> Iterator<String>
|
||||
addFnDoc(
|
||||
@@ -419,28 +498,34 @@ private suspend fun buildFsModule(module: ModuleScope, policy: FsAccessPolicy) {
|
||||
doc = "Read UTF-8 text in fixed-size chunks as an iterator of `String`.",
|
||||
params = listOf(ParamDoc("size", type("lyng.Int"))),
|
||||
returns = TypeGenericDoc(type("lyng.Iterator"), listOf(type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val self = this.thisObj as ObjPath
|
||||
val size = args.list.getOrNull(0)?.toInt() ?: 65536
|
||||
val text = self.secured.readUtf8(self.path)
|
||||
ObjFsStringChunksIterator(text, size)
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val self = scp.thisObj as ObjPath
|
||||
val size = scp.args.list.getOrNull(0)?.toInt() ?: 65536
|
||||
val text = self.secured.readUtf8(self.path)
|
||||
ObjFsStringChunksIterator(text, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// lines() -> Iterator<String>, implemented via readUtf8Chunks
|
||||
addFnDoc(
|
||||
name = "lines",
|
||||
doc = "Iterate lines of the file as `String` values.",
|
||||
returns = TypeGenericDoc(type("lyng.Iterator"), listOf(type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
fsGuard {
|
||||
val chunkIt = thisObj.invokeInstanceMethod(this, "readUtf8Chunks")
|
||||
ObjFsLinesIterator(chunkIt)
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.fsGuard {
|
||||
val chunkIt = scp.thisObj.invokeInstanceMethod(scp, "readUtf8Chunks")
|
||||
ObjFsLinesIterator(chunkIt)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Export into the module scope with docs
|
||||
@@ -518,39 +603,51 @@ class ObjFsBytesIterator(
|
||||
name = "iterator",
|
||||
doc = "Return this iterator instance (enables `for` loops).",
|
||||
returns = type("BytesIterator"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) { thisObj }
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = scp.thisObj
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "hasNext",
|
||||
doc = "Whether there is another chunk available.",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsBytesIterator>()
|
||||
(self.pos < self.data.size).toObj()
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsBytesIterator>()
|
||||
return (self.pos < self.data.size).toObj()
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "next",
|
||||
doc = "Return the next chunk as a `Buffer`.",
|
||||
returns = type("lyng.Buffer"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsBytesIterator>()
|
||||
if (self.pos >= self.data.size) raiseIllegalState("iterator exhausted")
|
||||
val end = minOf(self.pos + self.chunkSize, self.data.size)
|
||||
val chunk = self.data.copyOfRange(self.pos, end)
|
||||
self.pos = end
|
||||
ObjBuffer(chunk.asUByteArray())
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsBytesIterator>()
|
||||
if (self.pos >= self.data.size) scp.raiseIllegalState("iterator exhausted")
|
||||
val end = minOf(self.pos + self.chunkSize, self.data.size)
|
||||
val chunk = self.data.copyOfRange(self.pos, end)
|
||||
self.pos = end
|
||||
return ObjBuffer(chunk.asUByteArray())
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "cancelIteration",
|
||||
doc = "Stop the iteration early; subsequent `hasNext` returns false.",
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsBytesIterator>()
|
||||
self.pos = self.data.size
|
||||
ObjVoid
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsBytesIterator>()
|
||||
self.pos = self.data.size
|
||||
return ObjVoid
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -573,35 +670,47 @@ class ObjFsStringChunksIterator(
|
||||
name = "iterator",
|
||||
doc = "Return this iterator instance (enables `for` loops).",
|
||||
returns = type("StringChunksIterator"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) { thisObj }
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = scp.thisObj
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "hasNext",
|
||||
doc = "Whether there is another chunk available.",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsStringChunksIterator>()
|
||||
(self.pos < self.text.length).toObj()
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsStringChunksIterator>()
|
||||
return (self.pos < self.text.length).toObj()
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "next",
|
||||
doc = "Return the next UTF-8 chunk as a `String`.",
|
||||
returns = type("lyng.String"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsStringChunksIterator>()
|
||||
if (self.pos >= self.text.length) raiseIllegalState("iterator exhausted")
|
||||
val end = minOf(self.pos + self.chunkChars, self.text.length)
|
||||
val chunk = self.text.substring(self.pos, end)
|
||||
self.pos = end
|
||||
ObjString(chunk)
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsStringChunksIterator>()
|
||||
if (self.pos >= self.text.length) scp.raiseIllegalState("iterator exhausted")
|
||||
val end = minOf(self.pos + self.chunkChars, self.text.length)
|
||||
val chunk = self.text.substring(self.pos, end)
|
||||
self.pos = end
|
||||
return ObjString(chunk)
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "cancelIteration",
|
||||
doc = "Stop the iteration early; subsequent `hasNext` returns false.",
|
||||
moduleName = "lyng.io.fs"
|
||||
) { ObjVoid }
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = ObjVoid
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -624,46 +733,58 @@ class ObjFsLinesIterator(
|
||||
name = "iterator",
|
||||
doc = "Return this iterator instance (enables `for` loops).",
|
||||
returns = type("LinesIterator"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) { thisObj }
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = scp.thisObj
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "hasNext",
|
||||
doc = "Whether another line is available.",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsLinesIterator>()
|
||||
self.ensureBufferFilled(this)
|
||||
(self.buffer.isNotEmpty() || !self.exhausted).toObj()
|
||||
}
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsLinesIterator>()
|
||||
self.ensureBufferFilled(scp)
|
||||
return (self.buffer.isNotEmpty() || !self.exhausted).toObj()
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "next",
|
||||
doc = "Return the next line as `String`.",
|
||||
returns = type("lyng.String"),
|
||||
moduleName = "lyng.io.fs"
|
||||
) {
|
||||
val self = thisAs<ObjFsLinesIterator>()
|
||||
self.ensureBufferFilled(this)
|
||||
if (self.buffer.isEmpty() && self.exhausted) raiseIllegalState("iterator exhausted")
|
||||
val idx = self.buffer.indexOf('\n')
|
||||
val line = if (idx >= 0) {
|
||||
val l = self.buffer.substring(0, idx)
|
||||
self.buffer = self.buffer.substring(idx + 1)
|
||||
l
|
||||
} else {
|
||||
// last line without trailing newline
|
||||
val l = self.buffer
|
||||
self.buffer = ""
|
||||
self.exhausted = true
|
||||
l
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjFsLinesIterator>()
|
||||
self.ensureBufferFilled(scp)
|
||||
if (self.buffer.isEmpty() && self.exhausted) scp.raiseIllegalState("iterator exhausted")
|
||||
val idx = self.buffer.indexOf('\n')
|
||||
val line = if (idx >= 0) {
|
||||
val l = self.buffer.substring(0, idx)
|
||||
self.buffer = self.buffer.substring(idx + 1)
|
||||
l
|
||||
} else {
|
||||
// last line without trailing newline
|
||||
val l = self.buffer
|
||||
self.buffer = ""
|
||||
self.exhausted = true
|
||||
l
|
||||
}
|
||||
return ObjString(line)
|
||||
}
|
||||
}
|
||||
ObjString(line)
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "cancelIteration",
|
||||
doc = "Stop the iteration early; subsequent `hasNext` returns false.",
|
||||
moduleName = "lyng.io.fs"
|
||||
) { ObjVoid }
|
||||
moduleName = "lyng.io.fs",
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = ObjVoid
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ package net.sergeych.lyng.io.process
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import net.sergeych.lyng.ModuleScope
|
||||
import net.sergeych.lyng.Scope
|
||||
import net.sergeych.lyng.ScopeCallable
|
||||
import net.sergeych.lyng.miniast.*
|
||||
import net.sergeych.lyng.obj.*
|
||||
import net.sergeych.lyng.pacman.ImportManager
|
||||
import net.sergeych.lyng.pacman.ModuleBuilder
|
||||
import net.sergeych.lyng.statement
|
||||
import net.sergeych.lyngio.process.*
|
||||
import net.sergeych.lyngio.process.security.ProcessAccessDeniedException
|
||||
@@ -39,9 +41,11 @@ fun createProcessModule(policy: ProcessAccessPolicy, manager: ImportManager): Bo
|
||||
val name = "lyng.io.process"
|
||||
if (manager.packageNames.contains(name)) return false
|
||||
|
||||
manager.addPackage(name) { module ->
|
||||
buildProcessModule(module, policy)
|
||||
}
|
||||
manager.addPackage(name, object : ModuleBuilder {
|
||||
override suspend fun build(module: ModuleScope) {
|
||||
buildProcessModule(module, policy)
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -59,59 +63,74 @@ private suspend fun buildProcessModule(module: ModuleScope, policy: ProcessAcces
|
||||
name = "stdout",
|
||||
doc = "Get standard output stream as a Flow of lines.",
|
||||
returns = type("lyng.Flow"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val self = thisAs<ObjRunningProcess>()
|
||||
self.process.stdout.toLyngFlow(this)
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjRunningProcess>()
|
||||
return self.process.stdout.toLyngFlow(scp)
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "stderr",
|
||||
doc = "Get standard error stream as a Flow of lines.",
|
||||
returns = type("lyng.Flow"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val self = thisAs<ObjRunningProcess>()
|
||||
self.process.stderr.toLyngFlow(this)
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val self = scp.thisAs<ObjRunningProcess>()
|
||||
return self.process.stderr.toLyngFlow(scp)
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "signal",
|
||||
doc = "Send a signal to the process (e.g. 'SIGINT', 'SIGTERM', 'SIGKILL').",
|
||||
params = listOf(ParamDoc("signal", type("lyng.String"))),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
processGuard {
|
||||
val sigStr = requireOnlyArg<ObjString>().value.uppercase()
|
||||
val sig = try {
|
||||
ProcessSignal.valueOf(sigStr)
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
ProcessSignal.valueOf("SIG$sigStr")
|
||||
} catch (e2: Exception) {
|
||||
raiseIllegalArgument("Unknown signal: $sigStr")
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.processGuard {
|
||||
val sigStr = scp.requireOnlyArg<ObjString>().value.uppercase()
|
||||
val sig = try {
|
||||
ProcessSignal.valueOf(sigStr)
|
||||
} catch (e: Exception) {
|
||||
try {
|
||||
ProcessSignal.valueOf("SIG$sigStr")
|
||||
} catch (e2: Exception) {
|
||||
scp.raiseIllegalArgument("Unknown signal: $sigStr")
|
||||
}
|
||||
}
|
||||
scp.thisAs<ObjRunningProcess>().process.sendSignal(sig)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
thisAs<ObjRunningProcess>().process.sendSignal(sig)
|
||||
ObjVoid
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "waitFor",
|
||||
doc = "Wait for the process to exit and return its exit code.",
|
||||
returns = type("lyng.Int"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
processGuard {
|
||||
thisAs<ObjRunningProcess>().process.waitFor().toObj()
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
return scp.processGuard {
|
||||
scp.thisAs<ObjRunningProcess>().process.waitFor().toObj()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
addFnDoc(
|
||||
name = "destroy",
|
||||
doc = "Forcefully terminate the process.",
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
thisAs<ObjRunningProcess>().process.destroy()
|
||||
ObjVoid
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
scp.thisAs<ObjRunningProcess>().process.destroy()
|
||||
return ObjVoid
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val processType = object : ObjClass("Process") {}
|
||||
@@ -122,30 +141,36 @@ private suspend fun buildProcessModule(module: ModuleScope, policy: ProcessAcces
|
||||
doc = "Execute a process with arguments.",
|
||||
params = listOf(ParamDoc("executable", type("lyng.String")), ParamDoc("args", type("lyng.List"))),
|
||||
returns = type("RunningProcess"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
if (runner == null) raiseError("Processes are not supported on this platform")
|
||||
processGuard {
|
||||
val executable = requiredArg<ObjString>(0).value
|
||||
val args = requiredArg<ObjList>(1).list.map { it.toString() }
|
||||
val lp = runner.execute(executable, args)
|
||||
ObjRunningProcess(runningProcessType, lp)
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
if (runner == null) scp.raiseError("Processes are not supported on this platform")
|
||||
return scp.processGuard {
|
||||
val executable = scp.requiredArg<ObjString>(0).value
|
||||
val args = scp.requiredArg<ObjList>(1).list.map { it.toString() }
|
||||
val lp = runner.execute(executable, args)
|
||||
ObjRunningProcess(runningProcessType, lp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
addClassFnDoc(
|
||||
name = "shell",
|
||||
doc = "Execute a command via system shell.",
|
||||
params = listOf(ParamDoc("command", type("lyng.String"))),
|
||||
returns = type("RunningProcess"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
if (runner == null) raiseError("Processes are not supported on this platform")
|
||||
processGuard {
|
||||
val command = requireOnlyArg<ObjString>().value
|
||||
val lp = runner.shell(command)
|
||||
ObjRunningProcess(runningProcessType, lp)
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
if (runner == null) scp.raiseError("Processes are not supported on this platform")
|
||||
return scp.processGuard {
|
||||
val command = scp.requireOnlyArg<ObjString>().value
|
||||
val lp = runner.shell(command)
|
||||
ObjRunningProcess(runningProcessType, lp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val platformType = object : ObjClass("Platform") {}
|
||||
@@ -155,24 +180,28 @@ private suspend fun buildProcessModule(module: ModuleScope, policy: ProcessAcces
|
||||
name = "details",
|
||||
doc = "Get platform core details.",
|
||||
returns = type("lyng.Map"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
val d = getPlatformDetails()
|
||||
ObjMap(mutableMapOf(
|
||||
ObjString("name") to ObjString(d.name),
|
||||
ObjString("version") to ObjString(d.version),
|
||||
ObjString("arch") to ObjString(d.arch),
|
||||
ObjString("kernelVersion") to (d.kernelVersion?.toObj() ?: ObjNull)
|
||||
))
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val d = getPlatformDetails()
|
||||
return ObjMap(mutableMapOf(
|
||||
ObjString("name") to ObjString(d.name),
|
||||
ObjString("version") to ObjString(d.version),
|
||||
ObjString("arch") to ObjString(d.arch),
|
||||
ObjString("kernelVersion") to (d.kernelVersion?.toObj() ?: ObjNull)
|
||||
))
|
||||
}
|
||||
}
|
||||
)
|
||||
addClassFnDoc(
|
||||
name = "isSupported",
|
||||
doc = "Check if processes are supported on this platform.",
|
||||
returns = type("lyng.Bool"),
|
||||
moduleName = module.packageName
|
||||
) {
|
||||
isProcessSupported().toObj()
|
||||
}
|
||||
moduleName = module.packageName,
|
||||
code = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj = isProcessSupported().toObj()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
module.addConstDoc(
|
||||
@@ -216,19 +245,21 @@ private suspend inline fun Scope.processGuard(crossinline block: suspend () -> O
|
||||
}
|
||||
|
||||
private fun Flow<String>.toLyngFlow(flowScope: Scope): ObjFlow {
|
||||
val producer = statement {
|
||||
val builder = (this as? net.sergeych.lyng.ClosureScope)?.callScope?.thisObj as? ObjFlowBuilder
|
||||
?: this.thisObj as? ObjFlowBuilder
|
||||
val producer = statement(f = object : ScopeCallable {
|
||||
override suspend fun call(scp: Scope): Obj {
|
||||
val builder = (scp as? net.sergeych.lyng.ClosureScope)?.callScope?.thisObj as? ObjFlowBuilder
|
||||
?: scp.thisObj as? ObjFlowBuilder
|
||||
|
||||
this@toLyngFlow.collect {
|
||||
try {
|
||||
builder?.output?.send(ObjString(it))
|
||||
} catch (e: Exception) {
|
||||
// Channel closed or other error, stop collecting
|
||||
return@collect
|
||||
this@toLyngFlow.collect {
|
||||
try {
|
||||
builder?.output?.send(ObjString(it))
|
||||
} catch (e: Exception) {
|
||||
// Channel closed or other error, stop collecting
|
||||
return@collect
|
||||
}
|
||||
}
|
||||
return ObjVoid
|
||||
}
|
||||
ObjVoid
|
||||
}
|
||||
})
|
||||
return ObjFlow(producer, flowScope)
|
||||
}
|
||||
Reference in new issue
Block a user