Skip to content

opaque types #70

Description

@dragoncoder047

I had another idea: user-definable opaque types. You could add a void* pointer to the car and cdr of the object union, and then have a variable OpaqueCounter which is the highest registered opaque type which must be less than the start of the workspace to avoid confusing it with a cons cell.

You would have to fix the markobject routine so it wouldn't start marking wild pointers into out-of-workspace memory -- a simple fix would be to, before marking or recursing on a pointer, check to see if (obj >= &Workspace[0] && object <= &Workspace[WORKSPACESIZE-1]). That way, the opaque type could use Lisp lists/trees to store garbage-collected variable-size data structures.

The idea of this is that you could implement a

uint32_t OpaqueCounter = PAIR;
void NextOpaqueID () {
  uint32_t temp = OpaqueCounter;
  if (temp >= &Workspace[0]) return 0; // Bail, out of IDs
  OpaqueCounter += 2;
  return temp;
}

void printopaque (object* obj, pfun_t pfun) {
  pfstring(PSTR("<opaque-"), pfun);
  pint(obj->type, pfun);
  pfstring(PSTR(" at 0x"), pfun);
  pintbase((uint32_t)obj, 16, pfun);
  pfun('>');
}

object* makeopaque (uint32_t id, void* arg) {
  if (id < PAIR || id >= &Workspace[0]) error2(PSTR("invalid opaque id"));
  object* obj = myalloc();
  obj->type = id;
  obj->cdr = (object*)arg;
  return obj;
}

void* checkopaque (uint32_t id, object* obj) {
  if (obj == NULL || obj->type != id) error(PSTR("expected opaque type"), obj);
  return (void*)obj->cdr;
}
void markobject (object *obj) {
  MARK:
  if (obj == NULL) return;
+ if (obj < &Workspace[0] || object > &Workspace[WORKSPACESIZE-1]) return; // Wild opaque pointer
  if (marked(obj)) return;

  object* arg = car(obj);
  unsigned int type = obj->type;
  mark(obj);

- if (type >= PAIR || type == ZZERO) { // cons
+ if (type >= &Workspace[0] || type == ZZERO) { // cons
    markobject(arg);
    obj = cdr(obj);
    goto MARK;
  }
  /* SNIP */
}

I probably haven't thought of the rest of it (edits to the printobject() routine, etc) or how to display a pretty name for the type, but I am open to suggestions.

The one big problem with this is I can't figure out a simple API for how an extension should be notified when an opaque object is garbage collected and the external memory should be freed, to avoid memory leaks. You could just put a big warning that your program needs to keep its own references and free them later somehow, or allocate objects statically or on the stack, but that doesn't sit quite right with me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions