1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
/*****
* stack.h
* Andy Hammerlindl 2002/06/27
*
* The general stack machine used to run compiled camp code.
*****/
#ifndef STACK_H
#define STACK_H
#include <iostream>
#include "errormsg.h"
#include "vm.h"
#include "item.h"
#include "absyn.h"
namespace vm {
struct func;
class program;
struct lambda;
class importInitMap;
struct bpinfo : public gc {
fileinfo f;
absyntax::runnable *r;
bpinfo(const string& filename, size_t lineNum,
absyntax::runnable *r=NULL) :
f(fileinfo(filename,lineNum)), r(r) {}
};
inline bool operator == (const bpinfo& a, const bpinfo& b)
{
return a.f == b.f;
}
extern mem::list<bpinfo> bplist;
class runnable;
extern bool indebugger;
class stack {
public:
using vars_t = vmFrame*;
struct importInitMap {
virtual ~importInitMap() {}
virtual lambda *operator[](string) = 0;
};
private:
// stack for operands
using stack_t = mem::vector<item>;
stack_t theStack;
void draw(ostream& out);
// The initializer functions for imports, indexed by name.
importInitMap *initMap;
// The stack stores a map of initialized imported modules by name, so that
// each module is initialized only once and each import refers to the same
// instance.
using importInstanceMap = mem::map<const mem::string, vmFrame*>;
importInstanceMap instMap;
// One can associate an environment to embedded code while running.
trans::coenv *e;
// Debugger variables:
char debugOp;
position lastPos, breakPos;
bool newline;
// Move arguments from stack to frame.
void marshall(size_t args, stack::vars_t vars);
public:
stack() : e(0), debugOp(0), lastPos(nullPos),
breakPos(nullPos), newline(false) {};
virtual ~stack() {};
void setInitMap(importInitMap *i) {
initMap=i;
}
void setEnvironment(trans::coenv *e) {
this->e=e;
}
trans::coenv *getEnvironment() {
return e;
}
// Runs a lambda. If vars is non-null, it is used to store the variables of
// the lambda. Otherwise, the method allocates a closure only if needed.
void runWithOrWithoutClosure(lambda *l, vars_t vars, vars_t parent);
// Executes a function on top of the stack.
void run(func *f);
void breakpoint(absyntax::runnable *r=NULL);
void debug();
// Put an import (indexed by filename and optional template
// parameter signature) on top of the stack, initializing it if necessary.
void loadModule(string index, Int numPushedParents = 0);
// These are so that built-in functions can easily manipulate the stack
void push(item next) {
theStack.push_back(next);
}
template <typename T>
void push(T next) {
push((item)next);
}
item top() {
return theStack.back();
}
item pop() {
item ret = theStack.back();
theStack.pop_back();
return ret;
}
template <typename T>
T pop()
{
return get<T>(pop());
}
};
inline item pop(stack* s)
{
return s->pop();
}
template <typename T>
inline T pop(stack* s)
{
return get<T>(pop(s));
}
template <typename T>
inline T pop(stack* s, T defval)
{
item it=pop(s);
return isdefault(it) ? defval : get<T>(it);
}
class interactiveStack : public stack {
vars_t globals;
size_t globals_size;
public:
interactiveStack();
// Run a codelet, a small piece of code that uses globals as its frame.
void run(lambda *codelet);
};
} // namespace vm
#endif // STACK_H
|