Hi Michel,
> Hi Manuel,
>
> You can compile the files I copy/paste in the email, below = "bigloo -c
> failc.c ; bigloo fail.scm failc.o -o toto"
> Then execute, and see the result:
> > toto
> dataOK1 = 12346789-123456789-123456789-, len is: 30
> dataOK2 = 12346789-123456789-123456789-, len is: 30
> data-not-KO = 1234, len is: 30
>
> Let me comment:
> - we have a C structure, a kind of buffer with 2 fields 'data' and 'length'
> And we have a C function that set 'data' to a buf (filled) in the global
> area, and set 'len' to 30.
> In the scheme part, we construct an instance of c-struct and call the
> c-function that initialize it; in a 'let*'
> then, we try to retrieve the data content in the scheme, thanks to 3
> bindings, corresponding to 3 trials.
> I would expect 3 identical results. I can't explain why the latest trial is
> not ok.
> It looks like the 'if' says 'true' in the 3rd binding , but we expect 'false'
> that leads to a correct bind of the data.
> ...at the same time , a similar 'if' in the 2nd binding works fine ... that's
> even more strange.
>
> Tell me if you need more info.
> Thanks, regards,
> Michel
This is indeed very subtle... and confusing. Here is the explanation.
Local variables are typed by the compiler. On a let assignment, Bigloo
assigns the type of the variable with the type of the rhs expression.
In your example:
(let* (...
(dataOK1 (pragma::bstring ...))
(dataOK2 (if (equal? (c_struct*-len my-struct) 999)
"we should not get this because -len is not 999"
(pragma::bstring ...)))
(data-not-KO (if (equal? (c_struct*-len my-struct) 999)
(c_struct*-data my-struct))
(pragma::bstring "fool( $1, $2 )" (c_struct*-data
my-struct) (c_struct*-len my-struct))))
Variables dataOK1 and dataOK2 are assigned the type ::bstring (both rhs
expressions are bstring) but data-no-KO is assigned a type ::string
because on a if joint point Bigloo prefers the most efficient type.
Here is select ::string (the then branch of your if) against ::bstring
(the else part of the if). Before displaying the data-no-KO in the
expression
(print "data-not-KO = " data-not-KO ", len is: " (c_struct*-len my-struct))
The variable data-no-KO has to be compiled back to ::bstring before
being sent to print. For that it uses the conversion function string_to_bstring
that stops after a (char)0 and this is why print ends up with a string of
length 4.
To solve the problem, you can explicitly type the variable, for instance
with:
(data-not-KO::bstring (if (equal? ...)))
I agree that all this is very confusing but unfortunately, I'm not sure
it can be changed.
Cheers,
--
Manuel