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

Reply via email to