All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.skillw.asahi.internal.script.NativeFunctionImpl.kt Maven / Gradle / Ivy

There is a newer version: 1.6.7-beta-6
Show newest version
package com.skillw.asahi.internal.script

import com.skillw.asahi.api.AsahiAPI.compile
import com.skillw.asahi.api.member.context.AsahiContext
import com.skillw.asahi.api.script.AsahiCompiledScript
import com.skillw.asahi.api.script.linking.NativeFunction
import com.skillw.asahi.util.AsahiDataMap
import com.skillw.asahi.util.toLazyMap


/**
 * @className ScriptFunctionImpl
 *
 * @author Glom
 * @date 2022/12/28 21:24 Copyright 2022 user.
 */
class NativeFunctionImpl constructor(
    key: String,
    paramNames: Array,
    content: AsahiCompiledScript,
    initial: AsahiContext.() -> Unit = {},
) : NativeFunction(key, paramNames, content) {

    override val paramCount = paramNames.size
    private val initial: Map = AsahiContext.create().apply(initial)
    override fun invoke(context: AsahiContext, vararg params: Any?): Any? {
        if (params.size < paramCount) {
            throw IllegalArgumentException("Wrong params count! (${params.size} / $paramCount)")
        }
        val invokeContext = context.clone().apply {
            putAll(initial)
        }
        paramNames.forEachIndexed { index, name ->
            invokeContext[name] = params[index] ?: "null"
        }
        invokeContext.run {
            if (containsKey("args")) {
                put("super.args", get("args") ?: emptyArray())
            }
            put("args", params)
        }
        return invokeContext.run { content.run() }.also {
            invokeContext.forEach { key, value ->
                if (key == "super.args" || key == "args") return@forEach
                if (key.startsWith("@")) return@forEach
                if (key !in paramNames && context.containsKey(key) && !initial.containsKey(key)) context[key] = value
            }
        }
    }

    companion object {
        @JvmStatic
        fun create(
            key: String,
            paramNames: Array,
            content: AsahiCompiledScript,
            initial: AsahiContext.() -> Unit = {},
        ): NativeFunction {
            return NativeFunctionImpl(key, paramNames, content, initial)
        }

        @JvmStatic
        fun deserialize(key: String, content: String, vararg namespaces: String): NativeFunction {
            val script = content.compile(*namespaces)
            return NativeFunctionImpl(key, emptyArray(), script)
        }

        @JvmStatic
        fun deserialize(key: String, map: Map, vararg namespaces1: String): NativeFunction {
            val data = AsahiDataMap().apply { putAll(map) }
            val params = data.get("params", emptyList()).toTypedArray()
            val namespaces = data.get("namespaces", arrayListOf()).apply {
                addAll(namespaces1)
            }
            val import = data.get("import", emptyList()).toTypedArray()
            val context = data.get("context", emptyMap()).toLazyMap()
            val script = data.get("content", "print 'Not yet implemented'").compile(*namespaces.toTypedArray())
            return NativeFunctionImpl(key, params, script) {
                import(*import)
                putAll(context)
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy