/winxedst0.cpp
http://github.com/NotFound/winxed · C++ · 6494 lines · 5816 code · 541 blank · 137 comment · 799 complexity · 48432d18214d862feaa6834e8061c257 MD5 · raw file
Large files are truncated click here to view the full file
- // winxedst0.cpp
- // Revision 25-jun-2012
- // Winxed compiler stage 0.
- #include "token.h"
- #include "errors.h"
- #include "emit.h"
- #include <string>
- #include <iostream>
- #include <istream>
- #include <fstream>
- #include <sstream>
- #include <cctype>
- #include <vector>
- #include <map>
- #include <algorithm>
- #include <stdexcept>
- #include <string.h>
- #include <errno.h>
- #include <typeinfo>
- //**********************************************************************
- // Register types
- const char REGint = 'I';
- const char REGstring = 'S';
- const char REGvar = 'P';
- // Pseudotypes for builtins
- const char REGany = '?';
- const char REGnone = '\0'; // void return
- static const char * nameoftype(char ctype)
- {
- switch (ctype)
- {
- case REGint: return "int";
- case REGstring: return "string";
- case REGvar: return "pmc";
- default:
- throw CompileError("Invalid type");
- }
- }
- char nativetype(const Token &name)
- {
- if (name.iskeyword("int")) return REGint;
- else if (name.iskeyword("string")) return REGstring;
- else if (name.iskeyword("var")) return REGvar;
- else return '\0';
- }
- //**********************************************************************
- #define INDENT " "
- #define INDENTLABEL " "
- inline
- std::string op(const char *name, const std::string &op1)
- {
- return INDENT + std::string(name) + ' ' + op1;
- }
- inline
- std::string op(const char *name,
- const std::string &op1, const std::string &op2)
- {
- return INDENT + std::string(name) + ' ' + op1 + ", " + op2;
- }
- inline
- std::string op(const char *name,
- const std::string &op1,
- const std::string &op2, const std::string &op3)
- {
- return INDENT + std::string(name) + ' ' + op1 + ", " + op2 + ", " + op3;
- }
- inline
- std::string op_inc(const std::string &op1)
- {
- return op("inc", op1);
- }
- inline
- std::string op_dec(const std::string &op1)
- {
- return op("dec", op1);
- }
- inline
- std::string op_set(const std::string &res, const std::string &op1)
- {
- return op("set", res, op1);
- }
- inline
- std::string op_assign(const std::string &res, const std::string &op1)
- {
- return op("assign", res, op1);
- }
- inline
- std::string op_box(const std::string &res, const std::string &op1)
- {
- return op("box", res, op1);
- }
- inline
- std::string op_add(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("add", res, op1, op2);
- }
- inline
- std::string op_sub(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("sub", res, op1, op2);
- }
- inline
- std::string op_mul(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("mul", res, op1, op2);
- }
- inline
- std::string op_div(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("div", res, op1, op2);
- }
- inline
- std::string op_mod(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("mod", res, op1, op2);
- }
- inline
- std::string op_cmod(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("cmod", res, op1, op2);
- }
- inline
- std::string op_null(const std::string &res)
- {
- return op("null", res);
- }
- inline
- std::string op_isnull(const std::string &res, const std::string &op1)
- {
- return op("isnull", res, op1);
- }
- inline
- std::string op_iseq(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("iseq", res, op1, op2);
- }
- inline
- std::string op_isne(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("isne", res, op1, op2);
- }
- inline
- std::string op_islt(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("islt", res, op1, op2);
- }
- inline
- std::string op_isgt(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("isgt", res, op1, op2);
- }
- inline
- std::string op_isle(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("isle", res, op1, op2);
- }
- inline
- std::string op_isge(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("isge", res, op1, op2);
- }
- inline
- std::string op_isa(const std::string &res,
- const std::string &op1, const std::string &op2)
- {
- return op("isa", res, op1, op2);
- }
- //**********************************************************************
- inline void RequireOp(char name, const Token &t)
- {
- if (! t.isop(name) )
- throw Expected (name, t);
- }
- inline void ExpectOp(char name, Tokenizer &tk)
- {
- Token t= tk.get();
- RequireOp(name, t);
- }
- //**********************************************************************
- template <typename T>
- void emit_group(const std::vector<T *> &group, Emit &e)
- {
- for (size_t i= 0; i < group.size(); ++i)
- group[i]->emit(e);
- }
- //**********************************************************************
- class BuiltinFunction
- {
- public:
- static const int VarArgs = -1;
- BuiltinFunction(const std::string &name, char typeresult, int nargs) :
- pname(name),
- tresult(typeresult),
- n(nargs)
- {
- }
- BuiltinFunction(const std::string &name, char typeresult) :
- pname(name),
- tresult(typeresult),
- n(VarArgs)
- {
- }
- static const BuiltinFunction *find(const std::string &name,
- size_t numargs);
- bool name_is(const std::string &name) const
- { return pname == name; }
- size_t numargs() const { return n; }
- char resulttype() const { return tresult; }
- virtual char paramtype(size_t n) const = 0;
- virtual void emit(Emit &e, const std::string &result,
- const std::vector<std::string> args) const = 0;
- private:
- static const BuiltinFunction *builtins[];
- static const size_t numbuiltins;
- const std::string pname;
- char tresult;
- unsigned int n;
- };
- class BuiltinFunctionFixargs : public BuiltinFunction
- {
- public:
- BuiltinFunctionFixargs(const std::string &name,
- const std::string &body,
- char typeresult,
- char type0= '\0',
- char type1= '\0',
- char type2= '\0',
- char type3= '\0');
- private:
- void emit(Emit &e, const std::string &result,
- const std::vector<std::string> args) const;
- char paramtype(size_t n) const
- {
- switch(n)
- {
- case 0: return t0;
- case 1: return t1;
- case 2: return t2;
- case 3: return t3;
- default: return '\0';
- }
- }
- char t0, t1, t2, t3;
- std::vector<std::string> chunks;
- std::vector<int> marks;
- };
- class BuiltinFunctionVarargs : public BuiltinFunction
- {
- protected:
- BuiltinFunctionVarargs(const std::string &name,
- char typeresult) :
- BuiltinFunction(name, typeresult)
- { }
- char paramtype(size_t /*unused*/) const
- {
- return REGany;
- }
- };
- class Builtin_print : public BuiltinFunctionVarargs
- {
- public:
- Builtin_print() : BuiltinFunctionVarargs("print", REGnone)
- { }
- private:
- void emit(Emit &e, const std::string &,
- const std::vector<std::string> args) const
- {
- const size_t n = args.size();
- for (size_t i= 0; i < n; ++i)
- e << INDENT "print " << args[i] << '\n';
- }
- };
- class Builtin_say : public BuiltinFunctionVarargs
- {
- public:
- Builtin_say() : BuiltinFunctionVarargs("say", REGnone)
- { }
- private:
- void emit(Emit &e, const std::string &,
- const std::vector<std::string> args) const
- {
- const size_t n = args.size();
- if (n > 0) {
- for (size_t i= 0; i < n - 1; ++i)
- e << INDENT "print " << args[i] << '\n';
- e << INDENT "say " << args[n-1] << '\n';
- }
- else
- e << INDENT "say ''\n";
- }
- };
- class Builtin_cry : public BuiltinFunctionVarargs
- {
- public:
- Builtin_cry() : BuiltinFunctionVarargs("cry", REGnone)
- { }
- private:
- void emit(Emit &e, const std::string &,
- const std::vector<std::string> args) const
- {
- e <<
- INDENT "getstderr $P0\n";
- const size_t n = args.size();
- for (size_t i= 0; i < n; ++i)
- e << INDENT "$P0.'print'(" << args[i] << ")\n";
- e << INDENT "$P0.'print'(\"\\n\")\n";
- }
- };
- class Builtin_ASSERT : public BuiltinFunction
- {
- public:
- Builtin_ASSERT() : BuiltinFunction("__ASSERT__", REGnone, 1)
- { }
- char paramtype(size_t n) const { return REGint; }
- void emit(Emit &e, const std::string &,
- const std::vector<std::string> args) const
- {
- if (e.getDebug())
- {
- e <<
- INDENT ".const 'Sub' __WINXED_ASSERT_check ='__WINXED_ASSERT_check'\n"
- INDENT "__WINXED_ASSERT_check(" << args[0] << ")\n";
- }
- }
- };
- const BuiltinFunction *BuiltinFunction::builtins[]= {
- new Builtin_ASSERT(),
- new Builtin_print(),
- new Builtin_say(),
- new Builtin_cry(),
- new BuiltinFunctionFixargs("int",
- "{res} = {arg0}",
- REGint, REGany),
- new BuiltinFunctionFixargs("string",
- "{res} = {arg0}",
- REGstring, REGany),
- new BuiltinFunctionFixargs("exit",
- "exit {arg0}",
- REGnone, REGint),
- new BuiltinFunctionFixargs("spawnw",
- "spawnw {res}, {arg0}",
- REGint, REGvar),
- new BuiltinFunctionFixargs("getstdin",
- "getstdin {res}",
- REGvar),
- new BuiltinFunctionFixargs("getstdout",
- "getstdout {res}",
- REGvar),
- new BuiltinFunctionFixargs("getstderr",
- "getstderr {res}",
- REGvar),
- new BuiltinFunctionFixargs("open",
- "root_new {res}, ['parrot';'FileHandle']\n"
- "{res}.'open'({arg0})",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("open",
- "root_new {res}, ['parrot';'FileHandle']\n"
- "{res}.'open'({arg0},{arg1})",
- REGvar, REGstring, REGstring),
- new BuiltinFunctionFixargs("Error",
- "root_new {res}, ['parrot';'Exception']\n"
- "{res}['message'] = {arg0}\n"
- , REGvar, REGstring),
- new BuiltinFunctionFixargs("Error",
- "root_new {res}, ['parrot';'Exception']\n"
- "{res}['message'] = {arg0}\n"
- "{res}['severity'] = {arg1}\n"
- , REGvar, REGstring, REGint),
- new BuiltinFunctionFixargs("Error",
- "root_new {res}, ['parrot';'Exception']\n"
- "{res}['message'] = {arg0}\n"
- "{res}['severity'] = {arg1}\n"
- "{res}['type'] = {arg2}\n"
- , REGvar, REGstring, REGint, REGint),
- new BuiltinFunctionFixargs("Error",
- "root_new {res}, ['parrot';'Exception']\n"
- "{res}['message'] = {arg0}\n"
- "{res}['severity'] = {arg1}\n"
- "{res}['type'] = {arg2}\n"
- "{res}['payload'] = {arg3}\n"
- , REGvar, REGstring, REGint, REGint, REGvar),
- new BuiltinFunctionFixargs("elements",
- "elements {res}, {arg0}",
- REGint, REGvar),
- new BuiltinFunctionFixargs("length",
- "length {res}, {arg0}",
- REGint, REGstring),
- new BuiltinFunctionFixargs("bytelength",
- "bytelength {res}, {arg0}",
- REGint, REGstring),
- new BuiltinFunctionFixargs("chr",
- "chr $S0, {arg0}\n"
- "find_encoding $I0, 'utf8'\n"
- "trans_encoding {res}, $S0, $I0\n",
- REGstring, REGint),
- new BuiltinFunctionFixargs("ord",
- "ord {res}, {arg0}",
- REGint, REGstring),
- new BuiltinFunctionFixargs("ord",
- "ord {res}, {arg0}, {arg1}",
- REGint, REGstring, REGint),
- new BuiltinFunctionFixargs("substr",
- "substr {res}, {arg0}, {arg1}",
- REGstring, REGstring, REGint),
- new BuiltinFunctionFixargs("substr",
- "substr {res}, {arg0}, {arg1}, {arg2}",
- REGstring, REGstring, REGint, REGint),
- new BuiltinFunctionFixargs("replace",
- "replace {res}, {arg0}, {arg1}, {arg2}, {arg3}",
- REGstring, REGstring, REGint, REGint, REGstring),
- new BuiltinFunctionFixargs("indexof",
- "index {res}, {arg0}, {arg1}",
- REGint, REGstring, REGstring),
- new BuiltinFunctionFixargs("indexof",
- "index {res}, {arg0}, {arg1}, {arg2}",
- REGint, REGstring, REGstring, REGint),
- new BuiltinFunctionFixargs("escape",
- "escape {res}, {arg0}",
- REGstring, REGstring),
- new BuiltinFunctionFixargs("unescape",
- "$P0 = new ['String']\n"
- "$P0 = {arg0}\n"
- "{res} = $P0.'unescape'('utf8')\n",
- REGstring, REGstring),
- new BuiltinFunctionFixargs("unescape",
- "$P0 = new ['String']\n"
- "$P0 = {arg0}\n"
- "{res} = $P0.'unescape'({arg1})\n",
- REGstring, REGstring, REGstring),
- new BuiltinFunctionFixargs("upcase",
- "upcase {res}, {arg0}",
- REGstring, REGstring),
- new BuiltinFunctionFixargs("downcase",
- "downcase {res}, {arg0}",
- REGstring, REGstring),
- new BuiltinFunctionFixargs("titlecase",
- "titlecase {res}, {arg0}",
- REGstring, REGstring),
- new BuiltinFunctionFixargs("join",
- "join {res}, {arg0}, {arg1}",
- REGstring, REGstring, REGvar),
- new BuiltinFunctionFixargs("split",
- "split {res}, {arg0}, {arg1}",
- REGvar, REGstring, REGstring),
- new BuiltinFunctionFixargs("push",
- "push {arg0}, {arg1}",
- REGnone, REGvar, REGany),
- new BuiltinFunctionFixargs("getinterp",
- "getinterp {res}",
- REGvar),
- new BuiltinFunctionFixargs("get_class",
- "get_class {res}, {arg0}",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("typeof",
- "typeof {res}, {arg0}",
- REGvar, REGvar),
- new BuiltinFunctionFixargs("clone",
- "clone {res}, {arg0}",
- REGvar, REGvar),
- new BuiltinFunctionFixargs("compreg",
- "compreg {res}, {arg0}",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("compreg",
- "compreg {arg0}, {arg1}",
- REGnone, REGstring, REGvar),
- new BuiltinFunctionFixargs("load_language",
- "load_language {arg0}\n"
- "compreg {res}, {arg0}",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("load_language",
- "load_language {arg0}\n"
- "compreg {res}, {arg1}",
- REGvar, REGstring, REGstring),
- new BuiltinFunctionFixargs("loadlib",
- "loadlib {res}, {arg0}",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("load_bytecode",
- "load_bytecode {arg0}",
- REGvar, REGstring),
- new BuiltinFunctionFixargs("sprintf",
- "sprintf {res}, {arg0}, {arg1}",
- REGstring, REGstring, REGvar)
- };
- const size_t BuiltinFunction::numbuiltins =
- sizeof(BuiltinFunction::builtins) / sizeof(BuiltinFunction::builtins[0]);
- const BuiltinFunction *BuiltinFunction::find(const std::string &name,
- size_t numargs)
- {
- for (size_t i= 0; i < numbuiltins; ++i) {
- int n = builtins[i]->n;
- if ((n == BuiltinFunction::VarArgs || n == int(numargs)) &&
- builtins[i]->name_is(name) )
- return builtins[i];
- }
- return 0;
- }
- BuiltinFunctionFixargs::BuiltinFunctionFixargs(const std::string &name,
- const std::string &body,
- char typeresult,
- char type0, char type1, char type2, char type3) :
- BuiltinFunction(name, typeresult,
- bool(type0) +bool(type1) + bool(type2) + bool(type3) ),
- t0(type0), t1(type1), t2(type2), t3(type3)
- {
- const size_t ntags = 5;
- const std::string tags[ntags] =
- { "{res}", "{arg0}", "{arg1}", "{arg2}", "{arg3}" };
- std::string::size_type pos[ntags];
- std::string aux = body;
- for (;;)
- {
- for (size_t i = 0; i < ntags; ++i)
- pos[i] = aux.find(tags[i]);
- const std::string::size_type *minp = std::min_element(pos, pos + ntags);
- size_t minpos = minp - pos;
- std::string::size_type mpos = pos[minpos];
- if (mpos == std::string::npos)
- break;
- chunks.push_back(aux.substr(0, mpos));
- marks.push_back(minpos);
- aux.erase(0, mpos + tags[minpos].length());
- }
- if (aux.length() > 0)
- {
- chunks.push_back(aux);
- marks.push_back(-1);
- }
- }
- void BuiltinFunctionFixargs::emit(Emit &e, const std::string &result,
- const std::vector<std::string> args) const
- {
- std::string body;
- size_t n = chunks.size();
- for (size_t i = 0; i < n; ++i)
- {
- body+= chunks[i];
- int m = marks[i];
- switch (m)
- {
- case 0:
- body+= result;
- break;
- case 1: case 2: case 3: case 4:
- body+= args[m-1];
- break;
- case -1:
- break;
- default:
- throw InternalError("Unexpected failure in builtin");
- }
- }
- size_t pos = 0;
- size_t prev = 0;
- while ((pos = body.find("\n", prev)) != std::string::npos)
- {
- e << INDENT << body.substr(prev, pos - prev + 1);
- prev = pos + 1;
- }
- e << INDENT << body.substr(prev) << '\n';
- }
- //**********************************************************************
- class Annotated
- {
- protected:
- Annotated(const Token & tstart) : start(tstart)
- { }
- public:
- void annotate(Emit &e)
- {
- e.annotate(start);
- }
- const Token & getstart() const
- {
- return start;
- }
- private:
- const Token start;
- };
- //**********************************************************************
- class ConstantValue
- {
- public:
- ConstantValue(char type, const Token &value) :
- t(type), v(value)
- {
- switch(t)
- {
- case REGint:
- if (!v.isinteger())
- throw SyntaxError("Invalid const int value", v);
- break;
- case REGstring:
- if (!v.isliteralstring())
- throw SyntaxError("Invalid const string value", v);
- break;
- case 'n':
- // Special case
- if (!v.isidentifier())
- throw SyntaxError("Invalid const string value", v);
- break;
- default:
- throw InternalError("Invalid const type");
- }
- }
- char type() const { return t; }
- Token value() const { return v; }
- private:
- char t;
- Token v;
- };
- //**********************************************************************
- class ClassStatement;
- typedef std::vector<std::string> ClassKey;
- std::string dotted(const ClassKey &ck)
- {
- size_t l = ck.size();
- if (l == 0)
- return "(anonimous)";
- else
- {
- std::string r = ck[0];
- for (size_t i = 1; i < l; ++i)
- {
- r+= '.';
- r+= ck[i];
- }
- return r;
- }
- }
- //**********************************************************************
- class FunctionStatement;
- class BlockBase
- {
- public:
- virtual char checklocal(const std::string &name) const = 0;
- virtual char checkconstant(const std::string &name) const = 0;
- virtual ConstantValue getconstant(const std::string &name) const = 0;
- virtual FunctionStatement *getfunction(const std::string &name) const = 0;
- virtual void genconstant(const std::string &name, char type, const Token &value) = 0;
- virtual std::string genlocallabel() = 0;
- virtual std::string genlocalregister(char type)= 0;
- virtual void freelocalregister(const std::string &)= 0;
- virtual std::string gentemp(char /*unused*/)
- {
- throw std::runtime_error("No temp registers here!");
- }
- virtual void freetempregs()
- {
- throw std::runtime_error("No temp registers here!");
- }
- virtual void genlocal(const std::string &name, char type) = 0;
- virtual bool islocal(std::string /*name*/) const = 0;
- virtual std::string getbreaklabel() const
- {
- throw std::runtime_error("No break allowed");
- }
- virtual std::string getcontinuelabel() const
- {
- throw std::runtime_error("No continue allowed");
- }
- virtual ClassStatement *findclass(const ClassKey &classkey)
- {
- std::cerr << "BlockBase::findclass **WRONG CALL**\n";
- return 0;
- }
- virtual ~BlockBase() { }
- };
- class Block : public BlockBase
- {
- public:
- Block();
- virtual unsigned int blockid() = 0;
- void genlocal(const std::string &name, char type);
- bool islocal(std::string name) const;
- void genconstant(const std::string &name, char type, const Token &value);
- char checklocal(const std::string &name) const;
- char checkconstant(const std::string &name) const;
- ConstantValue getconstant(const std::string &name) const;
- std::string genlabel();
- protected:
- typedef std::map<std::string, char> Locals;
- Locals locals;
- typedef std::map<std::string, ConstantValue> Constants;
- Constants constants;
- };
- class InBlock : public BlockBase
- {
- protected:
- InBlock(BlockBase &block) : bl(block) { };
- public:
- std::string getbreaklabel() const
- {
- return bl.getbreaklabel();
- }
- std::string getcontinuelabel() const
- {
- return bl.getcontinuelabel();
- }
- char checklocal(const std::string &name) const
- {
- return bl.checklocal(name);
- }
- char checkconstant(const std::string &name) const
- {
- return bl.checkconstant(name);
- }
- void genconstant(const std::string &name, char type, const Token &value)
- {
- bl.genconstant(name, type, value);
- }
- ConstantValue getconstant(const std::string &name) const
- {
- return bl.getconstant(name);
- }
- FunctionStatement *getfunction(const std::string &name) const
- {
- return bl.getfunction(name);
- }
- std::string genlocallabel()
- {
- return bl.genlocallabel();
- }
- std::string genlocalregister(char type)
- {
- return bl.genlocalregister(type);
- }
- void freelocalregister(const std::string ®)
- {
- bl.freelocalregister(reg);
- }
- std::string gentemp(char type)
- {
- return bl.gentemp(type);
- }
- void freetempregs()
- {
- bl.freetempregs();
- }
- void genlocal(const std::string &name, char type)
- {
- bl.genlocal(name, type);
- }
- bool islocal(std::string name) const
- {
- return bl.islocal(name);
- }
- ClassStatement *findclass(const ClassKey &classkey)
- {
- return bl.findclass(classkey);
- }
- private:
- BlockBase &bl;
- };
- Block::Block()
- { }
- void Block::genlocal(const std::string &name, char type)
- {
- locals[name]= type;
- }
- bool Block::islocal(std::string name) const
- {
- return locals.find(name) != locals.end();
- }
- void Block::genconstant(const std::string &name, char type, const Token &value)
- {
- constants.insert(std::make_pair(name, ConstantValue(type, value)));
- }
- char Block::checklocal(const std::string &name) const
- {
- Locals::const_iterator it= locals.find(name);
- if (it != locals.end() )
- return it->second;
- Constants::const_iterator itc= constants.find(name);
- if (itc != constants.end() )
- return itc->second.type();
- return '\0';
- }
- char Block::checkconstant(const std::string &name) const
- {
- Constants::const_iterator itc= constants.find(name);
- if (itc != constants.end() )
- return itc->second.type();
- return '\0';
- }
- ConstantValue Block::getconstant(const std::string &name) const
- {
- Constants::const_iterator itc= constants.find(name);
- if (itc != constants.end() )
- return itc->second;
- throw InternalError("No such constant");
- }
- std::string Block::genlabel()
- {
- return genlocallabel();
- }
- //**********************************************************************
- class SubBlock : public Block
- {
- public:
- SubBlock(Block &parentblock) :
- parent(parentblock),
- id(parent.blockid()),
- nlabel(0)
- {
- }
- std::string getbreaklabel() const;
- std::string getcontinuelabel() const;
- bool islocal(std::string name) const;
- char checklocal(const std::string &name) const;
- char checkconstant(const std::string &name) const;
- ConstantValue getconstant(const std::string &name) const;
- FunctionStatement *getfunction(const std::string &name) const
- {
- return parent.getfunction(name);
- }
- std::string genlocalregister(char type)
- {
- return parent.genlocalregister(type);
- }
- void freelocalregister(const std::string ®)
- {
- parent.freelocalregister(reg);
- }
- std::string gentemp(char type)
- {
- return parent.gentemp(type);
- }
- void freetempregs()
- {
- parent.freetempregs();
- }
- std::string genlocallabel();
- ClassStatement *findclass(const ClassKey &classkey)
- {
- return parent.findclass(classkey);
- }
- private:
- unsigned int blockid();
- Block &parent;
- unsigned int id;
- unsigned int nlabel;
- };
- unsigned int SubBlock::blockid()
- {
- return parent.blockid();
- }
- std::string SubBlock::getbreaklabel() const
- {
- return parent.getbreaklabel();
- }
- std::string SubBlock::getcontinuelabel() const
- {
- return parent.getcontinuelabel();
- }
- char SubBlock::checklocal(const std::string &name) const
- {
- if (char c= Block::checklocal(name))
- return c;
- else
- return parent.checklocal(name);
- }
- bool SubBlock::islocal(std::string name) const
- {
- return checklocal(name) != '\0';
- }
- char SubBlock::checkconstant(const std::string &name) const
- {
- char c= Block::checkconstant(name);
- if (c == '\0')
- c= parent.checkconstant(name);
- return c;
- }
- ConstantValue SubBlock::getconstant(const std::string &name) const
- {
- if (Block::checkconstant(name))
- return Block::getconstant(name);
- else
- return parent.getconstant(name);
- }
- std::string SubBlock::genlocallabel()
- {
- std::ostringstream l;
- l << "__label_" << id << '_' << ++nlabel;
- return l.str();
- }
- //**********************************************************************
- class NamespaceKey
- {
- typedef std::vector <std::string> key_t;
- public:
- NamespaceKey() { }
- NamespaceKey(const std::string &name) :
- key(1, name)
- {
- }
- NamespaceKey(const key_t &newkey) :
- key(newkey)
- {
- }
- bool isroot() const
- {
- return key.empty();
- }
- NamespaceKey parent() const
- {
- key_t newkey = key;
- newkey.pop_back();
- return NamespaceKey(newkey);
- }
- std::string get_key() const
- {
- std::string r= "[ ";
- for (size_t i= 0; i < key.size(); ++i)
- {
- if (i > 0)
- r+= "; ";
- r+= '\'' + key [i] + '\'';
- }
- r+= " ]";
- return r;
- }
- void emit (Emit &e) const
- {
- e << ".namespace " << get_key() << '\n';
- }
- private:
- std::vector <std::string> key;
- };
- //**********************************************************************
- class FunctionBlock : public SubBlock
- {
- public:
- FunctionBlock(Block &parent) :
- SubBlock(parent),
- subblocks(0),
- nreg(0), nlabel(0)
- {
- }
- public:
- std::string genlocallabel();
- std::string genlocalregister(char type);
- std::string gentemp(char type);
- std::string genregister(char type);
- void freelocalregister(const std::string ®);
- void freeregister(const std::string ®);
- protected:
- size_t tempsused() const
- {
- return tempi.size() + temps.size() + tempp.size() +
- + freetempi.size() + freetemps.size() + freetempp.size();
- }
- void freetempregs()
- {
- using std::copy;
- using std::back_inserter;
- copy(tempi.begin(), tempi.end(), back_inserter(freetempi));
- tempi= std::vector<std::string>();
- copy(temps.begin(), temps.end(), back_inserter(freetemps));
- temps= std::vector<std::string>();
- copy(tempp.begin(), tempp.end(), back_inserter(freetempp));
- tempp= std::vector<std::string>();
- }
- private:
- unsigned int subblocks;
- unsigned int nreg;
- unsigned int nlabel;
- std::vector <std::string> tempi;
- std::vector <std::string> temps;
- std::vector <std::string> tempp;
- std::vector <std::string> freetempi;
- std::vector <std::string> freetemps;
- std::vector <std::string> freetempp;
- };
- std::string FunctionBlock::genlocalregister(char type)
- {
- if (type != REGint && type != REGstring && type != REGvar)
- throw InternalError("invalid register type");
- std::ostringstream l;
- l << '$' << type << ++nreg;
- return l.str();
- }
- void FunctionBlock::freelocalregister(const std::string ®)
- {
- if (reg.at(0) != '$')
- throw InternalError("invalid free register");
- switch(reg.at(1))
- {
- case REGint: freetempi.push_back(reg); break;
- case REGstring: freetemps.push_back(reg); break;
- case REGvar: freetempp.push_back(reg); break;
- default: throw InternalError("invalid free register");
- }
- }
- void FunctionBlock::freeregister(const std::string ®)
- {
- return freelocalregister(reg);
- }
- std::string FunctionBlock::genregister(char type)
- {
- return genlocalregister(type);
- }
- std::string FunctionBlock::gentemp(char type)
- {
- std::vector<std::string> &usefree= type == REGint ? freetempi :
- type == REGstring ? freetemps : freetempp;
- std::string temp;
- if (usefree.size() > 0)
- {
- temp= usefree.back();
- usefree.pop_back();
- }
- else
- {
- temp= genlocalregister(type);
- switch(type)
- {
- case REGint: tempi.push_back(temp); break;
- case REGstring: temps.push_back(temp); break;
- default: tempp.push_back(temp); break;
- }
- }
- return temp;
- }
- std::string FunctionBlock::genlocallabel()
- {
- std::ostringstream l;
- l << "__label_" << ++nlabel;
- return l.str();
- }
- //**********************************************************************
- class NamespaceBlockBase;
- class Expr;
- //**********************************************************************
- class BaseStatement
- {
- public:
- virtual bool isempty() { return false; }
- virtual void emit (Emit &e) = 0;
- virtual BaseStatement *optimize() { return this; }
- void optimize_branch(BaseStatement *&branch);
- void optimize_branch(Expr *&branch);
- virtual ~BaseStatement() { };
- };
- //**********************************************************************
- class MultiStatement : public BaseStatement
- {
- public:
- MultiStatement(BaseStatement *st1, BaseStatement *st2)
- {
- subst.push_back(st1);
- subst.push_back(st2);
- }
- void push(BaseStatement *st)
- {
- subst.push_back(st);
- }
- private:
- std::vector <BaseStatement *> subst;
- BaseStatement *optimize()
- {
- for (size_t i= 0; i < subst.size(); ++i)
- subst[i] = subst[i]->optimize();
- return this;
- }
- void emit (Emit &e)
- {
- for (size_t i= 0; i < subst.size(); ++i)
- subst[i]->emit(e);
- }
- };
- BaseStatement *addtomulti(BaseStatement *oldst, BaseStatement *newst)
- {
- if (! oldst)
- return newst;
- else if (MultiStatement *multi = dynamic_cast<MultiStatement *>(oldst))
- {
- multi->push(newst);
- return multi;
- }
- else
- return new MultiStatement(oldst, newst);
- }
- //**********************************************************************
- enum ClassSpecifierType
- {
- CLASSSPECIFIER_invalid,
- CLASSSPECIFIER_parrotkey,
- CLASSSPECIFIER_id
- };
- class ClassSpecifier : public Annotated
- {
- protected:
- ClassSpecifier(const Token &t) : Annotated(t)
- { }
- public:
- virtual ClassSpecifierType reftype() const
- { return CLASSSPECIFIER_invalid; }
- virtual ~ClassSpecifier() {}
- virtual std::string basename() const = 0;
- virtual void emit(Emit &e) = 0;
- };
- ClassSpecifier *parseClassSpecifier(const Token &start, Tokenizer &tk,
- BlockBase &owner);
- //**********************************************************************
- class SubStatement : public BaseStatement, public InBlock
- {
- public:
- SubStatement(Block &block);
- };
- SubStatement::SubStatement(Block &block) :
- InBlock(block)
- {
- }
- //**********************************************************************
- class EmptyStatement : public BaseStatement
- {
- private:
- bool isempty() { return true; }
- void emit (Emit &) { };
- };
- //**********************************************************************
- class BlockStatement : public BaseStatement, public SubBlock
- {
- public:
- BlockStatement (Block &parentblock) :
- SubBlock(parentblock)
- {
- }
- };
- //**********************************************************************
- class Expr : public InBlock, public Annotated
- {
- public:
- Expr(BlockBase &block, const Token & tstart) :
- InBlock(block),
- Annotated(tstart)
- {
- }
- virtual Expr *optimize()
- {
- return this;
- }
- virtual bool isleft() const { return false; }
- virtual void emitleft(Emit &)
- {
- std::cerr << typeid(*this).name() << '\n';
- throw InternalError("Not a left-side expression");
- }
- virtual void emitleft(Emit &, const std::string &)
- {
- std::cerr << typeid(*this).name() << '\n';
- throw InternalError("Not a left-side expression");
- }
- virtual void emitassign(Emit &, Expr &, const std::string &)
- {
- std::cerr << typeid(*this).name() << '\n';
- throw InternalError("Not an assignable expression");
- }
- virtual void emit(Emit &e, const std::string &result) = 0;
- virtual std::string emit_get(Emit &e);
- virtual bool issimple() const { return false; }
- virtual const Token &gettoken() const
- {
- std::cerr << typeid(*this).name() << '\n';
- throw InternalError("In gettoken: Not a simple expression");
- }
- virtual bool isidentifier() const { return false; }
- virtual std::string getidentifier() const
- { throw InternalError("Not an identifier"); }
- virtual bool isnull() const { return false; }
- virtual bool isliteralinteger() const { return false; }
- virtual bool isinteger() const { return false; }
- virtual int getintegervalue () const
- {
- std::cerr << typeid(*this).name() << '\n';
- throw InternalError("Not an integer");
- }
- virtual bool isliteralstring() const { return false; }
- virtual std::string getstringvalue () const
- { throw InternalError("Not a string"); }
- virtual bool isstring() const { return false; }
- virtual bool isindex() const { return false; }
- char checkresult() const
- {
- if (isinteger() ) return REGint;
- else if (isstring() ) return REGstring;
- else return REGvar;
- }
- void optimize_branch(Expr *&branch)
- { branch= branch->optimize(); }
- };
- Expr * parseExpr(BlockBase &block, Tokenizer &tk);
- //**********************************************************************
- class Condition : public InBlock
- {
- public:
- Condition (Block &block, Tokenizer &tk);
- Condition (BlockBase &block, Expr *condexpr);
- Condition *optimize();
- bool issimple() const;
- bool isinteger() const { return true; }
- //bool isstring() const { return expr->isstring(); }
- bool isliteralinteger() const;
- std::string value() const;
- std::string emit(Emit &e);
- void emit_if(Emit &e, const std::string &labeltrue);
- void emit_else(Emit &e, const std::string &labelfalse);
- enum Value { CVtrue, CVfalse, CVruntime };
- Value getvalue() const;
- private:
- Expr *expr;
- };
- //**********************************************************************
- void BaseStatement::optimize_branch(BaseStatement *&branch)
- {
- if (branch)
- branch= branch->optimize();
- }
- void BaseStatement::optimize_branch(Expr *&branch)
- {
- if (branch)
- branch= branch->optimize();
- }
- //**********************************************************************
- class Modifier
- {
- public:
- Modifier(BlockBase &block, Tokenizer &tk)
- {
- Token t= tk.get();
- if (!t.isidentifier())
- throw Expected("Modifier name", t);
- start = t;
- name= t.identifier();
- t= tk.get();
- if (!t.isop('('))
- tk.unget(t);
- else
- {
- do
- {
- args.push_back(parseExpr(block, tk));
- } while ((t= tk.get()).isop(','));
- RequireOp(')', t);
- }
- }
- std::string getname() const { return name; }
- Token getstart() const { return start; }
- void optimize()
- {
- for (size_t i= 0; i < args.size(); ++i)
- args[i]= args[i]->optimize();
- }
- size_t numargs() const { return args.size(); }
- Expr *getarg(size_t narg) const
- {
- return args.at(narg);
- }
- int getintegervalue(size_t narg) const
- {
- Expr *arg= args.at(narg);
- return arg->getintegervalue();
- }
- std::string getstringvalue(size_t narg) const
- {
- Expr *arg= args.at(narg);
- return arg->getstringvalue();
- }
- private:
- Token start;
- std::string name;
- std::vector <Expr *> args;
- };
- //**********************************************************************
- class ModifierList
- {
- public:
- bool has_modifier(const std::string &name) const
- {
- return modifiers.find(name) != modifiers.end();
- }
- const Modifier * getmodifier(const std::string &name) const
- {
- ModList::const_iterator it= modifiers.find(name);
- if (it != modifiers.end())
- return &it->second;
- else
- return NULL;
- }
- void parse(BlockBase &block, Tokenizer &tk)
- {
- Token t;
- do {
- Modifier m(block, tk);
- std::string name= m.getname();
- modifiers.insert(std::make_pair(name, m));
- } while ((t= tk.get()).isop(','));
- RequireOp(']', t);
- }
- void optimize()
- {
- for (ModList::iterator it= modifiers.begin();
- it != modifiers.end(); ++it)
- it->second.optimize();
- }
- protected:
- typedef std::map<std::string, Modifier> ModList;
- ModList modifiers;
- };
- //**********************************************************************
- class FunctionModifiers : public ModifierList
- {
- public:
- FunctionModifiers(BlockBase &block, Tokenizer &tk)
- {
- Token t= tk.get();
- if (! t.isop('[') )
- tk.unget(t);
- else
- parse(block, tk);
- }
- };
- //**********************************************************************
- class ArgumentModifierList : public ModifierList
- {
- public:
- void emitmodifiers(Emit &e)
- {
- bool isflat = false, isnamed = false;
- Expr * setname = 0;
- for (ModList::iterator it = modifiers.begin(); it != modifiers.end();
- ++it)
- {
- std::string name = it->first;
- Modifier &modifier = it->second;
- if (name == "flat")
- isflat = true;
- if (name == "named")
- {
- isnamed = true;
- switch (modifier.numargs())
- {
- case 0:
- break;
- case 1:
- setname = modifier.getarg(0);
- break;
- default:
- throw SyntaxError("Invalid modifier", modifier.getstart());
- }
- }
- }
- if (isflat)
- {
- if (isnamed)
- e << " :flat :named";
- else
- e << " :flat";
- }
- else if (isnamed)
- {
- e << " :named";
- if (setname)
- e << '(';
- setname->emit(e, "");
- e << ')';
- }
- }
- };
- class Argument
- {
- public:
- Argument(BlockBase &block, Tokenizer &tk) :
- modifiers(0)
- {
- expr = parseExpr(block, tk);
- Token t = tk.get();
- if (t.isop(':'))
- {
- t = tk.get();
- if (! t.isop('['))
- throw Expected("modifier list", t);
- modifiers = new ArgumentModifierList();
- modifiers->parse(block, tk);
- }
- else
- tk.unget(t);
- }
- Expr *get()
- {
- return expr;
- }
- ArgumentModifierList *getmodifiers()
- {
- return modifiers;
- }
- Argument *optimize()
- {
- expr= expr->optimize();
- return this;
- }
- void emit(Emit &e, const std::string &result)
- {
- expr->emit(e, result);
- }
- private:
- Expr *expr;
- ArgumentModifierList *modifiers;
- };
- class ArgumentList : public InBlock
- {
- public:
- ArgumentList(BlockBase &block, Tokenizer &tk, char delimiter);
- int numargs() const
- {
- return args ? args->size() : 0;
- }
- Expr *getfreearg(int i)
- {
- return args->at(i)->get();
- }
- void optimize();
- void prepare(Emit &e);
- void emit(Emit &e);
- private:
- std::vector <Argument *> *args;
- std::vector <std::string> argregs;
- };
- //**********************************************************************
- class ExprStatement : public BaseStatement
- {
- public:
- ExprStatement(Block &parentblock, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Expr *expr;
- };
- //**********************************************************************
- class CompoundStatement : public BlockStatement
- {
- public:
- CompoundStatement(Block &parentblock, Tokenizer &tk);
- BaseStatement *optimize();
- void emit (Emit &e);
- Token getend() const { return tend; }
- private:
- std::vector <BaseStatement *> subst;
- Token tend;
- };
- //**********************************************************************
- class ValueStatement : public SubStatement, public Annotated
- {
- public:
- ValueStatement(Block & block, const Token & tstart);
- protected:
- void parseArray(Tokenizer &tk);
- void emit (Emit &e, const std::string &name, char type);
- enum ValueType { ValueSimple, ValueArray, ValueFixedArray };
- ValueType vtype;
- Expr *esize;
- std::vector<Expr *> value;
- private:
- BaseStatement *optimize();
- };
- //**********************************************************************
- class IntStatement : public ValueStatement
- {
- public:
- IntStatement(Block & block, const Token &st, Tokenizer &tk);
- void emit (Emit &e);
- using ValueStatement::emit;
- private:
- std::string name;
- };
- //**********************************************************************
- class StringStatement : public ValueStatement
- {
- public:
- StringStatement(Block & block, const Token &st, Tokenizer &tk);
- void emit (Emit &e);
- using ValueStatement::emit;
- private:
- std::string name;
- };
- //**********************************************************************
- template <class DECST>
- BaseStatement *parseDeclare(Block & block, const Token &st, Tokenizer &tk)
- {
- BaseStatement *multi = 0;
- Token t;
- do {
- BaseStatement *item = new DECST(block, st, tk);
- multi = addtomulti(multi, item);
- t= tk.get();
- } while (t.isop(','));
- RequireOp (';', t);
- return multi;
- }
- //**********************************************************************
- class VarStatement : public ValueStatement
- {
- public:
- VarStatement(Block & block, const Token &st, Tokenizer &tk);
- void emit (Emit &e);
- private:
- std::string name;
- };
- //**********************************************************************
- class ConstStatement : public ValueStatement
- {
- public:
- ConstStatement(Block & block, const Token &st, Tokenizer &tk, char typed);
- BaseStatement *optimize();
- void emit (Emit &e);
- private:
- char type;
- std::string name;
- Expr *value;
- };
- BaseStatement * parseConst(Block & block, const Token &st, Tokenizer &tk);
- //**********************************************************************
- class LabelStatement: public SubStatement
- {
- public:
- LabelStatement(Block &block, const std::string &name);
- void emit (Emit &e);
- private:
- std::string labelname;
- std::string codename;
- };
- //**********************************************************************
- class ReturnStatement : public SubStatement, public Annotated
- {
- public:
- ReturnStatement(Block & block, const Token & tstart, Tokenizer &tk);
- BaseStatement *optimize();
- void emit (Emit &e);
- private:
- ArgumentList *values;
- };
- //**********************************************************************
- class BreakStatement : public SubStatement
- {
- public:
- BreakStatement(Block &block, Tokenizer &tk) :
- SubStatement(block)
- {
- ExpectOp(';', tk);
- }
- private:
- void emit (Emit &e)
- {
- e << INDENT "goto " << getbreaklabel() << " # break\n";
- }
- };
- //**********************************************************************
- class ContinueStatement : public SubStatement
- {
- public:
- ContinueStatement(Block &block, Tokenizer &tk) :
- SubStatement(block)
- {
- ExpectOp(';', tk);
- }
- private:
- void emit (Emit &e)
- {
- e << INDENT "goto " << getcontinuelabel() << " # continue\n";
- }
- };
- //**********************************************************************
- class BreakableStatement : public BlockStatement
- {
- protected:
- BreakableStatement(Block &block) :
- BlockStatement(block)
- { }
- std::string getbreaklabel() const
- {
- if (breaklabel.empty())
- throw InternalError("attempt to use break label before creating");
- return breaklabel;
- }
- std::string genbreaklabel()
- {
- if (! breaklabel.empty())
- throw InternalError("attempt to create break label twice");
- breaklabel = genlabel();
- return breaklabel;
- }
- private:
- std::string breaklabel;
- };
- class ContinuableStatement : public BreakableStatement
- {
- protected:
- ContinuableStatement(Block &block) :
- BreakableStatement(block)
- { }
- std::string getcontinuelabel() const
- {
- if (continuelabel.empty())
- throw InternalError("attempt to use continue label before creating");
- return continuelabel;
- }
- std::string gencontinuelabel()
- {
- if (! continuelabel.empty())
- throw InternalError("attempt to create continue label twice");
- continuelabel = genlabel();
- return continuelabel;
- }
- private:
- std::string continuelabel;
- };
- //**********************************************************************
- class SwitchBaseStatement : public BreakableStatement
- {
- protected:
- SwitchBaseStatement(Block &block);
- void parse_cases(Tokenizer &tk);
- std::vector<Expr *> casevalue;
- std::vector<std::vector<BaseStatement *> > casest;
- std::vector<BaseStatement *> defaultst;
- BaseStatement *optimize();
- };
- class SwitchStatement : public SwitchBaseStatement
- {
- public:
- SwitchStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Expr *condition;
- };
- class SwitchCaseStatement : public SwitchBaseStatement
- {
- public:
- SwitchCaseStatement(Block &block, Tokenizer &tk);
- private:
- void emit (Emit &e);
- };
- //**********************************************************************
- class IfStatement : public BlockStatement
- {
- public:
- IfStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Condition *condition;
- BaseStatement *st;
- BaseStatement *stelse;
- };
- //**********************************************************************
- class WhileStatement : public ContinuableStatement
- {
- public:
- WhileStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Condition *condition;
- BaseStatement *st;
- };
- //**********************************************************************
- class DoStatement : public ContinuableStatement
- {
- public:
- DoStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Condition *condition;
- BaseStatement *st;
- };
- //**********************************************************************
- class ForeachStatement : public ContinuableStatement
- {
- public:
- ForeachStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Token start;
- std::string varname;
- char vartype;
- Expr * container;
- BaseStatement *st;
- };
- //**********************************************************************
- class ForStatement : public ContinuableStatement
- {
- public:
- ForStatement(Block &block, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- BaseStatement * initializer;
- Expr * condition;
- Expr * iteration;
- BaseStatement *st;
- };
- //**********************************************************************
- class ThrowStatement : public SubStatement
- {
- public:
- ThrowStatement(Block &block, const Token &st, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- Token pos;
- Expr * excep;
- };
- //**********************************************************************
- class TryStatement : public BlockStatement, public Annotated
- {
- public:
- TryStatement(Block &block, const Token &st, Tokenizer &tk);
- private:
- BaseStatement *optimize();
- void emit (Emit &e);
- BaseStatement *stry;
- BaseStatement *scatch;
- std::string exname;
- };
- //**********************************************************************
- class FunctionParameter
- {
- public:
- FunctionParameter(FunctionStatement *owner, Tokenizer &tk);
- char gettype() const { return type; }
- std::string getname() const { return name; }
- void emit (Emit &e);
- private:
- std::string name;
- char type;
- ModifierList modifiers;
- bool has_modifier(const std::string &name) const
- {
- return modifiers.has_modifier(name);
- }
- };
- //**********************************************************************
- class FunctionStatement : protected FunctionModifiers, public FunctionBlock,
- public Annotated
- {
- public:
- FunctionStatement(Tokenizer &tk, const Token & tstart,
- Block &parent,
- const std::string &funcname);
- virtual std::string getsubid() const;
- std::string getname() const { return name; }
- void optimize();
- virtual void emit (Emit &e);
- void local(std::string name);
- bool islocal(std::st…