Example #1
0
void DotFunc::execute() {
    ComValue before_part(stack_arg(0, true));
    ComValue after_part(stack_arg(1, true));
    reset_stack();

    if (!before_part.is_symbol() && 
	!(before_part.is_attribute() && 
	  (((Attribute*)before_part.obj_val())->Value()->is_unknown() || 
	   ((Attribute*)before_part.obj_val())->Value()->is_attributelist())) &&
	!before_part.is_attributelist()) {
      cerr << "expression before \".\" needs to evaluate to a symbol or <AttributeList>\n";
      return;
    }
    if (nargs()>1 && !after_part.is_symbol()) {
      cerr << "expression after \".\" needs to be a symbol or evaluate to a symbol\n";
      return;
    }

    /* lookup value of before variable */
    void* vptr = nil; 
    AttributeList* al = nil;
    if (!before_part.is_attribute() && !before_part.is_attributelist()) {
      int before_symid = before_part.symbol_val();
      boolean global = before_part.global_flag();
      if (!global) {
	comterp()->localtable()->find(vptr, before_symid);
	if (!vptr) comterp()->globaltable()->find(vptr, before_symid);
      } else {
	comterp()->globaltable()->find(vptr, before_symid);
      }
      if (vptr &&((ComValue*) vptr)->class_symid() == AttributeList::class_symid()) {
	al = (AttributeList*) ((ComValue*) vptr)->obj_val();
      } else {
	al = new AttributeList();
	Resource::ref(al);
	ComValue* comval = new ComValue(AttributeList::class_symid(), (void*)al);
	if (!global)
	  comterp()->localtable()->insert(before_symid, comval);
	else
	  comterp()->globaltable()->insert(before_symid, comval);
      }
    } else if (!before_part.is_attributelist()) {
      if (((Attribute*)before_part.obj_val())->Value()->is_attributelist()) 
	al = (AttributeList*) ((Attribute*) before_part.obj_val())->Value()->obj_val();
      else {
	al = new AttributeList();
	AttributeValue newval(AttributeList::class_symid(), (void*) al);
	*((Attribute*)before_part.obj_val())->Value() = newval;
      }
    } else
      al = (AttributeList*) before_part.obj_val();

    if (nargs()>1) {
      int after_symid = after_part.symbol_val();
      Attribute* attr = al ? al->GetAttr(after_symid) :  nil;
      if (!attr) {
	attr = new Attribute(after_symid, new AttributeValue());
	al->add_attribute(attr);
      }
      ComValue retval(Attribute::class_symid(), attr);
      push_stack(retval);
    } else {
      ComValue retval(AttributeList::class_symid(), al);
      push_stack(retval);
    }
}