The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
%RI.id yeast frame
%include <smop/yeast.h>,<smop/dump.h>
%prefix smop_yeast_frame
%struct SMOP__Yeast__Frame
%lowlevel

%DUMP {
  SMOP__Yeast__Frame* frame = (SMOP__Yeast__Frame*) obj;
  /* TODO ret */
  return smop_dump_create((SMOP__Object*[]) {
      SMOP_DUMP_NAGC,
      smop_dump_attr_create("back"),
      smop_dump_obj_create(frame->back),
      smop_dump_attr_create("lexical"),
      smop_dump_obj_create(frame->lexical),
      smop_dump_attr_create("catch"),
      smop_dump_obj_create(frame->catch),
      smop_dump_attr_create("control"),
      smop_dump_obj_create(frame->control),
      smop_dump_attr_create("yeast"),
      smop_dump_obj_create(frame->yeast),
      smop_dump_attr_create("reg"),
      smop_dump_obj_array_create(frame->reg,((SMOP__Yeast*)frame->yeast)->registers),
      NULL
  });
%}
%{
SMOP__Object* SMOP__Yeast__Frame_create(SMOP__Object* interpreter,SMOP__Object* yeast_object) {
    SMOP__Yeast* yeast = (SMOP__Yeast*) yeast_object;
    SMOP__Yeast__Frame* ret = (SMOP__Yeast__Frame*) smop_nagc_alloc(sizeof(SMOP__Yeast__Frame));
    ret->RI = (SMOP__ResponderInterface*)RI;
    ret->step = yeast->step;
    ret->yeast = yeast_object;

    ret->pc = 0;
    ret->back = NULL;
    ret->reg = (SMOP__Object**) calloc(yeast->registers,sizeof(SMOP__ResponderInterface)); 
    ret->ret = NULL;

    int i;
    for (i = 0; i < yeast->constants_len; i++) {
      if (yeast->constants[i]) {
        ret->reg[i] = SMOP_REFERENCE(interpreter,yeast->constants[i]);
      }
    }

    return (SMOP__Object*) ret;
}

SMOP__Object* SMOP__Frame_create(SMOP__Object* interpreter,SMOP__Object* shape) {
  if (shape->RI == (SMOP__ResponderInterface*)SMOP__Yeast__RI) {
    return SMOP__Yeast__Frame_create(interpreter,shape);
  } else {
    return SMOP__Mold__Frame_create(interpreter,shape);
  }
}

void smop_reg_set(SMOP__Object* interpreter,SMOP__Object* frame, int regnum, SMOP__Object* value) {
  if (frame->RI == (SMOP__ResponderInterface*)RI)
    yeast_reg_set(interpreter,frame,regnum,value);
  else
    mold_reg_set(interpreter,frame,regnum,value);
}

void smop_back_set(SMOP__Object* interpreter,SMOP__Object* obj, SMOP__Object* value) {
    if (obj->RI == (SMOP__ResponderInterface*)RI) {
      SMOP__Yeast__Frame* frame = (SMOP__Yeast__Frame*) obj;
      if (frame->back) {
        printf("setting back , previous %s new = %s\n",frame->back->RI->id,value->RI->id);
        printf("Cannot redefine mold back!");
        abort();
      }
      frame->back = value;
    } else {
      mold_back_set(interpreter,obj,value);
    }
}

void yeast_reg_set(SMOP__Object* interpreter,SMOP__Object* yeastframe, int regnum, SMOP__Object* value) {
    SMOP__Yeast__Frame* frame = (SMOP__Yeast__Frame*) yeastframe;
    SMOP__Yeast* yeast = (SMOP__Yeast*) frame->yeast;
    int where = yeast->constants_len+regnum;
    SMOP__Object* old = frame->reg[where];
//    printf("setting %d to %s\n",where,value->RI->id);
    frame->reg[where] = value;
    if (old) {
      SMOP_RELEASE(interpreter, old);
    }
}
%}

%method eval


    void (*step)(SMOP__Object* interpreter,
                SMOP__Object* frame);
    step = ((SMOP__Yeast__Frame*)invocant)->step;
    step(interpreter,invocant);
    if (((SMOP__Yeast__Frame*)invocant)->pc == -1) {
      ret = SMOP__NATIVE__bool_false;
    } else {
      ret = SMOP__NATIVE__bool_true;
    }

%method setr
    SMOP__Object* value = SMOP__NATIVE__capture_positional(interpreter, capture, 1);

    if (value == invocant) {
      SMOP_RELEASE(interpreter, value);
    }
    SMOP__Object** target = ((SMOP__Yeast__Frame*)invocant)->ret;
    if (!target) fprintf(stderr,"calling setr on a frame not expecting a return value\n");
    if (*target) {
      SMOP_RELEASE(interpreter,ret);
    }
    *target = value;

%method set_regs
    int i;
    int count = SMOP__NATIVE__capture_positional_count(interpreter, capture);
    for (i = 1;i < count;i++) {
      SMOP__Object* value = SMOP__NATIVE__capture_positional(interpreter, capture, i);
      smop_reg_set(interpreter, invocant, i-1, value);
    }

%getset back
%getset control
%getset catch
%getset lexical

%method FETCH
    ___VALUE_FETCH___;

%method STORE
    ___VALUE_STORE___;

%method true
    ret = SMOP__NATIVE__bool_true;

%DESTROYALL {
    SMOP__Yeast__Frame* frame = (SMOP__Yeast__Frame*) invocant;
    SMOP__Yeast* yeast = (SMOP__Yeast*) frame->yeast;
    int i;
    for (i=0;i<yeast->registers;i++) {
      if (frame->reg[i]) {
        SMOP_RELEASE(interpreter,frame->reg[i]);
        frame->reg[i] = NULL;
      }
    }
    free(frame->reg);
    frame->reg = NULL;
    SMOP_RELEASE(interpreter,frame->yeast);
    if (frame->back) SMOP_RELEASE(interpreter,frame->back);
    if (frame->control) SMOP_RELEASE(interpreter,frame->control);
    if (frame->catch) SMOP_RELEASE(interpreter,frame->catch);
    if (frame->lexical) SMOP_RELEASE(interpreter,frame->lexical);
    frame->yeast = NULL;
%}