-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c2986e
commit 9679121
Showing
27 changed files
with
3,224 additions
and
398 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package eu.jameshamilton.klox.compile | ||
|
||
import eu.jameshamilton.klox.parse.FunctionStmt | ||
import eu.jameshamilton.klox.parse.FunctionType.* | ||
import eu.jameshamilton.klox.parse.Parameter | ||
import eu.jameshamilton.klox.parse.Token | ||
import eu.jameshamilton.klox.parse.TokenType.* | ||
import proguard.classfile.editor.CompactCodeAttributeComposer as Composer | ||
|
||
// Built-in Klox functions | ||
|
||
val builtIns = listOf( | ||
NativeFunctionStmt(Token(IDENTIFIER, "clock"), emptyList()) { | ||
invokestatic("java/lang/System", "currentTimeMillis", "()J") | ||
l2d() | ||
pushDouble(1000.0) | ||
ddiv() | ||
box("java/lang/Double") | ||
areturn() | ||
} | ||
) | ||
|
||
class NativeFunctionStmt(override val name: Token, override val params: List<Parameter>, val code: Composer.() -> Composer) : | ||
FunctionStmt(name, NATIVE, params, emptyList()) { | ||
|
||
override fun toString(): String = "<native fn>" | ||
} |
63 changes: 63 additions & 0 deletions
63
src/main/kotlin/eu/jameshamilton/klox/compile/ClassBuilderExt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package eu.jameshamilton.klox.compile | ||
|
||
import proguard.classfile.AccessConstants.PUBLIC | ||
import proguard.classfile.Method | ||
import proguard.classfile.ProgramClass | ||
import proguard.classfile.VersionConstants.CLASS_VERSION_1_6 | ||
import proguard.classfile.attribute.BootstrapMethodInfo | ||
import proguard.classfile.editor.BootstrapMethodsAttributeAdder | ||
import proguard.classfile.editor.ClassBuilder | ||
import proguard.classfile.editor.ConstantPoolEditor | ||
import proguard.classfile.editor.CompactCodeAttributeComposer as Composer | ||
|
||
private val EMPTY_CLASS: ProgramClass = ClassBuilder( | ||
CLASS_VERSION_1_6, | ||
PUBLIC, | ||
"EMPTY", | ||
"java/lang/Object" | ||
).programClass | ||
|
||
fun ClassBuilder.addMethod(u2accessFlags: Int, name: String, descriptor: String, composer: Composer.() -> Composer): ClassBuilder { | ||
// Inefficient, since the composition has to be done twice (first to compute the codeLength) but API is improved. | ||
// It also means that any code in the composer should not have side-effects, since it will be | ||
// executed twice! | ||
val countingComposer = composer(object : Composer(EMPTY_CLASS) { | ||
override fun label(label: Label): proguard.classfile.editor.CompactCodeAttributeComposer { | ||
// Adding a label without specifying a maxCodeFragmentSize would | ||
// normally throw an ArrayIndexOutOfBoundsException. | ||
// Since this first composer execution is only needed for | ||
// counting the size, it doesn't matter about adding labels. | ||
return this | ||
} | ||
}) | ||
|
||
return addMethod(u2accessFlags, name, descriptor, countingComposer.codeLength) { | ||
composer(it) | ||
} | ||
} | ||
|
||
inline fun <reified T : Method> ClassBuilder.addAndReturnMethod(u2accessFlags: Int, name: String, descriptor: String, noinline composer: Composer.() -> Composer): T { | ||
addMethod(u2accessFlags, name, descriptor, composer) | ||
return programClass.findMethod(name, descriptor) as T | ||
} | ||
|
||
// TODO how to get bootstrap method ID when needed? invokedynamic(0, "invoke") | ||
fun ClassBuilder.addBootstrapMethod(kind: Int, className: String, name: String, descriptor: String, arguments: (ConstantPoolEditor) -> Array<Int> = { emptyArray() }): ClassBuilder { | ||
val constantPoolEditor = ConstantPoolEditor(programClass) | ||
val bootstrapMethodsAttributeAdder = BootstrapMethodsAttributeAdder(programClass) | ||
|
||
val args = arguments(constantPoolEditor) | ||
|
||
val bootstrapMethodInfo = BootstrapMethodInfo( | ||
constantPoolEditor.addMethodHandleConstant( | ||
kind, | ||
constantPoolEditor.addMethodrefConstant(className, name, descriptor, null, null) | ||
), | ||
args.size, | ||
args.toIntArray() | ||
) | ||
|
||
bootstrapMethodsAttributeAdder.visitBootstrapMethodInfo(programClass, bootstrapMethodInfo) | ||
|
||
return this | ||
} |
5 changes: 5 additions & 0 deletions
5
src/main/kotlin/eu/jameshamilton/klox/compile/ClassPoolExt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package eu.jameshamilton.klox.compile | ||
|
||
import proguard.classfile.ClassPool | ||
|
||
fun ClassPool.contains(className: String) = this.getClass(className) != null |
Oops, something went wrong.