removed string conversion builtin functions, they're now subroutines in c64util

This commit is contained in:
Irmen de Jong 2018-12-22 01:07:43 +01:00
parent 6a18c83fa5
commit d55bbcf706
14 changed files with 179 additions and 165 deletions

View File

@ -23,7 +23,7 @@
; use loop to write characters
str bye = "Goodbye!\n"
for ubyte c in 0 to len(bye) { ; @TODO fix compiler crash
for ubyte c in 0 to len(bye) { ; @TODO fix compiler crash. Parent of assignment to c should be the anonymous scope 'c' is in, instead of the for loop itself.
c64.CHROUT(bye[c])
}

View File

@ -32,7 +32,7 @@
c64scr.print("es")
c64scr.print(" left.\nWhat is your next guess? ")
c64scr.input_chars(input)
ubyte guess = str2ubyte(input)
ubyte guess = c64utils.str2ubyte(input)
; debug info
; c64scr.print(" > attempts left=")

View File

@ -21,7 +21,7 @@
vm_write_str("es")
vm_write_str(" left. What is your next guess? ")
vm_input_str(input)
ubyte guess = str2ubyte(input)
ubyte guess = c64utils.str2ubyte(input) ; @todo replace with proper stubs for these functions when executing on stackvm.
if guess==secretnumber {
vm_write_str("\nYou guessed it, impressive!\n")
vm_write_str("Thanks for playing.\n")

View File

@ -28,9 +28,9 @@
}
sub screenx(float x) -> ubyte {
return b2ub(fintb(x * flt(width)/2.2) + width//2)
return (x * width/2.2) + width//2 as ubyte
}
sub screeny(float y) -> ubyte {
return b2ub(fintb(y * flt(height)/2.2) + height//2)
return (y * height/2.2) + height//2 as ubyte
}
}

View File

@ -23,9 +23,13 @@
}
sub screenx(float x) -> word {
return fintw(x * flt(width)/4.1) + width // 2
; return (x/4.1* (width as float) as word) + width // 2 ; @todo fix calculation
float wf = width
return (x/4.1* wf + wf / 2) as word
}
sub screeny(float y) -> word {
return fintw(y * flt(height)/4.1) + height // 2
;return (y/4.1 * (height as float) as word) + height // 2 ; @todo fix calculation
float hf = height
return (y/4.1 * hf + hf/ 2) as word
}
}

View File

