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 f3
b2 = 99
w2 = -9999
ub2 = 100
uw2 = 40000
f2 = 3.141592654
ubyte[3] uba = [1,2,3]
byte[3] ba = [-1,2,3]
uword[3] uwa = [1000,2000,3000]
word[3] wa = -222
;word[3] wa = [-1000.w,2000.w,3000.w] ; @todo array data type fix (float->word)
;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')
c64scr.print_ubyte_decimal(X)
c64.CHROUT('\n')
f1 = deg(f2)
c64flt.print_float(f1)
ub1 = any(uba)
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
c64.CHROUT('x')
c64scr.print_ubyte_decimal(X)
ub1 = any(ba)
c64scr.print_ubyte_decimal(ub1)
c64.CHROUT('\n')
f1 = rad(f1)
c64flt.print_float(f1)
ub1 = any(uwa)
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('x')
c64scr.print_ubyte_decimal(X)

View File

@ -88,7 +88,8 @@ enum class BranchCondition {
}
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_UW, DataType.ARRAY_W,
DataType.ARRAY_F)
@ -1394,6 +1395,18 @@ class FunctionCall(override var target: IdentifierReference,
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(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 {
var resultValue: LiteralValue? = null
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))
else {
for (arg in args.withIndex().zip(func.parameters)) {
if(arg.first.value.resultingDatatype(namespace, heap) !in arg.second.possibleDatatypes)
checkResult.add(ExpressionError("builtin function argument ${arg.first.index+1} has invalid type, expected ${arg.second.possibleDatatypes}", position))
val argDt=arg.first.value.resultingDatatype(namespace, heap)
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) {

View File

@ -671,6 +671,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
// some functions are implemented as vm opcodes
args.forEach { translate(it) } // place function argument(s) on the stack
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" -> {
// 1 argument, type determines the exact opcode to use
val arg = args.single()

View File

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

View File

@ -46,7 +46,6 @@ enum class Syscall(val callNr: Short) {
FUNC_MIN(83),
FUNC_AVG(84),
FUNC_SUM(85),
FUNC_LEN(86),
FUNC_ANY(87),
FUNC_ALL(88),
FUNC_RND(89), // push a random byte on the stack
@ -58,7 +57,11 @@ enum class Syscall(val callNr: Short) {
FUNC_STR2UBYTE(101),
FUNC_STR2WORD(102),
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:
// 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_RNDW -> evalstack.push(Value(DataType.UWORD, rnd.nextInt() and 65535))
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_COS -> evalstack.push(Value(DataType.FLOAT, cos(evalstack.pop().numericValue().toDouble())))
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 -> {
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')
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???"
.pend
func_len .proc
rts
.warn "len not implemented--of what does it take len?"
.pend
func_any .proc
rts
.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?"
.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
; -- put a random ubyte on the estack