List of lists from C


#1

I’ve read the “Converting Values between C and Lisp” thread and figured out making lists from C, but I’m having an awfully difficult time trying to figure out how to construct a list of lists from C. Everything I try combines all of the values into one list. I need to construct a two-dimensional list. Any pointers?


#2

Suppose you’ve got two lists lista and listb:

(defvar lista '(1 2))
(defvar listb '(3 4))

These will be represented internally as:

The result you want should be:

((1 2) (3 4))

which will look like this:

Does that help?

If not, send me the C code of what you’ve got and I’ll have a look at it.


#3

Thanks for the diagrams, but I haven’t quite figured out how to combine objects yet without using cons. It seems like the objects are similar to linked lists, but being more of a Python programmer these days I haven’t worked with low level data structures like linked lists in a while, and I’m having trouble visualizing how to fit together the sequence of things I need to do to put together what’s on your diagrams. I’m working on a complex project with uLisp as a refresher in C++ and a way to learn lisp. So, if you can show me how to extend my current code snippet to combine lists into lists of lists, it will probably elucidate several of my confusions all at once and remind me of a few things I’ve forgotten.

I’m working on turning uLisp into a command shell language, using the FreeRTOS kernel for preemptive task management, to make a simple OS that can spin off uLisp programs into parallel tasks. Currently I have gotten uLisp to run inside a task, and the process table contains just this base shell task. Eventually multitasking will be figured out once I understand uLisp’s architecture enough to know what can be shared between processes and what can’t, and then fn_ps() will need to be able to return lists of lists, one list containing the status and info of each process. Currently it only returns one list for the base process. The current code is below, and will probably be refactored as I continue to remember what the heck I’m doing as far as C++ is concerned.

object *fn_ps (object *args, object *env) {
  (void) env;
  int i;
  object* psid;
  object* runn;
  object* desc;
  object* result = NULL;
  //for (i = 0; i < ProcessTable.length(); i++) {
    i = 0;
    psid = number(ProcessTable[i].psid);
    if (ProcessTable[i].suspended == 0)
      runn = tee;
    else
      runn = nil;
    desc = lispstring(ProcessTable[i].desc);
    result = cons(psid, cons(runn, cons(desc, NULL)));
  //}
  return result;
}

Edit: I tried writing this, but it does something silly instead of working as intended.

object *fn_ps (object *args, object *env) {
  (void) env;
  int i;
  object* psid;
  object* runn;
  object* desc;
  object* curr = myalloc();
  object* head = curr;
  
  for (i = 0; i < ProcessTable.size(); i++) {
    psid = number(ProcessTable[i].psid);
    if (ProcessTable[i].suspended == 0)
      runn = tee;
    else
      runn = nil;
    desc = lispstring(ProcessTable[i].desc);
    car(curr) = cons(psid, cons(runn, cons(desc, NULL)));
    cdr(curr) = myalloc();
    curr = cdr(curr);
  }
  return head;
}

#4

The correct way is to use cons(); you shouldn’t need to call myalloc() directly.

I think your code should be as follows (I haven’t tried it):

object *fn_ps (object *args, object *env) {
  (void) env;
  int i;
  object* psid;
  object* runn;
  object* desc;
  object* head = NULL;
  
  for (i = 0; i < ProcessTable.size(); i++) {
    psid = number(ProcessTable[i].psid);
    if (ProcessTable[i].suspended == 0)
      runn = tee;
    else
      runn = nil;
    desc = lispstring(ProcessTable[i].desc);
    object *curr = cons(psid, cons(runn, cons(desc, NULL)));
    head = cons(curr, head);
  }
  return head;
}

The easiest way to build a list is backwards, so the result will have the last item at the front. In your code you can easily correct for this by changing the for statement to:

for (i = ProcessTable.size()-1; i >= 0; i--) {

#5

One thing you should be aware of when constructing a list like this. If there’s the possibility that the garbage collector will get called while you’re constructing the list, it could get garbage collected before you can return it as the result, and you may get a corrupted result.

I don’t think this is a problem here, because the garbage collector only gets called when you call eval(), and you’re not doing that here.

If, however, you needed to eval something while constructing the list you would need to protect the list from garbage collection by pushing a pointer to it onto GCStack while you’re constructing it, and pop it at the end.


#6

Thanks, that did the trick. I’ll keep the garbage collector in mind once I start spawning additional processes.