Skip to content

Commit

Permalink
Rearrange a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Dec 16, 2023
1 parent ce0a53c commit bd957a8
Show file tree
Hide file tree
Showing 6 changed files with 249 additions and 257 deletions.
20 changes: 5 additions & 15 deletions metis-lang/src/main/kotlin/io/github/seggan/metis/runtime/State.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,6 @@ class State(parentState: State? = null) {
*/
var currentDir = fileSystem.getPath(System.getProperty("user.dir")).toAbsolutePath()

/**
* The function used to wrap [InputStream]s into Metis objects.
*/
var inStreamWrapper: InputStreamWrapper = InputStreamWrapper { Value.Native(it, inStreamMetatable) }

/**
* The function used to wrap [OutputStream]s into Metis objects.
*/
var outStreamWrapper: OutputStreamWrapper = OutputStreamWrapper { Value.Native(it, outStreamMetatable) }

internal val openUpvalues = ArrayDeque<Upvalue.Instance>()

private var throwingException: MetisRuntimeException? = null
Expand Down Expand Up @@ -144,12 +134,12 @@ class State(parentState: State? = null) {
}

val io = Value.Table()
io["stdout"] = zeroArgFunction { outStreamWrapper.wrap(stdout) }
io["stderr"] = zeroArgFunction { outStreamWrapper.wrap(stderr) }
io["stdin"] = zeroArgFunction { inStreamWrapper.wrap(stdin) }
io["stdout"] = zeroArgFunction { Value.Native(stdout, NativeObjects.OUTPUT_STREAM) }
io["stderr"] = zeroArgFunction { Value.Native(stderr, NativeObjects.OUTPUT_STREAM) }
io["stdin"] = zeroArgFunction { Value.Native(stdin, NativeObjects.INPUT_STREAM) }

io["inStream"] = inStreamMetatable
io["outStream"] = outStreamMetatable
io["inStream"] = NativeObjects.INPUT_STREAM
io["outStream"] = NativeObjects.OUTPUT_STREAM
globals["io"] = io

globals["string"] = Value.String.metatable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
@file:JvmName("IntrinsicFunctions")

package io.github.seggan.metis.runtime.intrinsics

import io.github.seggan.metis.runtime.*
import io.github.seggan.metis.runtime.chunk.StepResult
import io.github.seggan.metis.util.MutableLazy
import io.github.seggan.metis.util.pop
import io.github.seggan.metis.util.push
import java.io.FileNotFoundException
import java.io.IOException
import java.nio.file.InvalidPathException


/**
* A function that is guaranteed to finish in one step. Optimization for this is implemented.
*
* @param arity The arity of the function.
*/
abstract class OneShotFunction(override val arity: Arity) : CallableValue {

override var metatable: Value.Table? by MutableLazy {
Value.Table(mutableMapOf("__str__".metisValue() to oneArgFunction { "OneShot".metisValue() }))
}

final override fun call(nargs: Int): CallableValue.Executor = object : CallableValue.Executor {
override fun step(state: State): StepResult {
execute(state, nargs)
return StepResult.FINISHED
}
}

abstract fun execute(state: State, nargs: Int)
}

/**
* Creates a [OneShotFunction] with zero arguments.
*
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun zeroArgFunction(crossinline fn: State.() -> Value): OneShotFunction = object : OneShotFunction(Arity.ZERO) {
override fun execute(state: State, nargs: Int) {
state.stack.push(state.fn())
}
}

/**
* Creates a [OneShotFunction] with one argument.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun oneArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(1, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
state.stack.push(state.fn(state.stack.pop()))
}
}

/**
* Creates a [OneShotFunction] with two arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun twoArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(2, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b))
}
}

/**
* Creates a [OneShotFunction] with three arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun threeArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(3, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val c = state.stack.pop()
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b, c))
}
}

/**
* Creates a [OneShotFunction] with four arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun fourArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value, Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(4, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val d = state.stack.pop()
val c = state.stack.pop()
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b, c, d))
}
}

/**
* Translates an [IOException] into a [MetisRuntimeException].
*
* @param block The block to execute.
*/
inline fun <T> translateIoError(block: () -> T): T {
val message = try {
null to block()
} catch (e: InvalidPathException) {
"Invalid path: ${e.message}" to null
} catch (e: FileNotFoundException) {
"File not found: ${e.message}" to null
} catch (e: NoSuchFileException) {
"File not found: ${e.message}" to null
} catch (e: FileAlreadyExistsException) {
"File already exists: ${e.message}" to null
} catch (e: SecurityException) {
"Permission denied: ${e.message}" to null
} catch (e: IOException) {
e.message to null
}
if (message.first != null) {
throw MetisRuntimeException("IoError", message.first!!)
} else {
return message.second!!
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:JvmName("Intrinsics")

package io.github.seggan.metis.runtime.intrinsics

import io.github.seggan.metis.parsing.CodeSource
Expand Down Expand Up @@ -54,116 +56,4 @@ object Intrinsics {
}
}
}
}