@ -1,111 +1,86 @@
%import c64utils
%import mathlib
%option enable_floats
;%import mathlib
;%option enable_floats
~ main {
;c64scr.PLOT(screenx(x), screeny(y)) ; @todo fix argument calculation???!!!
;@todo implement the various byte/word division routines.
;c64scr.PLOT(screenx(x), screeny(y)) ; @todo fix argument calculation of parameters ???!!!
sub start() {
byte[4] ba = [-1,2,-10,30]
ubyte[4] uba = [4,200,10,15]
word[5] wa = [400,-200,-1000,9999,1500]
uword[7] uwa = [333,42,9999,12,150,1000,4000]
float[6] fa = [-2.22, 3.33, -5.55, 1.11, 9999.99, -999.99]
c64scr.print(" X=")
c64scr.print_ub(X)
c64.CHROUT('\n')
byte bmin = min(ba)
byte bmax = max(ba)
ubyte ubmin = min(uba)
ubyte ubmax = max(uba)
word wmin = min(wa)
word wmax = max(wa)
uword uwmin = min(uwa)
uword uwmax = max(uwa)
float fmin = min(fa)
float fmax = max(fa)
c64scr.print_w(wmin)
c64.CHROUT(',')
c64scr.print_w(wmax)
word w = c64utils.str2word("000")
c64scr.print_w(w)
c64.CHROUT('\n')
w = c64utils.str2word("1")
c64scr.print_w(w)
c64.CHROUT('\n')
w = c64utils.str2word("-15000")
c64scr.print_w(w)
c64.CHROUT('\n')
w = c64utils.str2word("15000")
c64scr.print_w(w)
c64.CHROUT('\n')
c64scr.print_uw(uwmin)
c64.CHROUT(',')
c64scr.print_uw(uwmax)
c64.CHROUT('\n')
c64scr.print_b(bmin)
c64.CHROUT(',')
c64scr.print_b(bmax)
uword uw = c64utils.str2uword("0")
c64scr.print_uw(uw)
c64.CHROUT('\n')
uw = c64utils.str2uword("1")
c64scr.print_uw(uw)
c64.CHROUT('\n')
uw = c64utils.str2uword("15000")
c64scr.print_uw(uw)
c64.CHROUT('\n')
uw = c64utils.str2uword("65522")
c64scr.print_uw(uw)
c64.CHROUT('\n')
c64scr.print_ub(ubmin)
c64.CHROUT(',')
c64scr.print_ub(ubmax)
c64.CHROUT('\n')
c64flt.print_f(fmin)
c64.CHROUT(',')
c64flt.print_f(fmax)
byte b = c64utils.str2byte("0")
c64scr.print_b(b)
c64.CHROUT('\n')
b=c64utils.str2byte("10")
c64scr.print_b(b)
c64.CHROUT('\n')
b=c64utils.str2byte("-10")
c64scr.print_b(b)
c64.CHROUT('\n')
b=c64utils.str2byte("-128")
c64scr.print_b(b)
c64.CHROUT('\n')
b=c64utils.str2byte("127")
c64scr.print_b(b)
c64.CHROUT('\n')
c64.CHROUT('\n')
ubyte ub = c64utils.str2ubyte("0")
c64scr.print_ub(ub)
c64.CHROUT('\n')
ub=c64utils.str2ubyte("10")
c64scr.print_ub(ub)
c64.CHROUT('\n')
ub=c64utils.str2ubyte("10")
c64scr.print_ub(ub)
c64.CHROUT('\n')
ub=c64utils.str2ubyte("128")
c64scr.print_ub(ub)
c64.CHROUT('\n')
ub=c64utils.str2ubyte("255")
c64scr.print_ub(ub)
c64.CHROUT('\n')
c64.CHROUT('\n')
c64scr.print(" X=")
c64scr.print_ub(X)
c64.CHROUT('\n')
; ub3 = 200/67 as ubyte
; ub3 = 200//67
; c64scr.print_ub(ub3)
; c64.CHROUT('\n')
; ub3 = ub1/ub2
; c64scr.print_ub(ub3)
; c64.CHROUT('\n')
; ub3 = ub1//ub2
; c64scr.print_ub(ub3)
; c64.CHROUT('\n')
;
; uw3 = 2000/67 as uword
; c64scr.print_uw(uw3)
; c64.CHROUT('\n')
; uw3 = 2000//67
; c64scr.print_uw(uw3)
; c64.CHROUT('\n')
; uw3 = uw1/uw2
; c64scr.print_uw(uw3)
; c64.CHROUT('\n')
; uw3 = uw1//uw2
; c64scr.print_uw(uw3)
; c64.CHROUT('\n')
;
; const byte width=20
; word w1
; byte b1
; ubyte ub1
; float x = 3.45
; b1 = fintb(x * flt(width)/4.2) + width//2
; c64scr.print_b(b1)
; c64.CHROUT('\n')
; b1 = fintb(x/4.2 * flt(width)) + width//2
; c64scr.print_b(b1)
; c64.CHROUT('\n')
; ub1 = b2ub(fintb(x * flt(width)/4.2) + width//2)
; c64scr.print_ub(ub1)
; c64.CHROUT('\n')
; ub1 = b2ub(fintb(x/4.2 * flt(width)) + width//2)
; c64scr.print_ub(ub1)
; c64.CHROUT('\n')
; w1 = fintw(x * flt(width)/4.2) + width//2
; c64scr.print_w(w1)
; c64.CHROUT('\n')
; w1 = fintw(x/4.2 * flt(width)) + width//2
; c64scr.print_w(w1)
; c64.CHROUT('\n')
;uw1 = w2uw(fintw(x * flt(width)/4.2) + width//2) ; @todo w2uw
}
}

View File

@ -270,6 +270,7 @@ interface IAstProcessor {
}
fun process(typecastExpression: TypecastExpression): IExpression {
typecastExpression.expression = typecastExpression.expression.process(this)
return typecastExpression
}
}
@ -477,7 +478,7 @@ private class GlobalNamespace(override val name: String,
override fun linkParents(parent: Node) {}
override fun lookup(scopedName: List<String>, statement: Node): IStatement? {
if(scopedName.last() in BuiltinFunctions) {
if(scopedName.size==1 && scopedName[0] in BuiltinFunctions) {
// builtin functions always exist, return a dummy statement for them
val builtinPlaceholder = Label("builtin::${scopedName.last()}", statement.position)
builtinPlaceholder.parent = ParentSentinel

View File

@ -436,8 +436,11 @@ class AstChecker(private val namespace: INameScope,
val sourceDatatype: DataType? = assignment.value.resultingDatatype(namespace, heap)
if(sourceDatatype==null) {
if(assignment.targets.size<=1) {
if (assignment.value is FunctionCall)
checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position))
if (assignment.value is FunctionCall) {
val targetStmt = (assignment.value as FunctionCall).target.targetStatement(namespace)
if(targetStmt!=null)
checkResult.add(ExpressionError("function call doesn't return a suitable value to use in assignment", assignment.value.position))
}
else
checkResult.add(ExpressionError("assignment value is invalid or has no proper datatype", assignment.value.position))
}

View File

@ -1388,7 +1388,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
AX -> {
// deal with register pair AX: target = A + X*256
val targetDt = target.determineDatatype(namespace, heap, parent)
if(targetDt!=DataType.UWORD)
if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD)
throw CompilerException("invalid target datatype for registerpair $targetDt")
prog.instr(Opcode.PUSH_REGAX_WORD)
popValueIntoTarget(target, targetDt)
@ -1396,7 +1396,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
AY -> {
// deal with register pair AY: target = A + Y*256
val targetDt = target.determineDatatype(namespace, heap, parent)
if(targetDt!=DataType.UWORD)
if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD)
throw CompilerException("invalid target datatype for registerpair $targetDt")
prog.instr(Opcode.PUSH_REGAY_WORD)
popValueIntoTarget(target, targetDt)
@ -1404,7 +1404,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
XY -> {
// deal with register pair XY: target = X + Y*256
val targetDt = target.determineDatatype(namespace, heap, parent)
if(targetDt!=DataType.UWORD)
if(targetDt!=DataType.UWORD && targetDt!=DataType.WORD)
throw CompilerException("invalid target datatype for registerpair $targetDt")
prog.instr(Opcode.PUSH_REGXY_WORD)
popValueIntoTarget(target, targetDt)

View File

@ -425,10 +425,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr })
throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}")
val call = Syscall.values().find { it.callNr==ins.arg.numericValue() }
when(call) {
Syscall.FUNC_STR2UBYTE, Syscall.FUNC_STR2UWORD -> " jsr prog8_lib.func_str2uword"
else -> " jsr prog8_lib.${call.toString().toLowerCase()}"
}
" jsr prog8_lib.${call.toString().toLowerCase()}"
}
Opcode.BREAKPOINT -> {
breakpointCounter++

View File

@ -54,11 +54,6 @@ val BuiltinFunctions = mapOf(
"clear_carry" to FunctionSignature(false, emptyList(), null),
"set_irqd" to FunctionSignature(false, emptyList(), null),
"clear_irqd" to FunctionSignature(false, emptyList(), null),
"str2byte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.BYTE),
"str2ubyte" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UBYTE),
"str2word" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.WORD),
"str2uword" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.UWORD),
"str2float" to FunctionSignature(true, listOf(BuiltinFunctionParam("string", StringDatatypes)), DataType.FLOAT),
"vm_write_memchr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"vm_write_memstr" to FunctionSignature(false, listOf(BuiltinFunctionParam("address", setOf(DataType.UWORD))), null),
"vm_write_num" to FunctionSignature(false, listOf(BuiltinFunctionParam("number", NumericDatatypes)), null),

View File

@ -40,11 +40,6 @@ enum class Syscall(val callNr: Short) {
FUNC_RND(89), // push a random byte on the stack
FUNC_RNDW(90), // push a random word on the stack
FUNC_RNDF(91), // push a random float on the stack (between 0.0 and 1.0)
FUNC_STR2BYTE(100),
FUNC_STR2UBYTE(101),
FUNC_STR2WORD(102),
FUNC_STR2UWORD(103),
FUNC_STR2FLOAT(104),
FUNC_LEN_STR(105),
FUNC_LEN_STRP(106),
FUNC_LEN_STRS(107),
@ -1450,8 +1445,8 @@ class StackVm(private var traceOutputFile: String?) {
Syscall.FUNC_ROUND -> evalstack.push(Value(DataType.WORD, evalstack.pop().numericValue().toDouble().roundToInt()))
Syscall.FUNC_ABS -> {
val value = evalstack.pop()
val absValue=
when(value.type) {
val absValue =
when (value.type) {
DataType.UBYTE -> Value(DataType.UBYTE, value.numericValue())
DataType.UWORD -> Value(DataType.UWORD, value.numericValue())
DataType.FLOAT -> Value(DataType.FLOAT, value.numericValue())
@ -1468,13 +1463,13 @@ class StackVm(private var traceOutputFile: String?) {
Syscall.FUNC_DEG -> evalstack.push(Value(DataType.FLOAT, Math.toDegrees(evalstack.pop().numericValue().toDouble())))
Syscall.FUNC_FLOOR -> {
val value = evalstack.pop()
if(value.type in NumericDatatypes)
if (value.type in NumericDatatypes)
evalstack.push(Value(DataType.WORD, floor(value.numericValue().toDouble()).toInt()))
else throw VmExecutionException("cannot get floor of $value")
}
Syscall.FUNC_CEIL -> {
val value = evalstack.pop()
if(value.type in NumericDatatypes)
if (value.type in NumericDatatypes)
evalstack.push(Value(DataType.WORD, ceil(value.numericValue().toDouble()).toInt()))
else throw VmExecutionException("cannot get ceil of $value")
}
@ -1538,7 +1533,7 @@ class StackVm(private var traceOutputFile: String?) {
val result = value.array!!.min() ?: 0
evalstack.push(Value(DataType.FLOAT, result))
}
Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W, Syscall.FUNC_AVG_F-> {
Syscall.FUNC_AVG_UB, Syscall.FUNC_AVG_B, Syscall.FUNC_AVG_UW, Syscall.FUNC_AVG_W, Syscall.FUNC_AVG_F -> {
val iterable = evalstack.pop()
val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.FLOAT, value.array!!.average()))
@ -1568,39 +1563,7 @@ class StackVm(private var traceOutputFile: String?) {
val value = heap.get(iterable.heapId)
evalstack.push(Value(DataType.UBYTE, if (value.array!!.all { v -> v != 0 }) 1 else 0))
}
Syscall.FUNC_STR2BYTE -> {
val strvar = evalstack.pop()
val str = heap.get(strvar.heapId) // TODO CHECK
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.BYTE, y.toShort()))
}
Syscall.FUNC_STR2UBYTE -> {
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = (y.toInt() and 255).toShort()
evalstack.push(Value(DataType.UBYTE, number))
}
Syscall.FUNC_STR2WORD -> {
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.WORD, y.toInt()))
}
Syscall.FUNC_STR2UWORD -> {
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
val number = y.toInt() and 65535
evalstack.push(Value(DataType.UWORD, number))
}
Syscall.FUNC_STR2FLOAT -> {
val heapId = evalstack.pop().integerValue()
val str = heap.get(heapId)
val y = str.str!!.trim().trimEnd('\u0000')
evalstack.push(Value(DataType.FLOAT, y.toDouble()))
}
}
}
}
fun irq(timestamp: Long) {

View File

@ -565,21 +565,6 @@ rndw()
rndf()
returns a pseudo-random float between 0.0 and 1.0
str2byte(s)
converts string s into the numeric value that s represents (signed byte).
str2ubyte(s)
converts string s into the numeric value that s represents (unsigned byte).
str2word(s)
converts string s into the numeric value that s represents (signed word).
str2uword(s)
converts string s into the numeric value that s represents (unsigned word).
str2float(s)
converts string s into the numeric value that s represents (float).
lsl(x)
Shift the bits in x (byte or word) one position to the left.
Bit 0 is set to 0 (and the highest bit is shifted into the status register's Carry flag)

View File

@ -188,6 +188,97 @@ asmsub uword2decimal (uword value @ AY) -> clobbers(A,X,Y) -> () {
}
; @todo this is python code for a str-to-ubyte function that doesn't use the basic rom:
;def str2ubyte(s, slen):
; hundreds_map = {
; 0: 0,
; 1: 100,
; 2: 200
; }
; digitvalue = 0
; result = 0
; if slen==0:
; return digitvalue
; digitvalue = ord(s[slen-1])-48
; slen -= 1
; if slen==0:
; return digitvalue
; result = digitvalue
; digitvalue = 10 * (ord(s[slen-1])-48)
; result += digitvalue
; slen -= 1
; if slen==0:
; return result
; digitvalue = hundreds_map[ord(s[slen-1])-48]
; result += digitvalue
; return result
asmsub str2uword(str string @ AY) -> clobbers() -> (uword @ AY) {
%asm {{
;-- convert string (address in A/Y) to uword number in A/Y
; @todo don't use the (slow) kernel floating point conversion
sta $22
sty $23
jsr _strlen2233
tya
stx c64.SCRATCH_ZPREGX
jsr c64.FREADSTR ; string to fac1
jsr c64.GETADR ; fac1 to unsigned word in Y/A
ldx c64.SCRATCH_ZPREGX
sta c64.SCRATCH_ZPREG
tya
ldy c64.SCRATCH_ZPREG
rts
_strlen2233
;-- return the length of the (zero-terminated) string at $22/$23, in Y
ldy #0
- lda ($22),y
beq +
iny
bne -
+ rts
}}
}
asmsub str2word(str string @ AY) -> clobbers() -> (word @ AY) {
%asm {{
;-- convert string (address in A/Y) to signed word number in A/Y
; @todo don't use the (slow) kernel floating point conversion
sta $22
sty $23
jsr str2uword._strlen2233
tya
stx c64.SCRATCH_ZPREGX
jsr c64.FREADSTR ; string to fac1
jsr c64.FTOSWORDYA ; fac1 to unsigned word in Y/A
ldx c64.SCRATCH_ZPREGX
sta c64.SCRATCH_ZPREG
tya
ldy c64.SCRATCH_ZPREG
rts
}}
}
asmsub str2ubyte(str string @ AY) -> clobbers(Y) -> (ubyte @ A) {
%asm {{
;-- convert string (address in A/Y) to ubyte number in A
; @todo don't use the (slow) kernel floating point conversion
jmp str2uword
}}
}
asmsub str2byte(str string @ AY) -> clobbers(Y) -> (byte @ A) {
%asm {{
;-- convert string (address in A/Y) to byte number in A
; @todo don't use the (slow) kernel floating point conversion
jmp str2word
}}
}
; @todo string to 32 bit unsigned integer http://www.6502.org/source/strings/ascii-to-32bit.html