mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
tweaks
This commit is contained in:
parent
2f48406aad
commit
0137478ad4
@ -2,6 +2,7 @@
|
||||
|
||||
PROG8_LIBDIR=../prog8lib
|
||||
PROG8CLASSPATH=out/production/compiler
|
||||
LIBJARS=/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-stdlib.jar:/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
|
||||
KOTLINPATH=${HOME}/.IntelliJIdea2018.2/config/plugins/Kotlin
|
||||
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
|
||||
|
||||
java -Dprog8.libdir=${PROG8_LIBDIR} -cp ${PROG8CLASSPATH}:${LIBJARS} prog8.MainKt $*
|
||||
java -Dprog8.libdir=${PROG8_LIBDIR} -cp ${PROG8CLASSPATH}:${LIBJARS} prog8.CompilerMainKt $*
|
||||
|
9
compiler/src/compile.sh
Normal file → Executable file
9
compiler/src/compile.sh
Normal file → Executable file
@ -1,5 +1,8 @@
|
||||
#!/bin/sh
|
||||
#!/usr/bin/env bash
|
||||
mkdir -p compiled_java
|
||||
javac -d compiled_java -cp ../antlr/lib/antlr-runtime-4.7.1.jar $(find . -name \*.java)
|
||||
javac -verbose -d compiled_java -cp ../antlr/lib/antlr-runtime-4.7.1.jar $(find . -name \*.java)
|
||||
jar cf parser.jar -C compiled_java prog8
|
||||
kotlinc -d prog8_kotlin.jar -include-runtime -cp ../antlr/lib/antlr-runtime-4.7.1.jar:parser.jar prog8
|
||||
|
||||
KOTLINC="bash ${HOME}/.IntelliJIdea2018.2/config/plugins/Kotlin/kotlinc/bin/kotlinc"
|
||||
|
||||
${KOTLINC} -verbose -include-runtime -d prog8_kotlin.jar -cp ../antlr/lib/antlr-runtime-4.7.1.jar:parser.jar prog8
|
||||
|
41
compiler/src/prog8/StackVmMain.kt
Normal file
41
compiler/src/prog8/StackVmMain.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package prog8
|
||||
|
||||
import prog8.stackvm.*
|
||||
import java.awt.EventQueue
|
||||
import javax.swing.Timer
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("\nProg8 StackVM by Irmen de Jong (irmen@razorvine.net)")
|
||||
// @todo software license string
|
||||
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
||||
println("**** This is a prerelease version. Please do not distribute! ****\n")
|
||||
|
||||
if(args.size != 1) {
|
||||
System.err.println("requires one argument: name of stackvm sourcecode file")
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val program = Program.load(args.first())
|
||||
val vm = StackVm(traceOutputFile = null)
|
||||
val dialog = ScreenDialog()
|
||||
vm.load(program, dialog.canvas)
|
||||
EventQueue.invokeLater {
|
||||
dialog.pack()
|
||||
dialog.isVisible = true
|
||||
dialog.start()
|
||||
|
||||
val programTimer = Timer(10) { a ->
|
||||
try {
|
||||
vm.step()
|
||||
} catch(bp: VmBreakpointException) {
|
||||
println("Breakpoint: execution halted. Press enter to resume.")
|
||||
readLine()
|
||||
} catch (tx: VmTerminationException) {
|
||||
println("Execution halted: ${tx.message}")
|
||||
(a.source as Timer).stop()
|
||||
}
|
||||
}
|
||||
programTimer.start()
|
||||
}
|
||||
}
|
@ -4,17 +4,54 @@ import prog8.ast.IAstProcessor
|
||||
import prog8.ast.INameScope
|
||||
|
||||
/*
|
||||
todo eliminate useless terms:
|
||||
*0 -> constant 0
|
||||
X*1, X/1, X//1 -> just X
|
||||
todo simplify expression terms:
|
||||
X*0 -> 0
|
||||
X*1 -> X
|
||||
X*2 -> X << 1
|
||||
X*3 -> X + (X << 1)
|
||||
X*4 -> X << 2
|
||||
X*5 -> X + (X << 2)
|
||||
X*6 -> (X<<1) + (X << 2)
|
||||
X*7 -> X + (X<<1) + (X << 2)
|
||||
X*8 -> X << 3
|
||||
X*9 -> X + (X<<3)
|
||||
X*10 -> (X<<1) + (X<<3)
|
||||
|
||||
X/1, X//1, X**1 -> just X
|
||||
X/2, X//2 -> X >> 1 (if X is byte or word)
|
||||
X/4, X//4 -> X >> 2 (if X is byte or word)
|
||||
X/8, X//8 -> X >> 3 (if X is byte or word)
|
||||
X/16, X//16 -> X >> 4 (if X is byte or word)
|
||||
X/32, X//32 -> X >> 5 (if X is byte or word)
|
||||
X/64, X//64 -> X >> 6 (if X is byte or word)
|
||||
X/128, X//128 -> X >> 7 (if X is byte or word)
|
||||
X / (n>=256) -> 0 (if x is byte) X >> 8 (if X is word)
|
||||
X // (n>=256) -> 0 (if x is byte) X >> 8 (if X is word)
|
||||
|
||||
X+X -> X << 1
|
||||
X << n << m -> X << (n+m)
|
||||
|
||||
1**X -> 1
|
||||
0**X -> 0
|
||||
X*-1 -> unary prefix -X
|
||||
X**0 -> 1
|
||||
X**1 -> X
|
||||
X**2 -> X*X
|
||||
X**3 -> X*X*X
|
||||
X**0.5 -> sqrt(X)
|
||||
X**-1 -> 1.0/X
|
||||
X**-2 -> 1.0/X/X
|
||||
X**-3 -> 1.0/X/X/X
|
||||
X << 0 -> X
|
||||
X | 0 -> X
|
||||
x & 0 -> 0
|
||||
X ^ 0 -> X
|
||||
X*Y - X -> X*(Y-1)
|
||||
-X + A -> A - X
|
||||
-X - A -> -(X+A)
|
||||
X % 1 -> constant 0 (if X is byte/word)
|
||||
X % 2 -> X and 255 (byte) X and 65535 (word)
|
||||
|
||||
|
||||
todo expression optimization: remove redundant builtin function calls
|
||||
todo expression optimization: reduce expression nesting / flattening of parenthesis
|
||||
|
@ -16,6 +16,8 @@ import prog8.functions.BuiltinFunctionsWithoutSideEffects
|
||||
todo analyse for unreachable code and remove that (f.i. code after goto or return that has no label so can never be jumped to)
|
||||
todo merge sequence of assignments into one (as long as the value is a constant and the target not a MEMORY type!)
|
||||
todo report more always true/always false conditions
|
||||
todo inline subroutines that are only called once
|
||||
todo inline subroutines that are "sufficiently small"
|
||||
*/
|
||||
|
||||
class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcessor {
|
||||
|
@ -3,14 +3,11 @@ package prog8.stackvm
|
||||
import prog8.ast.DataType
|
||||
import prog8.compiler.target.c64.Petscii
|
||||
import prog8.compiler.target.c64.Mflpt5
|
||||
import java.awt.EventQueue
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import javax.swing.Timer
|
||||
import kotlin.math.*
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
enum class Opcode {
|
||||
|
||||
@ -237,15 +234,11 @@ class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=
|
||||
init {
|
||||
when(type) {
|
||||
DataType.BYTE -> {
|
||||
byteval = numericvalue!!.toShort()
|
||||
if(byteval!! <0 || byteval!! > 255)
|
||||
throw VmExecutionException("byte value overflow: $byteval")
|
||||
byteval = (numericvalue!!.toInt() and 255).toShort() // byte wrap around 0..255
|
||||
asBooleanValue = byteval != (0.toShort())
|
||||
}
|
||||
DataType.WORD -> {
|
||||
wordval = numericvalue!!.toInt()
|
||||
if(wordval!! <0 || wordval!! > 65535)
|
||||
throw VmExecutionException("word value overflow: $wordval")
|
||||
wordval = numericvalue!!.toInt() and 65535 // word wrap around 0..65535
|
||||
asBooleanValue = wordval != 0
|
||||
}
|
||||
DataType.FLOAT -> {
|
||||
@ -362,17 +355,17 @@ class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=
|
||||
val v1 = numericValue()
|
||||
val v2 = other.numericValue()
|
||||
val result = v1.toDouble().pow(v2.toDouble())
|
||||
return Value(type, result) // @todo datatype?
|
||||
return Value(type, result) // @todo datatype of pow is now always float, maybe allow byte/word results as well
|
||||
}
|
||||
|
||||
fun shl(): Value {
|
||||
val v = integerValue()
|
||||
return Value(type, v.shl(1))
|
||||
return Value(type, v shl 1)
|
||||
}
|
||||
|
||||
fun shr(): Value {
|
||||
val v = integerValue()
|
||||
return Value(type, v.ushr(1))
|
||||
return Value(type, v ushr 1)
|
||||
}
|
||||
|
||||
fun rol(carry: Boolean): Pair<Value, Boolean> {
|
||||
@ -1493,39 +1486,3 @@ class StackVm(val traceOutputFile: String?) {
|
||||
return ins.next
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("\nProg8 StackVM by Irmen de Jong (irmen@razorvine.net)")
|
||||
// @todo software license string
|
||||
// println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n")
|
||||
println("**** This is a prerelease version. Please do not distribute! ****\n")
|
||||
|
||||
if(args.size != 1) {
|
||||
System.err.println("requires one argument: name of stackvm sourcecode file")
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
val program = Program.load(args.first())
|
||||
val vm = StackVm(traceOutputFile = null)
|
||||
val dialog = ScreenDialog()
|
||||
vm.load(program, dialog.canvas)
|
||||
EventQueue.invokeLater {
|
||||
dialog.pack()
|
||||
dialog.isVisible = true
|
||||
dialog.start()
|
||||
|
||||
val programTimer = Timer(10) { a ->
|
||||
try {
|
||||
vm.step()
|
||||
} catch(bp: VmBreakpointException) {
|
||||
println("Breakpoint: execution halted. Press enter to resume.")
|
||||
readLine()
|
||||
} catch (tx: VmTerminationException) {
|
||||
println("Execution halted: ${tx.message}")
|
||||
(a.source as Timer).stop()
|
||||
}
|
||||
}
|
||||
programTimer.start()
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
PROG8CLASSPATH=out/production/compiler
|
||||
LIBJARS=/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-stdlib.jar:/opt/irmen/idea-2018/plugins/Kotlin/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
|
||||
KOTLINPATH=${HOME}/.IntelliJIdea2018.2/config/plugins/Kotlin
|
||||
LIBJARS=${KOTLINPATH}/lib/kotlin-stdlib.jar:${KOTLINPATH}/lib/kotlin-reflect.jar:antlr/lib/antlr-runtime-4.7.1.jar
|
||||
|
||||
java -cp ${PROG8CLASSPATH}:${LIBJARS} prog8.stackvm.StackVmKt $*
|
||||
java -cp ${PROG8CLASSPATH}:${LIBJARS} prog8.StackVmMainKt $*
|
||||
|
@ -597,17 +597,16 @@ class TestStackVmOpcodes {
|
||||
Instruction(Opcode.NEG)
|
||||
)
|
||||
vm.load(makeProg(ins2), null)
|
||||
assertFailsWith<VmExecutionException> {
|
||||
vm.step(2)
|
||||
}
|
||||
vm.step(2)
|
||||
assertEquals(Value(DataType.WORD, 64302), vm.evalstack.pop())
|
||||
|
||||
val ins3 = mutableListOf(
|
||||
Instruction(Opcode.PUSH, Value(DataType.BYTE, 12)),
|
||||
Instruction(Opcode.NEG)
|
||||
)
|
||||
vm.load(makeProg(ins3), null)
|
||||
assertFailsWith<VmExecutionException> {
|
||||
vm.step(2)
|
||||
}
|
||||
vm.step(2)
|
||||
assertEquals(Value(DataType.BYTE, 244), vm.evalstack.pop())
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user