/***** * program.cc * Tom Prince * * The list of instructions used by the virtual machine. *****/ #include #include "util.h" #include "callable.h" #include "program.h" namespace vm { static const char* opnames[] = { "pop", "intpush", "constpush", "varpush", "varsave", "fieldpush", "fieldsave", "builtin", "jmp", "cjmp", "njmp", "call", "pushclosure", "makefunc", "ret", "alloc", "pushframe", "popframe" }; static const Int numOps = (Int)(sizeof(opnames)/sizeof(char *)); #ifdef DEBUG_BLTIN mem::map bltinRegistry; void registerBltin(bltin b, string s) { bltinRegistry[b] = s; } string lookupBltin(bltin b) { return bltinRegistry[b]; } #endif ostream& operator<< (ostream& out, const item& i) { // TODO: Make a data structure mapping typeids to print functions. if (i.empty()) out << "empty"; else if (isdefault(i)) out << "default"; else if (i.type() == typeid(Int)) out << "Int, value = " << get(i); else if (i.type() == typeid(double)) out << "real, value = " << get(i); else if (i.type() == typeid(string)) out << "string, value = " << get(i); else if (i.type() == typeid(callable)) out << *(get(i)); else if (i.type() == typeid(frame)) { out << "frame"; #ifdef DEBUG_FRAME out << " " << (get(i))->getName(); #endif } else out << "type " << demangle(i.type().name()); return out; } void printInst(ostream& out, const program::label& code, const program::label& base) { out.width(4); out << offset(base,code) << " "; Int i = (Int)code->op; if (i < 0 || i >= numOps) { out << "<> " << i; } out << opnames[i]; switch (code->op) { case inst::intpush: case inst::varpush: case inst::varsave: case inst::fieldpush: case inst::fieldsave: case inst::alloc: { out << " " << get(*code); break; } case inst::constpush: { item c = code->ref; out << " " << c; break; } #ifdef DEBUG_BLTIN case inst::builtin: { string s=lookupBltin(get(*code)); out << " " << (!s.empty() ? s : "") << " "; break; } #endif case inst::jmp: case inst::cjmp: case inst::njmp: { char f = out.fill('0'); out << " i"; out.width(4); out << offset(base,get(*code)); out.fill(f); break; } #ifdef DEBUG_FRAME case inst::makefunc: { out << " " << get(*code)->name << " "; break; } #endif default: { /* nothing else to do */ break; } }; } void print(ostream& out, program *base) { program::label code = base->begin(); bool active = true; while (active) { if (code->op == inst::ret || code->op < 0 || code->op >= numOps) active = false; printInst(out, code, base->begin()); out << '\n'; ++code; } } } // namespace vm