diff options
author | Karl Berry <karl@freefriends.org> | 2009-05-16 00:19:13 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-05-16 00:19:13 +0000 |
commit | bab45528d65eaafe68a705dbb2a57075c7b7cbd8 (patch) | |
tree | 10b4ae2b5195c8dede153ab89359ec00f55f325f /Build/source/utils/asymptote/coder.cc | |
parent | 8643d90372e9c31e0f461c15c596b60a545bd7d3 (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.cc | 278 |
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 + |