mirror of
https://github.com/irmen/prog8.git
synced 2024-09-29 08:57:51 +00:00
len()
This commit is contained in:
parent
2478c73bc0
commit
13a5a06ffb
@ -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)
|
||||||
|
@ -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]]
|
||||||
|
@ -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) {
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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()))
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user