mirror of
https://github.com/irmen/prog8.git
synced 2025-01-12 19:29:50 +00:00
len()
This commit is contained in:
parent
2478c73bc0
commit
13a5a06ffb
@ -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)
|
||||
|
@ -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]]
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
|
@ -1,6 +1,7 @@
|
||||
package prog8.functions
|
||||
|
||||
import prog8.ast.*
|
||||
import prog8.compiler.CompilerException
|
||||
import prog8.compiler.HeapValues
|
||||
import kotlin.math.log2
|
||||
|
||||
|
@ -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()))
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user