Skip to content

Commit

Permalink
We is 20% faster on some programs
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Dec 1, 2023
1 parent f58ed1c commit 6df4d25
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class Compiler private constructor(
if (op.op == UnOp.NOT) {
+Insn.Not
} else {
generateMetaCall(op.op.metamethod!!, 0)
+Insn.MetaCall(0, op.op.metamethod!!)
}
}

Expand All @@ -259,7 +259,7 @@ class Compiler private constructor(

private fun compileErrorLiteral(error: AstNode.ErrorLiteral) = buildInsns(error.span) {
+compileExpression(error.message)
generateMetaCall("__str__", 0)
+Insn.MetaCall(0, "__str__")
if (error.companionData != null) {
+compileExpression(error.companionData)
} else {
Expand All @@ -283,7 +283,7 @@ class Compiler private constructor(

private fun compileFor(statement: AstNode.For) = buildInsns(statement.span) {
+compileExpression(statement.iterable)
generateMetaCall("__iter__", 0)
+Insn.MetaCall(0, "__iter__")
localStack.addFirst(Local("", scope, localStack.size))
val start = Insn.Label()
val end = Insn.Label()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,6 @@ class InsnsBuilder(val span: Span) {
}
}

/**
* Generates a call to a metamethod.
*
* @param name The name of the metamethod.
* @param nargs The number of arguments to the metamethod.
*/
fun InsnsBuilder.generateMetaCall(name: String, nargs: Int) {
+Insn.CopyUnder(nargs)
+Insn.Push("metatable")
+Insn.Index
+Insn.Push(name)
+Insn.Index
+Insn.Call(nargs + 1, true)
}

/**
* Utility function for building instructions.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List<FullInsn>, List<F
IN({ left, right ->
+right
+left
generateMetaCall("__contains__", 1)
+Insn.MetaCall(1, "__contains__")
}),
NOT_IN(IN),
IS({ left, right ->
Expand Down Expand Up @@ -56,7 +56,7 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List<FullInsn>, List<F
+left
+Insn.Push(Value.Null)
+Insn.CopyUnder(1)
generateMetaCall("__eq__", 1)
+Insn.MetaCall(1, "__eq__")
val end = Insn.Label()
+Insn.RawJumpIf(end, condition = false)
+Insn.Pop
Expand All @@ -67,7 +67,7 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List<FullInsn>, List<F
constructor(metamethod: String) : this({ left, right ->
+left
+right
generateMetaCall(metamethod, 1)
+Insn.MetaCall(1, metamethod)
})

constructor(op: BinOp) : this({ left, right ->
Expand All @@ -78,7 +78,7 @@ enum class BinOp(internal val generateCode: InsnsBuilder.(List<FullInsn>, List<F
constructor(number: Int, inverse: Boolean = false) : this({ left, right ->
+left
+right
generateMetaCall("__cmp__", 1)
+Insn.MetaCall(1, "__cmp__")
+Insn.Push(number)
+Insn.CopyUnder(1)
+Insn.Push("__eq__")
Expand Down
23 changes: 23 additions & 0 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 @@ -376,6 +376,29 @@ class State(parentState: State? = null) {
}
}

/**
* Performs a metamethod call on the value [nargs] below the top of the stack.
*
* @param nargs The number of arguments to pass to the metamethod.
* @param metamethod The name of the metamethod to call.
* @param span The span of the call. May be null if unknown.
*/
fun metaCall(nargs: Int, metamethod: String, span: Span? = null) {
val value = stack.getFromTop(nargs)
val meta = value.metatable?.lookUp(metamethod.metisValue())
if (meta is CallableValue) {
callValue(meta, nargs + 1, true, span)
} else {
throw MetisRuntimeException(
"TypeError",
"Cannot call metamethod $metamethod on value of type ${typeToName(value::class)}",
buildTable { table ->
table["value"] = value
}
)
}
}

private fun callValue(value: CallableValue, nargs: Int, selfProvided: Boolean, span: Span? = null) {
val stackBottom = stack.size - nargs
val (reqArgs, requiresSelf) = value.arity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class Chunk(
is Insn.PushFinally -> finallyStack.push(insn.label)
is Insn.CopyUnder -> state.stack.push(state.stack.getFromTop(insn.index))
is Insn.Call -> state.call(insn.nargs, insn.selfProvided, spans[ip - 1])
is Insn.MetaCall -> state.metaCall(insn.nargs, insn.metamethod, spans[ip - 1])
is Insn.ToBeUsed -> toBeUsed = state.stack.pop()
is Insn.Return -> {
ip = insns.size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ sealed interface Insn {
data object Index : Insn
data object Set : Insn
data class Call(val nargs: Int, val selfProvided: Boolean) : Insn
data class MetaCall(val nargs: Int, val metamethod: String) : Insn

/**
* Used to mark a value as being used, so that it doesn't get popped. Used in the implementations of
Expand Down

0 comments on commit 6df4d25

Please sign in to comment.