/***** * 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[] = { #define OPCODE(name, type) #name, #include "opcodes.h" #undef OPCODE }; static const Int numOps = (Int)(sizeof(opnames)/sizeof(char *)); static const char optypes[] = { #define OPCODE(name, type) type, #include "opcodes.h" #undef OPCODE }; #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) { if (i.empty()) return out << "empty"; if (isdefault(i)) return out << "default"; #if COMPACT // TODO: Try to guess the type from the value. Int n = get(i); double x = get(i); void *p = get(i); if (n == BoolTruthValue) return out << "true"; if (n == BoolFalseValue) return out << "false"; if (std::abs(n) < 1000000) return out << n; if (fabs(x) < 1e30 and fabs(x) > 1e-30) return out << x; return out << ""; #else // TODO: Make a data structure mapping typeids to print functions. 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 { frame *f = get(i); if (f) out << " " << f->getName(); else out << " "; } # endif } else out << "type " << demangle(i.type().name()); #endif 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; return; } out << opnames[i]; switch (optypes[i]) { case 'n': { out << " " << get(*code); break; } case 't': { item c = code->ref; out << " " << c; break; } case 'b': { #ifdef DEBUG_BLTIN string s=lookupBltin(get(*code)); out << " " << (!s.empty() ? s : "") << " "; #endif break; } case 'o': { char f = out.fill('0'); out << " i"; out.width(4); out << offset(base,get(*code)); out.fill(f); break; } case 'l': { #ifdef DEBUG_FRAME out << " " << get(*code)->name << " "; #endif break; } 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