summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/coder.cc
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
committerKarl Berry <karl@freefriends.org>2009-05-16 00:19:13 +0000
commitbab45528d65eaafe68a705dbb2a57075c7b7cbd8 (patch)
tree10b4ae2b5195c8dede153ab89359ec00f55f325f /Build/source/utils/asymptote/coder.cc
parent8643d90372e9c31e0f461c15c596b60a545bd7d3 (diff)
asymptote 1.72 sources (not integrated into build yet)
git-svn-id: svn://tug.org/texlive/trunk@13110 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/utils/asymptote/coder.cc')
-rw-r--r--Build/source/utils/asymptote/coder.cc278
1 files changed, 278 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/coder.cc b/Build/source/utils/asymptote/coder.cc
new file mode 100644
index 00000000000..01d3ff3a58f
--- /dev/null
+++ b/Build/source/utils/asymptote/coder.cc
@@ -0,0 +1,278 @@
+/*****
+ * coder.cc
+ * Andy Hammerlindl 2004/11/06
+ *
+ * Handles encoding of syntax into programs. It's methods are called by
+ * abstract syntax objects during translation to construct the virtual machine
+ * code.
+ *****/
+
+#include <utility>
+
+#include "errormsg.h"
+#include "coder.h"
+#include "genv.h"
+#include "entry.h"
+
+using namespace sym;
+using namespace types;
+
+namespace trans {
+
+namespace {
+function *inittype();
+function *bootuptype();
+}
+
+// The dummy environment of the global environment.
+// Used purely for global variables and static code blocks of file
+// level modules.
+coder::coder(modifier sord)
+ : level(new frame(0, 0)),
+ recordLevel(0),
+ recordType(0),
+ isCodelet(false),
+ l(new vm::lambda),
+ funtype(bootuptype()),
+ parent(0),
+ sord(sord),
+ perm(DEFAULT_PERM),
+ program(new vm::program),
+ numLabels(0),
+ curPos(nullPos)
+{
+ sord_stack.push(sord);
+ encodeAllocInstruction();
+}
+
+// Defines a new function environment.
+coder::coder(function *t, coder *parent, modifier sord, bool reframe)
+ : level(reframe ? new frame(parent->getFrame(), t->sig.getNumFormals()) :
+ parent->getFrame()),
+ recordLevel(parent->recordLevel),
+ recordType(parent->recordType),
+ isCodelet(!reframe),
+ l(new vm::lambda),
+ funtype(t),
+ parent(parent),
+ sord(sord),
+ perm(DEFAULT_PERM),
+ program(new vm::program),
+ numLabels(0),
+ curPos(nullPos)
+{
+ sord_stack.push(sord);
+ encodeAllocInstruction();
+}
+
+// Start encoding the body of the record. The function being encoded
+// is the record's initializer.
+coder::coder(record *t, coder *parent, modifier sord)
+ : level(t->getLevel()),
+ recordLevel(t->getLevel()),
+ recordType(t),
+ isCodelet(false),
+ l(t->getInit()),
+ funtype(inittype()),
+ parent(parent),
+ sord(sord),
+ perm(DEFAULT_PERM),
+ program(new vm::program),
+ numLabels(0),
+ curPos(nullPos)
+{
+ sord_stack.push(sord);
+ encodeAllocInstruction();
+}
+
+coder coder::newFunction(function *t, modifier sord)
+{
+ return coder(t, this, sord);
+}
+
+coder coder::newCodelet()
+{
+ return coder(new function(primVoid()), this, DEFAULT_DYNAMIC, false);
+}
+
+record *coder::newRecord(symbol *id)
+{
+ frame *underlevel = getFrame();
+
+ frame *level = new frame(underlevel, 0);
+
+ record *r = new record(id, level);
+
+ return r;
+}
+
+coder coder::newRecordInit(record *r, modifier sord)
+{
+ return coder(r, this, sord);
+}
+
+
+bool coder::encode(frame *f)
+{
+ frame *toplevel = getFrame();
+
+ if (f == 0) {
+ encode(inst::constpush,(item)0);
+ }
+ else if (f == toplevel) {
+ encode(inst::pushclosure);
+ }
+ else {
+ encode(inst::varpush,0);
+
+ frame *level = toplevel->getParent();
+ while (level != f) {
+ if (level == 0)
+ // Frame request was in an improper scope.
+ return false;
+
+ encode(inst::fieldpush,0);
+
+ level = level->getParent();
+ }
+ }
+
+ return true;
+}
+
+bool coder::encode(frame *dest, frame *top)
+{
+ //cerr << "coder::encode()\n";
+
+ if (dest == 0) {
+ encode(inst::pop);
+ encode(inst::constpush,(item)0);
+ }
+ else {
+ frame *level = top;
+ while (level != dest) {
+ if (level == 0) {
+ // Frame request was in an improper scope.
+ //cerr << "failed\n";
+
+ return false;
+ }
+
+ encode(inst::fieldpush,0);
+
+ level = level->getParent();
+ }
+ }
+
+ //cerr << "succeeded\n";
+ return true;
+}
+
+Int coder::defLabel()
+{
+ if (isStatic())
+ return parent->defLabel();
+
+ return defLabel(numLabels++);
+}
+
+Int coder::defLabel(Int label)
+{
+ if (isStatic())
+ return parent->defLabel(label);
+
+ assert(label >= 0 && label < numLabels);
+
+ defs.insert(std::make_pair(label,program->end()));
+
+ std::multimap<Int,vm::program::label>::iterator p = uses.lower_bound(label);
+ while (p != uses.upper_bound(label)) {
+ p->second->ref = program->end();
+ ++p;
+ }
+
+ return label;
+}
+
+void coder::useLabel(inst::opcode op, Int label)
+{
+ if (isStatic())
+ return parent->useLabel(op,label);
+
+ std::map<Int,vm::program::label>::iterator p = defs.find(label);
+ if (p != defs.end()) {
+ encode(op,p->second);
+ } else {
+ // Not yet defined
+ uses.insert(std::make_pair(label,program->end()));
+ encode(op);
+ }
+}
+
+Int coder::fwdLabel()
+{
+ if (isStatic())
+ return parent->fwdLabel();
+
+ // Create a new label without specifying its position.
+ return numLabels++;
+}
+
+void coder::markPos(position pos)
+{
+ curPos = pos;
+}
+
+// When translating the function is finished, this ties up loose ends
+// and returns the lambda.
+vm::lambda *coder::close() {
+ // These steps must be done dynamically, not statically.
+ sord = EXPLICIT_DYNAMIC;
+ sord_stack.push(sord);
+
+ // Add a return for void types; may be redundant.
+ if (funtype->result->kind == types::ty_void)
+ encode(inst::ret);
+
+ l->code = program;
+
+ l->params = level->getNumFormals();
+
+ // Now that we know how many variables the function has, allocate space for
+ // all of them at the start of the function.
+ finishAlloc();
+
+ sord_stack.pop();
+ sord = sord_stack.top();
+
+ return l;
+}
+
+void coder::closeRecord()
+{
+ // Put record into finished state.
+ encode(inst::pushclosure);
+ close();
+}
+
+bool coder::isRecord()
+{
+ return (funtype==inittype());
+}
+
+namespace {
+function *inittype()
+{
+ static function t(types::primVoid());
+ return &t;
+}
+
+function *bootuptype()
+{
+ static function t(types::primVoid());
+ return &t;
+}
+} // private
+
+} // namespace trans
+