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); } }