This commit is contained in:
Irmen de Jong 2018-12-16 13:58:18 +01:00
parent 2478c73bc0
commit 13a5a06ffb
7 changed files with 91 additions and 24 deletions

View File

@ -17,24 +17,36 @@
float f2 float f2
float f3 float f3
ubyte[3] uba = [1,2,3]
b2 = 99 byte[3] ba = [-1,2,3]
w2 = -9999 uword[3] uwa = [1000,2000,3000]
ub2 = 100 word[3] wa = -222
uw2 = 40000 ;word[3] wa = [-1000.w,2000.w,3000.w] ; @todo array data type fix (float->word)
f2 = 3.141592654 ;word[3] wa = [1000,2000,3000] ; @todo array data type fix (uword->word)
float[3] fa = [-1000,44.555, 99.999]
str string = "hello"
str_p pstring = "hello1"
str_s sstring = "hello12"
str_ps psstring = "hello123"
c64.CHROUT('x') c64.CHROUT('x')
c64scr.print_ubyte_decimal(X) c64scr.print_ubyte_decimal(X)
c64.CHROUT('\n') c64.CHROUT('\n')
f1 = deg(f2)
c64flt.print_float(f1) ub1 = any(uba)
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n') c64.CHROUT('\n')
c64.CHROUT('x') ub1 = any(ba)
c64scr.print_ubyte_decimal(X) c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n') c64.CHROUT('\n')
f1 = rad(f1) ub1 = any(uwa)
c64flt.print_float(f1) c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
ub1 = any(wa)
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
ub1 = any(fa)
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n') c64.CHROUT('\n')
c64.CHROUT('x') c64.CHROUT('x')
c64scr.print_ubyte_decimal(X) c64scr.print_ubyte_decimal(X)

View File

