mirror of
https://github.com/irmen/prog8.git
synced 2024-09-08 10:55:08 +00:00
tweaks
This commit is contained in:
parent
2f48406aad
commit
0137478ad4
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
PROG8_LIBDIR=../prog8lib
|
PROG8_LIBDIR=../prog8lib
|
||||||
PROG8CLASSPATH=out/production/compiler
|
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
|
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
|
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
|
import prog8.ast.INameScope
|
||||||
|
|
||||||
/*
|
/*
|
||||||
todo eliminate useless terms:
|
todo simplify expression terms:
|
||||||
*0 -> constant 0
|
X*0 -> 0
|
||||||
X*1, X/1, X//1 -> just X
|
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*-1 -> unary prefix -X
|
||||||
X**0 -> 1
|
X**0 -> 1
|
||||||
X**1 -> X
|
X**1 -> X
|
||||||
|
X**2 -> X*X
|
||||||
|
X**3 -> X*X*X
|
||||||
|
X**0.5 -> sqrt(X)
|
||||||
X**-1 -> 1.0/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 -> X
|
X | 0 -> X
|
||||||
x & 0 -> 0
|
x & 0 -> 0
|
||||||
X ^ 0 -> X
|
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: remove redundant builtin function calls
|
||||||
todo expression optimization: reduce expression nesting / flattening of parenthesis
|
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 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 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 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 {
|
class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcessor {
|
||||||
|
@ -3,14 +3,11 @@ package prog8.stackvm
|
|||||||
import prog8.ast.DataType
|
import prog8.ast.DataType
|
||||||
import prog8.compiler.target.c64.Petscii
|
import prog8.compiler.target.c64.Petscii
|
||||||
import prog8.compiler.target.c64.Mflpt5
|
import prog8.compiler.target.c64.Mflpt5
|
||||||
import java.awt.EventQueue
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import javax.swing.Timer
|
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
import kotlin.system.exitProcess
|
|
||||||
|
|
||||||
enum class Opcode {
|
enum class Opcode {
|
||||||
|
|
||||||
@ -237,15 +234,11 @@ class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=
|
|||||||
init {
|
init {
|
||||||
when(type) {
|
when(type) {
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
byteval = numericvalue!!.toShort()
|
byteval = (numericvalue!!.toInt() and 255).toShort() // byte wrap around 0..255
|
||||||
if(byteval!! <0 || byteval!! > 255)
|
|
||||||
throw VmExecutionException("byte value overflow: $byteval")
|
|
||||||
asBooleanValue = byteval != (0.toShort())
|
asBooleanValue = byteval != (0.toShort())
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
wordval = numericvalue!!.toInt()
|
wordval = numericvalue!!.toInt() and 65535 // word wrap around 0..65535
|
||||||
if(wordval!! <0 || wordval!! > 65535)
|
|
||||||
throw VmExecutionException("word value overflow: $wordval")
|
|
||||||
asBooleanValue = wordval != 0
|
asBooleanValue = wordval != 0
|
||||||
}
|
}
|
||||||
DataType.FLOAT -> {
|
DataType.FLOAT -> {
|
||||||
@ -362,17 +355,17 @@ class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=
|
|||||||
val v1 = numericValue()
|
val v1 = numericValue()
|
||||||
val v2 = other.numericValue()
|
val v2 = other.numericValue()
|
||||||
val result = v1.toDouble().pow(v2.toDouble())
|
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 {
|
fun shl(): Value {
|
||||||
val v = integerValue()
|
val v = integerValue()
|
||||||
return Value(type, v.shl(1))
|
return Value(type, v shl 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shr(): Value {
|
fun shr(): Value {
|
||||||
val v = integerValue()
|
val v = integerValue()
|
||||||
return Value(type, v.ushr(1))
|
return Value(type, v ushr 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rol(carry: Boolean): Pair<Value, Boolean> {
|
fun rol(carry: Boolean): Pair<Value, Boolean> {
|
||||||
@ -1493,39 +1486,3 @@ class StackVm(val traceOutputFile: String?) {
|
|||||||
return ins.next
|
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
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
PROG8CLASSPATH=out/production/compiler
|
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)
|
Instruction(Opcode.NEG)
|
||||||
)
|
)
|
||||||
vm.load(makeProg(ins2), null)
|
vm.load(makeProg(ins2), null)
|
||||||
assertFailsWith<VmExecutionException> {
|
|
||||||
vm.step(2)
|
vm.step(2)
|
||||||
}
|
assertEquals(Value(DataType.WORD, 64302), vm.evalstack.pop())
|
||||||
|
|
||||||
val ins3 = mutableListOf(
|
val ins3 = mutableListOf(
|
||||||
Instruction(Opcode.PUSH, Value(DataType.BYTE, 12)),
|
Instruction(Opcode.PUSH, Value(DataType.BYTE, 12)),
|
||||||
Instruction(Opcode.NEG)
|
Instruction(Opcode.NEG)
|
||||||
)
|
)
|
||||||
vm.load(makeProg(ins3), null)
|
vm.load(makeProg(ins3), null)
|
||||||
assertFailsWith<VmExecutionException> {
|
|
||||||
vm.step(2)
|
vm.step(2)
|
||||||
}
|
assertEquals(Value(DataType.BYTE, 244), vm.evalstack.pop())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user