Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
concatenation of a str and a str function result (*solved*)
#1
I cannot understand the reason of some errors I'm getting about converting a string into a value and a value into a string.

In order to debug, I wrote a simplified version of the code:

Code:
dim a as ubyte

let a = 10
print "Yes: "+stringIF(a,"yes")+"..." ' ERROR: Cannot convert string to a value. Use VAL() function
print "Nothing: "+stringIF(0,"yes")+"..."
stop

function stringIf(condition as uinteger,text as string) as string

    if condition then
        return text
    else
        return ""
    end if

end function

stringIf is a simple alternative to the Sinclair Basic use of AND with strings:

Code:
LET A$ = "string" AND condition

So I can port it this way:

Code:
let aString = stringIf(condition,"string")

I don't understand why the following line fails:

Code:
print "Yes: "+stringIF(a,"yes")+"..." ' ERROR: Cannot convert string to a value. Use VAL() function

I tried an alternative, but nothing changed:

Code:
dim a as ubyte
dim t as string

let a = 10
let t = "Yes: "+stringIF(a,"yes")+"..." ' ERROR: Cannot convert string to a value. Use VAL() function
let t = "Nothing: "+stringIF(0,"yes")+"..."
stop

Beside those simple tests, I did several tries in the original code, and noted "FINE" or "ERROR" (all variables are DIMed as ubyte):

Code:
    #define true 1

    tell("Son las "+str(currentHour)+stringIf(currentMinute<>0,":"+stringIf(currentMinute<10,"0")+str(currentMinute))+" de la noche.") ' ERROR : Cannot convert string to a value. Use VAL() function
    print "Son las "+str(currentHour)+stringIf(currentMinute<>0,":"+stringIf(currentMinute<10,"0")+str(currentMinute))+" de la noche.") ' ERROR : Cannot convert string to a value. Use VAL() function
    print "Son las "+str(currentHour) ' FINE
    print "Son las "+str(currentHour)+str(currentMinute)+" de la noche." ' FINE
    print "Son las "+stringIf(currentMinute<>0,":") ' ERROR: Cannot convert string to a value. Use VAL() function
    print "Son las "+stringIf(true,":") ' ERROR: Cannot convert string to a value. Use VAL() function
    print stringIf(true,":") ' FINE

One of the tries caused both errors at the same time (string into value and vice versa!):

Code:
    #define true 1
    dim temp as string
    ' the following line gets two errors:
    ' Cannot convert value to string. Use STR() function
    ' Cannot convert string to a value. Use VAL() function
    let temp = "Son las "+stringIf(true,":")
    print temp

The stringIf function is defined to return a string, so I cannot understand what's the problem.

I tried another thing... Maybe it has to do with concatenation... Let's see:

Code:
print "Yes: ";stringIf(a,"yes");"..." ' FINE

it compiles! So the problem has something to do with string concatenation.

I'm stuck. I need some enlightenment.
Reply
#2
programandala.net Wrote:One of the tries caused both errors at the same time (string into value and vice versa!):
Code:
    let temp = "Son las "+stringIf(true,":")

The following calculation causes both errors at the same time too:

Code:
dim grade(1 to 10) as string
dim newGrade as ubyte

let grade(i)=stringIf(newGrade<10," ")+str(newGrade)

Quote:...:869: Cannot convert string to a value. Use VAL() function
...:869: Cannot convert value to string. Use STR() function

It seems it happens when I try to concatenate a literal string or a string function (like str) with the string output returned by a defined string function.

