I've embedded chibi scheme into my C++ application and am trying to create a float vector with a size of 3 in scheme, and then get the individual values of that vector back into my c++ program, however when I attempt to do so I only get the correct results if I use indexes beyond the size of the vector. As you can see below I verify the size of the vector.
test.scm
(define (test-vec in-a in-b)
(let ((vec (vector (* 3.1 in-a) (* 4.1 in-b) 5.0)))
(display "From Scheme: ")
(display vec)
(display "\n")
vec))
test.cpp
#include <iostream>
#include <chibi/eval.h>
int is_defined(sexp ctx, const char *sym)
{
sexp_gc_var1(ret);
sexp_gc_preserve1(ctx, ret);
ret = sexp_eval_string(ctx, sym, -1, NULL);
int defined = sexp_procedurep(ret);
sexp_gc_release1(ctx);
return defined;
}
int main()
{
float returnA, returnB, returnC, returnD, returnE, returnF;
sexp_scheme_init();
sexp ctx = sexp_make_eval_context(NULL, NULL, NULL, 0, 0);
sexp_load_standard_env(ctx, NULL, SEXP_SEVEN);
sexp_load_standard_ports(ctx, NULL, stdin, stdout, stderr, 1);
// Load the scheme file and create temp variables to pass the values to chibi
sexp_gc_var6(inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
sexp_gc_preserve6(ctx, inAVal, inASym, inBVal, inBSym, returnedVector, filePath);
filePath = sexp_c_string(ctx, "test.scm", -1);
sexp_load(ctx, filePath, NULL);
// Ensure our procedure is defined
if(is_defined(ctx, "test-vec"))
std::cout << "test-vec is defined" << std::endl;
// Create the values and create the symbols
inAVal = sexp_make_flonum(ctx, 1.0);
inASym = sexp_intern(ctx, "a", -1);
inBVal = sexp_make_flonum(ctx, 2.0);
inBSym = sexp_intern(ctx, "b", -1);
// Bind the values to the symbols and pass them to chibi
sexp_env_define(ctx, sexp_context_env(ctx), inASym, inAVal);
sexp_env_define(ctx, sexp_context_env(ctx), inBSym, inBVal);
// Evaluate the expression and store the result
returnedVector = sexp_eval_string(ctx, "(test-vec a b)", -1, NULL);
std::cout << "Vector size: " << sexp_vector_length(returnedVector) << std::endl;
// I would expect this to return the expected results?
returnA = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnB = sexp_flonum_value(sexp_vector_ref(returnedVector, 1));
returnC = sexp_flonum_value(sexp_vector_ref(returnedVector, 2));
std::cout << "Vector[0] = " << returnA << "\nVector[1] = " << returnB << "\nVector[2] = " << returnC << std::endl << std::endl;
// If I index outside of the range of the vector, it gives me the correct results?
returnD = sexp_flonum_value(sexp_vector_ref(returnedVector, 0));
returnE = sexp_flonum_value(sexp_vector_ref(returnedVector, 3));
returnF = sexp_flonum_value(sexp_vector_ref(returnedVector, 4));
std::cout << "Vector[0] = " << returnD << "\nVector[3] = " << returnE << "\nVector[4] = " << returnF << std::endl;
sexp_gc_release6(ctx);
}
Which gives me the output:
test-vec is defined
From Scheme: #(3.1 8.2 5.0)
Vector size: 3
Vector[0] = 3.1
Vector[1] = 3.1
Vector[2] = 8.2
Vector[0] = 3.1
Vector[3] = 8.2
Vector[4] = 5
How come indexing beyond the length of the vector is giving me the correct values?
Figured out the issue. It's because sexp_vector_ref(vec, i)
evaluates to
#define sexp_vector_ref(x,i) (sexp_vector_data(x)[sexp_unbox_fixnum(i)])
and sexp_unbox_fixnum(i)
evaluates to
#define sexp_unbox_fixnum(n) (((sexp_sint_t)((sexp_uint_t)(n) & ~SEXP_FIXNUM_TAG))/(sexp_sint_t)((sexp_sint_t)1<<SEXP_FIXNUM_BITS))
Which when we just pass in straight integers
std::cout << "Unboxed fixnums: " <<
sexp_unbox_fixnum(0) << " " <<
sexp_unbox_fixnum(1) << " " <<
sexp_unbox_fixnum(2) << " " <<
sexp_unbox_fixnum(3) << " " <<
sexp_unbox_fixnum(4) << std::endl;
gives us the output
Unboxed fixnums: 0 0 1 1 2
However if we first convert them into the proper types that chibi expects, like so
std::cout << "Fixnum: " <<
sexp_unbox_fixnum(sexp_make_fixnum(0)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(1)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(2)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(3)) << " " <<
sexp_unbox_fixnum(sexp_make_fixnum(4)) << std::endl;
we get the proper output
Fixnum: 0 1 2 3 4
Solution: Use the correct types when indexing