summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/program.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/program.cc')
-rw-r--r--Build/source/utils/asymptote/program.cc172
1 files changed, 172 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/program.cc b/Build/source/utils/asymptote/program.cc
new file mode 100644
index 00000000000..2af41c967d5
--- /dev/null
+++ b/Build/source/utils/asymptote/program.cc
@@ -0,0 +1,172 @@
+/*****
+ * program.cc
+ * Tom Prince
+ *
+ * The list of instructions used by the virtual machine.
+ *****/
+
+#include <iostream>
+#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<bltin,string> 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<Int>(i);
+ double x = get<double>(i);
+ void *p = get<void *>(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 << "<item " << p << ">";
+#else
+ // TODO: Make a data structure mapping typeids to print functions.
+ else if (i.type() == typeid(Int))
+ out << "Int, value = " << get<Int>(i);
+ else if (i.type() == typeid(double))
+ out << "real, value = " << get<double>(i);
+ else if (i.type() == typeid(string))
+ out << "string, value = " << get<string>(i);
+ else if (i.type() == typeid(callable))
+ out << *(get<callable *>(i));
+ else if (i.type() == typeid(frame)) {
+ out << "frame";
+# ifdef DEBUG_FRAME
+ {
+ frame *f = get<frame *>(i);
+ if (f)
+ out << " " << f->getName();
+ else
+ out << " <null>";
+ }
+# 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 << "<<invalid op>>" << i;
+ return;
+ }
+ out << opnames[i];
+
+ switch (optypes[i]) {
+ case 'n':
+ {
+ out << " " << get<Int>(*code);
+ break;
+ }
+
+ case 't':
+ {
+ item c = code->ref;
+ out << " " << c;
+ break;
+ }
+
+ case 'b':
+ {
+#ifdef DEBUG_BLTIN
+ string s=lookupBltin(get<bltin>(*code));
+ out << " " << (!s.empty() ? s : "<unnamed>") << " ";
+#endif
+ break;
+ }
+
+ case 'o':
+ {
+ char f = out.fill('0');
+ out << " i";
+ out.width(4);
+ out << offset(base,get<program::label>(*code));
+ out.fill(f);
+ break;
+ }
+
+ case 'l':
+ {
+#ifdef DEBUG_FRAME
+ out << " " << get<lambda*>(*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