@ -88,7 +88,8 @@ enum class BranchCondition {
} }
val IterableDatatypes = setOf( val IterableDatatypes = setOf(
DataType.STR, DataType.STR_S, // note: the STR_P/STR_PS types aren't iterable because they store their length as the first byte DataType.STR, DataType.STR_S,
DataType.STR_P, DataType.STR_PS, // note: these are a bit weird they store their length as the first byte
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UB, DataType.ARRAY_B,
DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_UW, DataType.ARRAY_W,
DataType.ARRAY_F) DataType.ARRAY_F)
@ -1394,6 +1395,18 @@ class FunctionCall(override var target: IdentifierReference,
private fun constValue(namespace: INameScope, heap: HeapValues, withDatatypeCheck: Boolean): LiteralValue? { private fun constValue(namespace: INameScope, heap: HeapValues, withDatatypeCheck: Boolean): LiteralValue? {
// if the function is a built-in function and the args are consts, should try to const-evaluate! // if the function is a built-in function and the args are consts, should try to const-evaluate!
if(target.nameInSource.size>1) return null if(target.nameInSource.size>1) return null
if(target.nameInSource[0]=="len" && arglist.size==1) {
val arg=arglist[0]
if(arg is IdentifierReference) {
val target=arg.targetStatement(namespace)
if(target!=null) {
if (arg.resultingDatatype(namespace, heap) in StringDatatypes) {
// len on strings should be dynamic, all other cases are a compile-time constant
return null
}
}
}
}
try { try {
var resultValue: LiteralValue? = null var resultValue: LiteralValue? = null
val func = BuiltinFunctions[target.nameInSource[0]] val func = BuiltinFunctions[target.nameInSource[0]]

View File

@ -716,8 +716,9 @@ class AstChecker(private val namespace: INameScope,
checkResult.add(SyntaxError("invalid number of arguments", position)) checkResult.add(SyntaxError("invalid number of arguments", position))
else { else {
for (arg in args.withIndex().zip(func.parameters)) { for (arg in args.withIndex().zip(func.parameters)) {
if(arg.first.value.resultingDatatype(namespace, heap) !in arg.second.possibleDatatypes) val argDt=arg.first.value.resultingDatatype(namespace, heap)
checkResult.add(ExpressionError("builtin function argument ${arg.first.index+1} has invalid type, expected ${arg.second.possibleDatatypes}", position)) if(argDt !in arg.second.possibleDatatypes)
checkResult.add(ExpressionError("builtin function argument ${arg.first.index+1} has invalid type $argDt, expected ${arg.second.possibleDatatypes}", position))
} }
} }
} else if(target is Subroutine) { } else if(target is Subroutine) {

View File

@ -671,6 +671,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
// some functions are implemented as vm opcodes // some functions are implemented as vm opcodes
args.forEach { translate(it) } // place function argument(s) on the stack args.forEach { translate(it) } // place function argument(s) on the stack
when (funcname) { when (funcname) {
"len" -> {
// 1 argument, type determines the exact syscall to use
val arg=args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.STR -> createSyscall("${funcname}_str")
DataType.STR_P -> createSyscall("${funcname}_strp")
DataType.STR_S -> createSyscall("${funcname}_str")
DataType.STR_PS -> createSyscall("${funcname}_strp")
else -> throw CompilerException("wrong datatype for len()")
}
}
"flt" -> { "flt" -> {
// 1 argument, type determines the exact opcode to use // 1 argument, type determines the exact opcode to use
val arg = args.single() val arg = args.single()

View File

@ -1,6 +1,7 @@
package prog8.functions package prog8.functions
import prog8.ast.* import prog8.ast.*
import prog8.compiler.CompilerException
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import kotlin.math.log2 import kotlin.math.log2

View File

@ -46,7 +46,6 @@ enum class Syscall(val callNr: Short) {
FUNC_MIN(83), FUNC_MIN(83),
FUNC_AVG(84), FUNC_AVG(84),
FUNC_SUM(85), FUNC_SUM(85),
FUNC_LEN(86),
FUNC_ANY(87), FUNC_ANY(87),
FUNC_ALL(88), FUNC_ALL(88),
FUNC_RND(89), // push a random byte on the stack FUNC_RND(89), // push a random byte on the stack
@ -58,7 +57,11 @@ enum class Syscall(val callNr: Short) {
FUNC_STR2UBYTE(101), FUNC_STR2UBYTE(101),
FUNC_STR2WORD(102), FUNC_STR2WORD(102),
FUNC_STR2UWORD(103), FUNC_STR2UWORD(103),
FUNC_STR2FLOAT(104) FUNC_STR2FLOAT(104),
FUNC_LEN_STR(105),
FUNC_LEN_STRP(106),
FUNC_LEN_STRS(107),
FUNC_LEN_STRPS(108)
// note: not all builtin functions of the Prog8 language are present as functions: // note: not all builtin functions of the Prog8 language are present as functions:
// some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)! // some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL_BYTE, ROR, ROL2, ROR2, and FLT)!
@ -1454,7 +1457,11 @@ class StackVm(private var traceOutputFile: String?) {
Syscall.FUNC_RND -> evalstack.push(Value(DataType.UBYTE, rnd.nextInt() and 255)) Syscall.FUNC_RND -> evalstack.push(Value(DataType.UBYTE, rnd.nextInt() and 255))
Syscall.FUNC_RNDW -> evalstack.push(Value(DataType.UWORD, rnd.nextInt() and 65535)) Syscall.FUNC_RNDW -> evalstack.push(Value(DataType.UWORD, rnd.nextInt() and 65535))
Syscall.FUNC_RNDF -> evalstack.push(Value(DataType.FLOAT, rnd.nextDouble())) Syscall.FUNC_RNDF -> evalstack.push(Value(DataType.FLOAT, rnd.nextDouble()))
Syscall.FUNC_LEN -> throw VmExecutionException("len() should have been const-folded away everywhere (it's not possible on non-const values)") Syscall.FUNC_LEN_STR, Syscall.FUNC_LEN_STRS, Syscall.FUNC_LEN_STRP, Syscall.FUNC_LEN_STRPS -> {
val strPtr = evalstack.pop().integerValue()
val text = heap.get(strPtr).str!!
evalstack.push(Value(DataType.UBYTE, text.length))
}
Syscall.FUNC_SIN -> evalstack.push(Value(DataType.FLOAT, sin(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_SIN -> evalstack.push(Value(DataType.FLOAT, sin(evalstack.pop().numericValue().toDouble())))
Syscall.FUNC_COS -> evalstack.push(Value(DataType.FLOAT, cos(evalstack.pop().numericValue().toDouble()))) Syscall.FUNC_COS -> evalstack.push(Value(DataType.FLOAT, cos(evalstack.pop().numericValue().toDouble())))
Syscall.FUNC_ROUND -> evalstack.push(Value(DataType.WORD, evalstack.pop().numericValue().toDouble().roundToInt())) Syscall.FUNC_ROUND -> evalstack.push(Value(DataType.WORD, evalstack.pop().numericValue().toDouble().roundToInt()))
@ -1565,7 +1572,7 @@ class StackVm(private var traceOutputFile: String?) {
} }
Syscall.FUNC_STR2BYTE -> { Syscall.FUNC_STR2BYTE -> {
val strvar = evalstack.pop() val strvar = evalstack.pop()
val str = heap.get(strvar.heapId) val str = heap.get(strvar.heapId) // TODO CHECK
val y = str.str!!.trim().trimEnd('\u0000') val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.BYTE, y.toShort())) evalstack.push(Value(DataType.BYTE, y.toShort()))
} }

View File

@ -897,11 +897,6 @@ func_sum .proc
.warn "sum not implemented--what does it sum over???" .warn "sum not implemented--what does it sum over???"
.pend .pend
func_len .proc
rts
.warn "len not implemented--of what does it take len?"
.pend
func_any .proc func_any .proc
rts rts
.warn "any not implemented--of what does it do any?" .warn "any not implemented--of what does it do any?"
@ -912,6 +907,33 @@ func_all .proc
.warn "all not implemented--of what does it do all?" .warn "all not implemented--of what does it do all?"
.pend .pend
func_len_str .proc
; -- push length of 0-terminated string on stack
lda ESTACK_LO+1,x
sta SCRATCH_ZPWORD1
lda ESTACK_HI+1,x
sta SCRATCH_ZPWORD1+1
ldy #0
- lda (SCRATCH_ZPWORD1),y
beq +
iny
bne -
+ tya
sta ESTACK_LO+1,x
rts
.pend
func_len_strp .proc
; -- push length of pascal-string on stack
lda ESTACK_LO+1,x
sta SCRATCH_ZPWORD1
lda ESTACK_HI+1,x
sta SCRATCH_ZPWORD1+1
ldy #0
lda (SCRATCH_ZPWORD1),y ; first byte is length
sta ESTACK_LO+1,x
rts
.pend
func_rnd .proc func_rnd .proc
; -- put a random ubyte on the estack ; -- put a random ubyte on the estack