/**
* A function that is guaranteed to finish in one step. Optimization for this is implemented.
*
* @param arity The arity of the function.
*/
abstract class OneShotFunction(override val arity: Arity) : CallableValue {

override var metatable: Value.Table? by MutableLazy {
Value.Table(mutableMapOf("__str__".metisValue() to oneArgFunction { "OneShot".metisValue() }))
}

final override fun call(nargs: Int): CallableValue.Executor = object : CallableValue.Executor {
override fun step(state: State): StepResult {
execute(state, nargs)
return StepResult.FINISHED
}
}

abstract fun execute(state: State, nargs: Int)
}

/**
* Creates a [OneShotFunction] with zero arguments.
*
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun zeroArgFunction(crossinline fn: State.() -> Value): OneShotFunction = object : OneShotFunction(Arity.ZERO) {
override fun execute(state: State, nargs: Int) {
state.stack.push(state.fn())
}
}

/**
* Creates a [OneShotFunction] with one argument.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun oneArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(1, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
state.stack.push(state.fn(state.stack.pop()))
}
}

/**
* Creates a [OneShotFunction] with two arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun twoArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(2, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b))
}
}

/**
* Creates a [OneShotFunction] with three arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun threeArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(3, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val c = state.stack.pop()
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b, c))
}
}

/**
* Creates a [OneShotFunction] with four arguments.
*
* @param requiresSelf Whether the function requires a `self` argument.
* @param fn The function to execute.
* @return The created function.
* @see OneShotFunction
*/
inline fun fourArgFunction(
requiresSelf: Boolean = false,
crossinline fn: State.(Value, Value, Value, Value) -> Value
): OneShotFunction = object : OneShotFunction(Arity(4, requiresSelf)) {
override fun execute(state: State, nargs: Int) {
val d = state.stack.pop()
val c = state.stack.pop()
val b = state.stack.pop()
val a = state.stack.pop()
state.stack.push(state.fn(a, b, c, d))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,8 @@ object PathLib : NativeLibrary("__path") {
lib["createDir"] = pathFunction { it.createDirectory().absolutePathString().metisValue() }
lib["createDirs"] = pathFunction { it.createDirectories().absolutePathString().metisValue() }
lib["deleteRecursive"] = pathFunction { it.deleteRecursively(); Value.Null }
lib["openWrite"] = pathFunction { outStreamWrapper.wrap(it.outputStream()) }
lib["openRead"] = pathFunction { inStreamWrapper.wrap(it.inputStream()) }
lib["openWrite"] = pathFunction { Value.Native(it.outputStream(), NativeObjects.OUTPUT_STREAM) }
lib["openRead"] = pathFunction { Value.Native(it.inputStream(), NativeObjects.INPUT_STREAM) }
}
}

Expand Down
Loading

0 comments on commit bd957a8

Please sign in to comment.