(I'm using version 1.2.5, I forgot)
Reply
#3
This definitively seems to be a bug. Let me examine it...
Reply
#4
Ok, you seems to have a bug in your code. ZX BASIC compiler is *case sensitive* by default. You have declared a function named stringIF (notice the uppercase F), but calls a different function named stringIf.

Also calling a function before it's declared automatically declares it as Float, so you're effectively, concatenating a float function with a string (The compiler should do a better work, and has a bug, anyway). If you declare the function FIRST (at the top), your program will work:
Code:
function stringIf(condition as uinteger,text as string) as string

   if condition then
      return text
   else
      return ""
   end if

end function

dim a as ubyte

let a = 10
print "Yes: "+stringIF(a,"yes")+"..." ' ERROR: Cannot convert string to a value. Use VAL() function
print "Nothing: "+stringIF(0,"yes")+"..."
REM stop ' not needed

Anyway: The compiler has a bug. It should not allow you to declare stringIF as String if you have already called it in your program-
Reply
#5
boriel Wrote:This definitively seems to be a bug. Let me examine it...

Yes, it was too strange.

I temporarily changed all lines that triggered that bug, removing the concatenations, one by one, compiling after every single change. But when I finished to fix the last syntax mistake, the compiler crashed and showed the following traceback:

Quote:marcos$ zxb.py --tap --autorun --BASIC --sinclair colegio_erevest_4.bas
Generating LALR tables
Generating LALR tables
WARNING: Token 'UMINUS' defined, but not used
WARNING: There is 1 unused token
Traceback (most recent call last):
File "/home/marcos/bin/zxb.py", line 255, in <module>
sys.exit(main(sys.argv)) # Exit
File "/home/marcos/bin/zxb.py", line 203, in main
zxbtrad.traverse(zxbtrad.FUNCTIONS) # This will fill MEMORY with pending functions
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 250, in traverse
traverse(l)
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 959, in traverse
traverse(i)
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 257, in traverse
traverse(i)
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 770, in traverse
traverse(tree.next[1])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 720, in traverse
traverse(tree.next[0])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 1004, in traverse
traverse(tree.next[i])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 1008, in traverse
traverse(tree.next[0])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 569, in traverse
traverse(tree.next[0])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 375, in traverse
traverse(tree.next[0])
File "/opt/zxbasic/1.2.5/zxbtrad.py", line 530, in traverse
if tree.next[0].token != 'STRING' and tree.next[0].token != 'ID' and tree.next[0].symbol._mangled[0] != '_':
AttributeError: 'SymbolSTRSLICE' object has no attribute '_mangled'

It's the first time it happens. I don't know if it has something to do with the same bug.

Anyway it's time to turn the "Spectrum" off Smile
Reply
#6
Yes, it's a bug. But try the code I posted above. It works, so you can continue with your program.
Reply
#7
boriel Wrote:Ok, you seems to have a bug in your code. ZX BASIC compiler is *case sensitive* by default. You have declared a function named stringIF (notice the uppercase F), but calls a different function named stringIf.

Thanks, I realized that while debugging. I mistyped the actual name (stringIf) in one or two calls, but that is not the cause of the problem because there are more calls with proper spelling.

boriel Wrote:Also calling a function before it's declared automatically declares it as Float, so you're effectively, concatenating a float function with a string (The compiler should do a better work, and has a bug, anyway). If you declare the function FIRST (at the top), your program will work:

You are right, it works. Thank you. I couldn't imagine the order has anything to do! Maybe it's in the docs, but I didn't see it. This feature forces me to rearrange the code quite a bit, because many secondary functions are declared at the end of the source...

boriel Wrote:Anyway: The compiler has a bug. It should not allow you to declare stringIF as String if you have already called it in your program-

What about a warning? There are warnings when a number is not declared, and the compiler declares them as float by default. If there were a similar warning when calling an undefined function, it would be easy to trace the problem.

Anyhow, is the default float issue to be changed in the future? It would be nice not to depend on the order the functions are defined.

By the way, I remember FreeBASIC needs the function headers to be declared at the start, what it quite annoying: you have to write them twice: at the function itself and at the top of the program. But I guess it has something to do with all this. That could be an alternative for ZX Basic too, to make sure all functions are declared at the start. Then their position in the source would'nt matter.
Reply
#8
That's right. The compiler should issue also a warning.

Regarding to the forward function declaration, I think it's much more elegant to let the compiler to guess the function type instead of letting the user to declare it in advance. But if it's required I will also put it. The idea is that your first program MUST also work since it's a valid ZX BASIC program. :wink:
Reply
#9
boriel Wrote:Regarding to the forward function declaration, I think it's much more elegant to let the compiler to guess the function type instead of letting the user to declare it in advance.
But if it's required I will also put it.

I agree the programmer shouldn't declare the functions in advance, it's quite annoying. But the current behaviour of the compiler (default float for not yet parsed functions) forces the programmer to rearrange the source in order to put the string functions at the top, what sometimes is hard to achieve, because some functions call others, and so on... Is this compiler limitation hard to remove? If so, I'd rather declare the functions in advance, so the source can be written freely with any desired layout. That would be more comfortable for the programmer.
Reply
#10
programandala.net Wrote:
boriel Wrote:Regarding to the forward function declaration, I think it's much more elegant to let the compiler to guess the function type instead of letting the user to declare it in advance.
But if it's required I will also put it.

I agree the programmer shouldn't declare the functions in advance, it's quite annoying. But the current behaviour of the compiler (default float for not yet parsed functions) forces the programmer to rearrange the source in order to put the string functions at the top, what sometimes is hard to achieve, because some functions call others, and so on... Is this compiler limitation hard to remove? If so, I'd rather declare the functions in advance, so the source can be written freely with any desired layout. That would be more comfortable for the programmer.
With the "forward" declaration (as FreeBasic, C or Pascal do) this limitation is rather easy to remove. But allowing the function to be called in advance without a forward declaration with a single pass compiler (as ZX BASIC), is rather difficult, because the calling code compilation must be delayed until the function has already been declared. This is a somewhat advanced compilation technique referred sometimes as "lazy compilation", and it's mostly used in dynamic languages. I will give it a try... :wink:
Reply
#11
Quote:With the "forward" declaration (as FreeBasic, C or Pascal do) this limitation is rather easy to remove.

I suggest a compromise: If no function is declared in advance, they are supposed to return float as currently. To change that, the programmer may declare them as in FreeBASIC:

Code:
declare function exit_join(as byte,as byte) as string

In FreeBASIC even SUBs must be declared, but that's not needed in ZX Basic, isn't it?

Quote:allowing the function to be called in advance without a forward declaration with a single pass compiler (as ZX BASIC), is rather difficult

I didn't know ZX Basic does one single pass! It's one more reason to appreciate your work. It's impressive.

But wouldn't it be easier to do two passes? Then the program could search for function declarations.
Reply
#12
I finally decided to implement "Declare", because it's much much easier than letting the compiler to guess it (it also requires 2 pass compiling, etc). Declared will be unneeded by SUBs, but required by non float Functions if you want to use them in advance.
Reply
#13
That's going to be handy, because it allows you to bias where in memory code ends up.

When 128K issues arise, that's going to become extremely critical :-)
Reply
#14
Okay, new version 1.2.6-r1603c is out, and adds DECLARE FUNCTION, so this error is corrected. Now you can declare functions in advance following FreeBASIC DECLARE syntax.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)