How to access two-dimensional uLisp array?


#1

I’m pretty much stuck trying to manipulate an existing two-dimensional uLisp array from C (within an extension function). What’s the best way to do this? I tried hard to figure it out reading “Implementation” and the uLisp source code back and forth, but to no effect.

Should I use sp_setf to do it? If so, what do I have to pass to this function? When I pass

cons(fn_aref(cons(array, cons(number(x), cons (number(y), NULL))), env), cons(number(newvalue), NULL))

I get “Error: unknown variable: 1” (assuming the array has been initialized with ‘1’ before). So obviously the pointer returned by fn_aref is interpreted wrong because it already points to the value stored in array[x][y].

Thus I assume I should not use sp_setf to change the value but rather utilize the result of getarray(...) directly. But I cannot figure out whether I can safely access the memory cell the “pointer to a pointer” obtained by getarray(...) refers to, or rather I’m not sure what exactly this pointer points to.

So, in short, what do I need to do within a C function to store a new value (in this case, just a number) in a cell of a two-dimensional uLisp array? Any help greatly appreciated!


#2

Here’s some demonstration code to write a Lisp function test. It takes a two-dimensional array, two subscripts, and a value:

(test array x y value)

and sets the specified element of the array to that value:

object *fn_test (object *args, object *env) {
  int bit;
  // Get the four parameters
  object *array = first(args);
  object *x = second(args);
  args = cddr(args);
  object *y = first(args);
  object *value = second(args);
  // Build a list of the subscripts
  object *subscripts = cons(x, cons(y, NULL));
  // Get a pointer to the required array element
  object **element = getarray(array, subscripts, env, &bit);
  // Set it to the value
  *element = value;
  return value;
}

Trying it out:

2816> (defvar a (make-array '(2 3)))
a

2801> a
#2A((nil nil nil) (nil nil nil))

2801> (test a 1 2 73)
73

2800> a
#2A((nil nil nil) (nil nil 73))

Hope that helps! Feel free to ask any questions.


#3

Thank you so much! That clears things up and should be really easy. Now I know how the result of “getarray” needs to be dereferenced - and that “env” indeed needs to be passed as well (which was something I wondered).
I’d add one question, just in case I should need it in the future: How would I fill an array slot with a string or a list? (Presumably just using the object* pointer?)
Thanks again!


#4

The array value can be any type of Lisp object, so that’s how you would set it to a string or list object.

By the way, it should have been possible to get your original approach to work, of setting up a list of appropriate parameters to setf and aref from C, but my suggested solution using getarray() is probably simpler.