PageRenderTime 512ms CodeModel.GetById 14ms app.highlight 460ms RepoModel.GetById 1ms app.codeStats 1ms

/winxedst0.cpp

http://github.com/NotFound/winxed
C++ | 6494 lines | 5816 code | 541 blank | 137 comment | 792 complexity | 48432d18214d862feaa6834e8061c257 MD5 | raw file
   1// winxedst0.cpp
   2// Revision 25-jun-2012
   3
   4// Winxed compiler stage 0.
   5
   6#include "token.h"
   7#include "errors.h"
   8#include "emit.h"
   9
  10#include <string>
  11#include <iostream>
  12#include <istream>
  13#include <fstream>
  14#include <sstream>
  15#include <cctype>
  16#include <vector>
  17#include <map>
  18#include <algorithm>
  19#include <stdexcept>
  20
  21#include <string.h>
  22#include <errno.h>
  23
  24#include <typeinfo>
  25
  26//**********************************************************************
  27
  28// Register types
  29const char REGint    = 'I';
  30const char REGstring = 'S';
  31const char REGvar    = 'P';
  32// Pseudotypes for builtins
  33const char REGany    = '?';
  34const char REGnone   = '\0'; // void return
  35
  36static const char * nameoftype(char ctype)
  37{
  38    switch (ctype)
  39    {
  40    case REGint:    return "int";
  41    case REGstring: return "string";
  42    case REGvar:    return "pmc";
  43    default:
  44        throw CompileError("Invalid type");
  45    }
  46}
  47
  48char nativetype(const Token &name)
  49{
  50    if (name.iskeyword("int")) return REGint;
  51    else if (name.iskeyword("string")) return REGstring;
  52    else if (name.iskeyword("var")) return REGvar;
  53    else return '\0';
  54}
  55
  56//**********************************************************************
  57
  58#define INDENT "    "
  59#define INDENTLABEL "  "
  60
  61inline
  62std::string op(const char *name, const std::string &op1)
  63{
  64    return INDENT + std::string(name) + ' ' + op1;
  65}
  66
  67inline
  68std::string op(const char *name,
  69    const std::string &op1, const std::string &op2)
  70{
  71    return INDENT + std::string(name) + ' ' + op1 + ", " + op2;
  72}
  73
  74inline
  75std::string op(const char *name,
  76    const std::string &op1,
  77    const std::string &op2, const std::string &op3)
  78{
  79    return INDENT + std::string(name) + ' ' + op1 + ", " + op2 + ", " + op3;
  80}
  81
  82inline
  83std::string op_inc(const std::string &op1)
  84{
  85    return op("inc", op1);
  86}
  87
  88inline
  89std::string op_dec(const std::string &op1)
  90{
  91    return op("dec", op1);
  92}
  93
  94inline
  95std::string op_set(const std::string &res, const std::string &op1)
  96{
  97    return op("set", res, op1);
  98}
  99
 100inline
 101std::string op_assign(const std::string &res, const std::string &op1)
 102{
 103    return op("assign", res, op1);
 104}
 105
 106inline
 107std::string op_box(const std::string &res, const std::string &op1)
 108{
 109    return op("box", res, op1);
 110}
 111
 112inline
 113std::string op_add(const std::string &res,
 114    const std::string &op1, const std::string &op2)
 115{
 116    return op("add", res, op1, op2);
 117}
 118
 119inline
 120std::string op_sub(const std::string &res,
 121    const std::string &op1, const std::string &op2)
 122{
 123    return op("sub", res, op1, op2);
 124}
 125
 126inline
 127std::string op_mul(const std::string &res,
 128    const std::string &op1, const std::string &op2)
 129{
 130    return op("mul", res, op1, op2);
 131}
 132
 133inline
 134std::string op_div(const std::string &res,
 135    const std::string &op1, const std::string &op2)
 136{
 137    return op("div", res, op1, op2);
 138}
 139
 140inline
 141std::string op_mod(const std::string &res,
 142    const std::string &op1, const std::string &op2)
 143{
 144    return op("mod", res, op1, op2);
 145}
 146
 147inline
 148std::string op_cmod(const std::string &res,
 149    const std::string &op1, const std::string &op2)
 150{
 151    return op("cmod", res, op1, op2);
 152}
 153
 154inline
 155std::string op_null(const std::string &res)
 156{
 157    return op("null", res);
 158}
 159
 160inline
 161std::string op_isnull(const std::string &res, const std::string &op1)
 162{
 163    return op("isnull", res, op1);
 164}
 165
 166inline
 167std::string op_iseq(const std::string &res,
 168    const std::string &op1, const std::string &op2)
 169{
 170    return op("iseq", res, op1, op2);
 171}
 172
 173inline
 174std::string op_isne(const std::string &res,
 175    const std::string &op1, const std::string &op2)
 176{
 177    return op("isne", res, op1, op2);
 178}
 179
 180inline
 181std::string op_islt(const std::string &res,
 182    const std::string &op1, const std::string &op2)
 183{
 184    return op("islt", res, op1, op2);
 185}
 186
 187inline
 188std::string op_isgt(const std::string &res,
 189    const std::string &op1, const std::string &op2)
 190{
 191    return op("isgt", res, op1, op2);
 192}
 193
 194inline
 195std::string op_isle(const std::string &res,
 196    const std::string &op1, const std::string &op2)
 197{
 198    return op("isle", res, op1, op2);
 199}
 200
 201inline
 202std::string op_isge(const std::string &res,
 203    const std::string &op1, const std::string &op2)
 204{
 205    return op("isge", res, op1, op2);
 206}
 207
 208inline
 209std::string op_isa(const std::string &res,
 210    const std::string &op1, const std::string &op2)
 211{
 212    return op("isa", res, op1, op2);
 213}
 214
 215//**********************************************************************
 216
 217inline void RequireOp(char name, const Token &t)
 218{
 219    if (! t.isop(name) )
 220        throw Expected (name, t);
 221}
 222
 223inline void ExpectOp(char name, Tokenizer &tk)
 224{
 225    Token t= tk.get();
 226    RequireOp(name, t);
 227}
 228
 229//**********************************************************************
 230
 231template <typename T>
 232void emit_group(const std::vector<T *> &group, Emit &e)
 233{
 234    for (size_t i= 0; i < group.size(); ++i)
 235        group[i]->emit(e);
 236}
 237
 238//**********************************************************************
 239
 240class BuiltinFunction
 241{
 242public:
 243    static const int VarArgs = -1;
 244    BuiltinFunction(const std::string &name, char typeresult, int nargs) :
 245        pname(name),
 246        tresult(typeresult),
 247        n(nargs)
 248    {
 249    }
 250    BuiltinFunction(const std::string &name, char typeresult) :
 251        pname(name),
 252        tresult(typeresult),
 253        n(VarArgs)
 254    {
 255    }
 256    static const BuiltinFunction *find(const std::string &name,
 257        size_t numargs);
 258    bool name_is(const std::string &name) const
 259    { return pname == name; }
 260    size_t numargs() const { return n; }
 261    char resulttype() const { return tresult; }
 262
 263    virtual char paramtype(size_t n) const = 0;
 264    virtual void emit(Emit &e, const std::string &result,
 265        const std::vector<std::string> args) const = 0;
 266private:
 267    static const BuiltinFunction *builtins[];
 268    static const size_t numbuiltins;
 269    const std::string pname;
 270    char tresult;
 271    unsigned int n;
 272};
 273
 274class BuiltinFunctionFixargs : public BuiltinFunction
 275{
 276public:
 277    BuiltinFunctionFixargs(const std::string &name,
 278            const std::string &body,
 279            char typeresult,
 280            char type0= '\0',
 281            char type1= '\0',
 282            char type2= '\0',
 283            char type3= '\0');
 284private:
 285    void emit(Emit &e, const std::string &result,
 286        const std::vector<std::string> args) const;
 287    char paramtype(size_t n) const
 288    {
 289        switch(n)
 290        {
 291        case 0: return t0;
 292        case 1: return t1;
 293        case 2: return t2;
 294        case 3: return t3;
 295        default: return '\0';
 296        }
 297    }
 298    char t0, t1, t2, t3;
 299    std::vector<std::string> chunks;
 300    std::vector<int> marks;
 301};
 302
 303class BuiltinFunctionVarargs : public BuiltinFunction
 304{
 305protected:
 306    BuiltinFunctionVarargs(const std::string &name,
 307            char typeresult) :
 308        BuiltinFunction(name, typeresult)
 309    { }
 310    char paramtype(size_t /*unused*/) const
 311    {
 312        return REGany;
 313    }
 314};
 315
 316class Builtin_print : public BuiltinFunctionVarargs
 317{
 318public:
 319    Builtin_print() : BuiltinFunctionVarargs("print", REGnone)
 320    { }
 321private:
 322    void emit(Emit &e, const std::string &,
 323        const std::vector<std::string> args) const
 324    {
 325        const size_t n = args.size();
 326        for (size_t i= 0; i < n; ++i)
 327            e << INDENT "print " << args[i] << '\n';
 328    }
 329};
 330
 331class Builtin_say : public BuiltinFunctionVarargs
 332{
 333public:
 334    Builtin_say() : BuiltinFunctionVarargs("say", REGnone)
 335    { }
 336private:
 337    void emit(Emit &e, const std::string &,
 338        const std::vector<std::string> args) const
 339    {
 340        const size_t n = args.size();
 341        if (n > 0) {
 342            for (size_t i= 0; i < n - 1; ++i)
 343                e << INDENT "print " << args[i] << '\n';
 344            e << INDENT "say " << args[n-1] << '\n';
 345        }
 346        else
 347            e << INDENT "say ''\n";
 348    }
 349};
 350
 351class Builtin_cry : public BuiltinFunctionVarargs
 352{
 353public:
 354    Builtin_cry() : BuiltinFunctionVarargs("cry", REGnone)
 355    { }
 356private:
 357    void emit(Emit &e, const std::string &,
 358        const std::vector<std::string> args) const
 359    {
 360        e <<
 361            INDENT "getstderr $P0\n";
 362        const size_t n = args.size();
 363        for (size_t i= 0; i < n; ++i)
 364            e << INDENT "$P0.'print'(" << args[i] << ")\n";
 365        e << INDENT "$P0.'print'(\"\\n\")\n";
 366    }
 367};
 368
 369class Builtin_ASSERT : public BuiltinFunction
 370{
 371public:
 372    Builtin_ASSERT() : BuiltinFunction("__ASSERT__", REGnone, 1)
 373    { }
 374    char paramtype(size_t n) const { return REGint; }
 375    void emit(Emit &e, const std::string &,
 376        const std::vector<std::string> args) const
 377    {
 378         if (e.getDebug())
 379         {
 380             e <<
 381                 INDENT ".const 'Sub' __WINXED_ASSERT_check ='__WINXED_ASSERT_check'\n"
 382                 INDENT "__WINXED_ASSERT_check(" << args[0] << ")\n";
 383         }
 384    }
 385};
 386
 387const BuiltinFunction *BuiltinFunction::builtins[]= {
 388    new Builtin_ASSERT(),
 389    new Builtin_print(),
 390    new Builtin_say(),
 391    new Builtin_cry(),
 392    new BuiltinFunctionFixargs("int",
 393        "{res} = {arg0}",
 394        REGint, REGany),
 395    new BuiltinFunctionFixargs("string",
 396        "{res} = {arg0}",
 397        REGstring, REGany),
 398    new BuiltinFunctionFixargs("exit",
 399        "exit {arg0}",
 400        REGnone, REGint),
 401    new BuiltinFunctionFixargs("spawnw",
 402        "spawnw {res}, {arg0}",
 403        REGint, REGvar),
 404    new BuiltinFunctionFixargs("getstdin",
 405        "getstdin {res}",
 406        REGvar),
 407    new BuiltinFunctionFixargs("getstdout",
 408        "getstdout {res}",
 409        REGvar),
 410    new BuiltinFunctionFixargs("getstderr",
 411        "getstderr {res}",
 412        REGvar),
 413    new BuiltinFunctionFixargs("open",
 414        "root_new {res}, ['parrot';'FileHandle']\n"
 415        "{res}.'open'({arg0})",
 416        REGvar, REGstring),
 417    new BuiltinFunctionFixargs("open",
 418        "root_new {res}, ['parrot';'FileHandle']\n"
 419        "{res}.'open'({arg0},{arg1})",
 420        REGvar, REGstring, REGstring),
 421    new BuiltinFunctionFixargs("Error",
 422        "root_new {res}, ['parrot';'Exception']\n"
 423        "{res}['message'] = {arg0}\n"
 424        , REGvar, REGstring),
 425    new BuiltinFunctionFixargs("Error",
 426        "root_new {res}, ['parrot';'Exception']\n"
 427        "{res}['message'] = {arg0}\n"
 428        "{res}['severity'] = {arg1}\n"
 429        , REGvar, REGstring, REGint),
 430    new BuiltinFunctionFixargs("Error",
 431        "root_new {res}, ['parrot';'Exception']\n"
 432        "{res}['message'] = {arg0}\n"
 433        "{res}['severity'] = {arg1}\n"
 434        "{res}['type'] = {arg2}\n"
 435        , REGvar, REGstring, REGint, REGint),
 436    new BuiltinFunctionFixargs("Error",
 437        "root_new {res}, ['parrot';'Exception']\n"
 438        "{res}['message'] = {arg0}\n"
 439        "{res}['severity'] = {arg1}\n"
 440        "{res}['type'] = {arg2}\n"
 441        "{res}['payload'] = {arg3}\n"
 442        , REGvar, REGstring, REGint, REGint, REGvar),
 443    new BuiltinFunctionFixargs("elements",
 444        "elements {res}, {arg0}",
 445        REGint, REGvar),
 446    new BuiltinFunctionFixargs("length",
 447        "length {res}, {arg0}",
 448        REGint, REGstring),
 449    new BuiltinFunctionFixargs("bytelength",
 450        "bytelength {res}, {arg0}",
 451        REGint, REGstring),
 452    new BuiltinFunctionFixargs("chr",
 453        "chr $S0, {arg0}\n"
 454        "find_encoding $I0, 'utf8'\n"
 455        "trans_encoding {res}, $S0, $I0\n",
 456        REGstring, REGint),
 457    new BuiltinFunctionFixargs("ord",
 458        "ord {res}, {arg0}",
 459        REGint, REGstring),
 460    new BuiltinFunctionFixargs("ord",
 461        "ord {res}, {arg0}, {arg1}",
 462        REGint, REGstring, REGint),
 463    new BuiltinFunctionFixargs("substr",
 464        "substr {res}, {arg0}, {arg1}",
 465        REGstring, REGstring, REGint),
 466    new BuiltinFunctionFixargs("substr",
 467        "substr {res}, {arg0}, {arg1}, {arg2}",
 468        REGstring, REGstring, REGint, REGint),
 469    new BuiltinFunctionFixargs("replace",
 470        "replace {res}, {arg0}, {arg1}, {arg2}, {arg3}",
 471        REGstring, REGstring, REGint, REGint, REGstring),
 472    new BuiltinFunctionFixargs("indexof",
 473        "index {res}, {arg0}, {arg1}",
 474        REGint, REGstring, REGstring),
 475    new BuiltinFunctionFixargs("indexof",
 476        "index {res}, {arg0}, {arg1}, {arg2}",
 477        REGint, REGstring, REGstring, REGint),
 478    new BuiltinFunctionFixargs("escape",
 479        "escape {res}, {arg0}",
 480        REGstring, REGstring),
 481    new BuiltinFunctionFixargs("unescape",
 482        "$P0 = new ['String']\n"
 483        "$P0 = {arg0}\n"
 484        "{res} = $P0.'unescape'('utf8')\n",
 485        REGstring, REGstring),
 486    new BuiltinFunctionFixargs("unescape",
 487        "$P0 = new ['String']\n"
 488        "$P0 = {arg0}\n"
 489        "{res} = $P0.'unescape'({arg1})\n",
 490        REGstring, REGstring, REGstring),
 491    new BuiltinFunctionFixargs("upcase",
 492        "upcase {res}, {arg0}",
 493        REGstring, REGstring),
 494    new BuiltinFunctionFixargs("downcase",
 495        "downcase {res}, {arg0}",
 496        REGstring, REGstring),
 497    new BuiltinFunctionFixargs("titlecase",
 498        "titlecase {res}, {arg0}",
 499        REGstring, REGstring),
 500    new BuiltinFunctionFixargs("join",
 501        "join {res}, {arg0}, {arg1}",
 502        REGstring, REGstring, REGvar),
 503    new BuiltinFunctionFixargs("split",
 504        "split {res}, {arg0}, {arg1}",
 505        REGvar, REGstring, REGstring),
 506    new BuiltinFunctionFixargs("push",
 507        "push {arg0}, {arg1}",
 508        REGnone, REGvar, REGany),
 509    new BuiltinFunctionFixargs("getinterp",
 510        "getinterp {res}",
 511        REGvar),
 512    new BuiltinFunctionFixargs("get_class",
 513        "get_class {res}, {arg0}",
 514        REGvar, REGstring),
 515    new BuiltinFunctionFixargs("typeof",
 516        "typeof {res}, {arg0}",
 517        REGvar, REGvar),
 518    new BuiltinFunctionFixargs("clone",
 519        "clone {res}, {arg0}",
 520        REGvar, REGvar),
 521    new BuiltinFunctionFixargs("compreg",
 522        "compreg {res}, {arg0}",
 523        REGvar, REGstring),
 524    new BuiltinFunctionFixargs("compreg",
 525        "compreg {arg0}, {arg1}",
 526        REGnone, REGstring, REGvar),
 527    new BuiltinFunctionFixargs("load_language",
 528        "load_language {arg0}\n"
 529        "compreg {res}, {arg0}",
 530        REGvar, REGstring),
 531    new BuiltinFunctionFixargs("load_language",
 532        "load_language {arg0}\n"
 533        "compreg {res}, {arg1}",
 534        REGvar, REGstring, REGstring),
 535    new BuiltinFunctionFixargs("loadlib",
 536        "loadlib {res}, {arg0}",
 537        REGvar, REGstring),
 538    new BuiltinFunctionFixargs("load_bytecode",
 539        "load_bytecode {arg0}",
 540        REGvar, REGstring),
 541    new BuiltinFunctionFixargs("sprintf",
 542        "sprintf {res}, {arg0}, {arg1}",
 543        REGstring, REGstring, REGvar)
 544};
 545
 546const size_t BuiltinFunction::numbuiltins =
 547    sizeof(BuiltinFunction::builtins) / sizeof(BuiltinFunction::builtins[0]);
 548
 549const BuiltinFunction *BuiltinFunction::find(const std::string &name,
 550    size_t numargs)
 551{
 552    for (size_t i= 0; i < numbuiltins; ++i) {
 553        int n = builtins[i]->n;
 554        if ((n == BuiltinFunction::VarArgs || n == int(numargs)) &&
 555                builtins[i]->name_is(name) )
 556            return builtins[i];
 557    }
 558    return 0;
 559}
 560
 561BuiltinFunctionFixargs::BuiltinFunctionFixargs(const std::string &name,
 562            const std::string &body,
 563            char typeresult,
 564            char type0, char type1, char type2, char type3) :
 565        BuiltinFunction(name, typeresult,
 566                bool(type0) +bool(type1) + bool(type2) + bool(type3) ),
 567        t0(type0), t1(type1), t2(type2), t3(type3)
 568{
 569    const size_t ntags = 5;
 570    const std::string tags[ntags] =
 571        { "{res}", "{arg0}", "{arg1}", "{arg2}", "{arg3}" };
 572    std::string::size_type pos[ntags];
 573
 574    std::string aux = body;
 575
 576    for (;;)
 577    {
 578        for (size_t i = 0; i < ntags; ++i)
 579            pos[i] = aux.find(tags[i]);
 580        const std::string::size_type *minp = std::min_element(pos, pos + ntags);
 581        size_t minpos = minp - pos;
 582        std::string::size_type mpos = pos[minpos];
 583        if (mpos == std::string::npos)
 584            break;
 585        chunks.push_back(aux.substr(0, mpos));
 586        marks.push_back(minpos);
 587        aux.erase(0, mpos + tags[minpos].length());
 588    }
 589    if (aux.length() > 0)
 590    {
 591        chunks.push_back(aux);
 592        marks.push_back(-1);
 593    }
 594}
 595
 596void BuiltinFunctionFixargs::emit(Emit &e, const std::string &result,
 597    const std::vector<std::string> args) const
 598{
 599    std::string body;
 600    size_t n = chunks.size();
 601    for (size_t i = 0; i < n; ++i)
 602    {
 603        body+= chunks[i];
 604        int m = marks[i];
 605        switch (m)
 606        {
 607          case 0:
 608            body+= result;
 609            break;
 610          case 1: case 2: case 3: case 4:
 611            body+= args[m-1];
 612            break;
 613          case -1:
 614            break;
 615          default:
 616            throw InternalError("Unexpected failure in builtin");
 617        }
 618    }
 619
 620    size_t pos = 0;
 621    size_t prev = 0;
 622    while ((pos = body.find("\n", prev)) != std::string::npos)
 623    {
 624        e << INDENT << body.substr(prev, pos - prev + 1);
 625        prev = pos + 1;
 626    }
 627    e << INDENT << body.substr(prev) << '\n';
 628}
 629
 630//**********************************************************************
 631
 632class Annotated
 633{
 634protected:
 635    Annotated(const Token & tstart) : start(tstart)
 636    { }
 637public:
 638    void annotate(Emit &e)
 639    {
 640        e.annotate(start);
 641    }
 642    const Token & getstart() const
 643    {
 644        return start;
 645    }
 646private:
 647    const Token start;
 648};
 649
 650//**********************************************************************
 651
 652class ConstantValue
 653{
 654public:
 655    ConstantValue(char type, const Token &value) :
 656        t(type), v(value)
 657    {
 658        switch(t)
 659        {
 660        case REGint:
 661            if (!v.isinteger())
 662                throw SyntaxError("Invalid const int value", v);
 663            break;
 664        case REGstring:
 665            if (!v.isliteralstring())
 666                throw SyntaxError("Invalid const string value", v);
 667            break;
 668        case 'n':
 669            // Special case
 670            if (!v.isidentifier())
 671                throw SyntaxError("Invalid const string value", v);
 672            break;
 673        default:
 674            throw InternalError("Invalid const type");
 675        }
 676    }
 677    char type() const { return t; }
 678    Token value() const { return v; }
 679private:
 680    char t;
 681    Token v;
 682};
 683
 684//**********************************************************************
 685
 686class ClassStatement;
 687
 688typedef std::vector<std::string> ClassKey;
 689
 690std::string dotted(const ClassKey &ck)
 691{
 692    size_t l = ck.size();
 693    if (l == 0)
 694        return "(anonimous)";
 695    else
 696    {
 697        std::string r = ck[0];
 698        for (size_t i = 1; i < l; ++i)
 699        {
 700            r+= '.';
 701            r+= ck[i];
 702        }
 703        return r;
 704    }
 705}
 706
 707//**********************************************************************
 708
 709class FunctionStatement;
 710
 711class BlockBase
 712{
 713public:
 714    virtual char checklocal(const std::string &name) const = 0;
 715    virtual char checkconstant(const std::string &name) const = 0;
 716    virtual ConstantValue getconstant(const std::string &name) const = 0;
 717    virtual FunctionStatement *getfunction(const std::string &name) const = 0;
 718    virtual void genconstant(const std::string &name, char type, const Token &value) = 0;
 719    virtual std::string genlocallabel() = 0;
 720    virtual std::string genlocalregister(char type)= 0;
 721    virtual void freelocalregister(const std::string &)= 0;
 722    virtual std::string gentemp(char /*unused*/)
 723    {
 724        throw std::runtime_error("No temp registers here!");
 725    }
 726    virtual void freetempregs()
 727    {
 728        throw std::runtime_error("No temp registers here!");
 729    }
 730    virtual void genlocal(const std::string &name, char type) = 0;
 731    virtual bool islocal(std::string /*name*/) const = 0;
 732    virtual std::string getbreaklabel() const
 733    {
 734        throw std::runtime_error("No break allowed");
 735    }
 736    virtual std::string getcontinuelabel() const
 737    {
 738        throw std::runtime_error("No continue allowed");
 739    }
 740    virtual ClassStatement *findclass(const ClassKey &classkey)
 741    {
 742        std::cerr << "BlockBase::findclass **WRONG CALL**\n";
 743        return 0;
 744    }
 745    virtual ~BlockBase() { }
 746};
 747
 748class Block : public BlockBase
 749{
 750public:
 751    Block();
 752    virtual unsigned int blockid() = 0;
 753    void genlocal(const std::string &name, char type);
 754    bool islocal(std::string name) const;
 755    void genconstant(const std::string &name, char type, const Token &value);
 756    char checklocal(const std::string &name) const;
 757    char checkconstant(const std::string &name) const;
 758    ConstantValue getconstant(const std::string &name) const;
 759    std::string genlabel();
 760protected:
 761    typedef std::map<std::string, char> Locals;
 762    Locals locals;
 763    typedef std::map<std::string, ConstantValue> Constants;
 764    Constants constants;
 765};
 766
 767class InBlock : public BlockBase
 768{
 769protected:
 770    InBlock(BlockBase &block) : bl(block) { };
 771public:
 772    std::string getbreaklabel() const
 773    {
 774        return bl.getbreaklabel();
 775    }
 776    std::string getcontinuelabel() const
 777    {
 778        return bl.getcontinuelabel();
 779    }
 780    char checklocal(const std::string &name) const
 781    {
 782        return bl.checklocal(name);
 783    }
 784    char checkconstant(const std::string &name) const
 785    {
 786        return bl.checkconstant(name);
 787    }
 788    void genconstant(const std::string &name, char type, const Token &value)
 789    {
 790        bl.genconstant(name, type, value);
 791    }
 792    ConstantValue getconstant(const std::string &name) const
 793    {
 794        return bl.getconstant(name);
 795    }
 796    FunctionStatement *getfunction(const std::string &name) const
 797    {
 798        return bl.getfunction(name);
 799    }
 800    std::string genlocallabel()
 801    {
 802        return bl.genlocallabel();
 803    }
 804    std::string genlocalregister(char type)
 805    {
 806        return bl.genlocalregister(type);
 807    }
 808    void freelocalregister(const std::string &reg)
 809    {
 810        bl.freelocalregister(reg);
 811    }
 812    std::string gentemp(char type)
 813    {
 814        return bl.gentemp(type);
 815    }
 816    void freetempregs()
 817    {
 818        bl.freetempregs();
 819    }
 820    void genlocal(const std::string &name, char type)
 821    {
 822        bl.genlocal(name, type);
 823    }
 824    bool islocal(std::string name) const
 825    {
 826        return bl.islocal(name);
 827    }
 828    ClassStatement *findclass(const ClassKey &classkey)
 829    {
 830        return bl.findclass(classkey);
 831    }
 832private:
 833    BlockBase &bl;
 834};
 835
 836Block::Block()
 837{ }
 838
 839void Block::genlocal(const std::string &name, char type)
 840{
 841    locals[name]= type;
 842}
 843
 844bool Block::islocal(std::string name) const
 845{
 846    return locals.find(name) != locals.end();
 847}
 848
 849void Block::genconstant(const std::string &name, char type, const Token &value)
 850{
 851    constants.insert(std::make_pair(name, ConstantValue(type, value)));
 852}
 853
 854char Block::checklocal(const std::string &name) const
 855{
 856    Locals::const_iterator it= locals.find(name);
 857    if (it != locals.end() )
 858        return it->second;
 859    Constants::const_iterator itc= constants.find(name);
 860    if (itc != constants.end() )
 861        return itc->second.type();
 862    return '\0';
 863}
 864
 865char Block::checkconstant(const std::string &name) const
 866{
 867    Constants::const_iterator itc= constants.find(name);
 868    if (itc != constants.end() )
 869        return itc->second.type();
 870    return '\0';
 871}
 872
 873ConstantValue Block::getconstant(const std::string &name) const
 874{
 875    Constants::const_iterator itc= constants.find(name);
 876    if (itc != constants.end() )
 877        return itc->second;
 878    throw InternalError("No such constant");
 879}
 880
 881std::string Block::genlabel()
 882{
 883    return genlocallabel();
 884}
 885
 886//**********************************************************************
 887
 888class SubBlock : public Block
 889{
 890public:
 891    SubBlock(Block &parentblock) :
 892        parent(parentblock),
 893        id(parent.blockid()),
 894        nlabel(0)
 895    {
 896    }
 897    std::string getbreaklabel() const;
 898    std::string getcontinuelabel() const;
 899    bool islocal(std::string name) const;
 900    char checklocal(const std::string &name) const;
 901    char checkconstant(const std::string &name) const;
 902    ConstantValue getconstant(const std::string &name) const;
 903    FunctionStatement *getfunction(const std::string &name) const
 904    {
 905        return parent.getfunction(name);
 906    }
 907    std::string genlocalregister(char type)
 908    {
 909        return parent.genlocalregister(type);
 910    }
 911    void freelocalregister(const std::string &reg)
 912    {
 913        parent.freelocalregister(reg);
 914    }
 915    std::string gentemp(char type)
 916    {
 917        return parent.gentemp(type);
 918    }
 919    void freetempregs()
 920    {
 921        parent.freetempregs();
 922    }
 923    std::string genlocallabel();
 924    ClassStatement *findclass(const ClassKey &classkey)
 925    {
 926        return parent.findclass(classkey);
 927    }
 928private:
 929    unsigned int blockid();
 930
 931    Block &parent;
 932    unsigned int id;
 933    unsigned int nlabel;
 934};
 935
 936unsigned int SubBlock::blockid()
 937{
 938    return parent.blockid();
 939}
 940
 941std::string SubBlock::getbreaklabel() const
 942{
 943    return parent.getbreaklabel();
 944}
 945
 946std::string SubBlock::getcontinuelabel() const
 947{
 948    return parent.getcontinuelabel();
 949}
 950
 951char SubBlock::checklocal(const std::string &name) const
 952{
 953    if (char c= Block::checklocal(name))
 954        return c;
 955    else
 956        return parent.checklocal(name);
 957}
 958
 959bool SubBlock::islocal(std::string name) const
 960{
 961    return checklocal(name) != '\0';
 962}
 963
 964char SubBlock::checkconstant(const std::string &name) const
 965{
 966    char c= Block::checkconstant(name);
 967    if (c == '\0')
 968        c= parent.checkconstant(name);
 969    return c;
 970}
 971
 972ConstantValue SubBlock::getconstant(const std::string &name) const
 973{
 974    if (Block::checkconstant(name))
 975        return Block::getconstant(name);
 976    else
 977        return parent.getconstant(name);
 978}
 979
 980std::string SubBlock::genlocallabel()
 981{
 982    std::ostringstream l;
 983    l << "__label_" << id << '_' << ++nlabel;
 984    return l.str();
 985}
 986
 987//**********************************************************************
 988
 989class NamespaceKey
 990{
 991    typedef std::vector <std::string> key_t;
 992public:
 993    NamespaceKey() { }
 994    NamespaceKey(const std::string &name) :
 995        key(1, name)
 996    {
 997    }
 998    NamespaceKey(const key_t &newkey) :
 999        key(newkey)
1000    {
1001    }
1002    bool isroot() const
1003    {
1004        return key.empty();
1005    }
1006    NamespaceKey parent() const
1007    {
1008        key_t newkey = key;
1009        newkey.pop_back();
1010        return NamespaceKey(newkey);
1011    }
1012    std::string get_key() const
1013    {
1014        std::string r= "[ ";
1015        for (size_t i= 0; i < key.size(); ++i)
1016        {
1017            if (i > 0)
1018                r+= "; ";
1019            r+= '\'' + key [i] + '\'';
1020        }
1021        r+= " ]";
1022        return r;
1023    }
1024    void emit (Emit &e) const
1025    {
1026        e << ".namespace " << get_key() << '\n';
1027    }
1028private:
1029    std::vector <std::string> key;
1030};
1031
1032//**********************************************************************
1033
1034class FunctionBlock : public SubBlock
1035{
1036public:
1037    FunctionBlock(Block &parent) :
1038        SubBlock(parent),
1039        subblocks(0),
1040        nreg(0), nlabel(0)
1041    {
1042    }
1043public:
1044    std::string genlocallabel();
1045    std::string genlocalregister(char type);
1046    std::string gentemp(char type);
1047    std::string genregister(char type);
1048    void freelocalregister(const std::string &reg);
1049    void freeregister(const std::string &reg);
1050protected:
1051    size_t tempsused() const
1052    {
1053        return tempi.size() + temps.size() + tempp.size() +
1054            + freetempi.size() + freetemps.size() + freetempp.size();
1055    }
1056    void freetempregs()
1057    {
1058        using std::copy;
1059        using std::back_inserter;
1060        copy(tempi.begin(), tempi.end(), back_inserter(freetempi));
1061        tempi= std::vector<std::string>();
1062        copy(temps.begin(), temps.end(), back_inserter(freetemps));
1063        temps= std::vector<std::string>();
1064        copy(tempp.begin(), tempp.end(), back_inserter(freetempp));
1065        tempp= std::vector<std::string>();
1066    }
1067private:
1068    unsigned int subblocks;
1069    unsigned int nreg;
1070    unsigned int nlabel;
1071    std::vector <std::string> tempi;
1072    std::vector <std::string> temps;
1073    std::vector <std::string> tempp;
1074    std::vector <std::string> freetempi;
1075    std::vector <std::string> freetemps;
1076    std::vector <std::string> freetempp;
1077};
1078
1079std::string FunctionBlock::genlocalregister(char type)
1080{
1081    if (type != REGint && type != REGstring && type != REGvar)
1082        throw InternalError("invalid register type");
1083    std::ostringstream l;
1084    l << '$' << type << ++nreg;
1085    return l.str();
1086}
1087
1088void FunctionBlock::freelocalregister(const std::string &reg)
1089{
1090    if (reg.at(0) != '$')
1091        throw InternalError("invalid free register");
1092    switch(reg.at(1))
1093    {
1094    case REGint:    freetempi.push_back(reg); break;
1095    case REGstring: freetemps.push_back(reg); break;
1096    case REGvar:    freetempp.push_back(reg); break;
1097    default: throw InternalError("invalid free register");
1098    }
1099}
1100
1101void FunctionBlock::freeregister(const std::string &reg)
1102{
1103   return freelocalregister(reg);
1104}
1105
1106std::string FunctionBlock::genregister(char type)
1107{
1108    return genlocalregister(type);
1109}
1110
1111std::string FunctionBlock::gentemp(char type)
1112{
1113    std::vector<std::string> &usefree= type == REGint ? freetempi :
1114        type == REGstring ? freetemps : freetempp;
1115    std::string temp;
1116    if (usefree.size() > 0)
1117    {
1118        temp= usefree.back();
1119        usefree.pop_back();
1120    }
1121    else
1122    {
1123        temp= genlocalregister(type);
1124        switch(type)
1125        {
1126        case REGint:    tempi.push_back(temp); break;
1127        case REGstring: temps.push_back(temp); break;
1128        default:        tempp.push_back(temp); break;
1129        }
1130    }
1131    return temp;
1132}
1133
1134std::string FunctionBlock::genlocallabel()
1135{
1136    std::ostringstream l;
1137    l << "__label_" << ++nlabel;
1138    return l.str();
1139}
1140
1141//**********************************************************************
1142
1143class NamespaceBlockBase;
1144class Expr;
1145
1146//**********************************************************************
1147
1148class BaseStatement
1149{
1150public:
1151    virtual bool isempty() { return false; }
1152    virtual void emit (Emit &e) = 0;
1153    virtual BaseStatement *optimize() { return this; }
1154    void optimize_branch(BaseStatement *&branch);
1155    void optimize_branch(Expr *&branch);
1156    virtual ~BaseStatement() { };
1157};
1158
1159//**********************************************************************
1160
1161class MultiStatement : public BaseStatement
1162{
1163public:
1164    MultiStatement(BaseStatement *st1, BaseStatement *st2)
1165    {
1166        subst.push_back(st1);
1167        subst.push_back(st2);
1168    }
1169    void push(BaseStatement *st)
1170    {
1171        subst.push_back(st);
1172    }
1173private:
1174    std::vector <BaseStatement *> subst;
1175    BaseStatement *optimize()
1176    {
1177        for (size_t i= 0; i < subst.size(); ++i)
1178            subst[i] = subst[i]->optimize();
1179        return this;
1180    }
1181    void emit (Emit &e)
1182    {
1183        for (size_t i= 0; i < subst.size(); ++i)
1184            subst[i]->emit(e);
1185    }
1186};
1187
1188BaseStatement *addtomulti(BaseStatement *oldst, BaseStatement *newst)
1189{
1190    if (! oldst)
1191        return newst;
1192    else if (MultiStatement *multi = dynamic_cast<MultiStatement *>(oldst))
1193    {
1194        multi->push(newst);
1195        return multi;
1196    }
1197    else
1198        return new MultiStatement(oldst, newst);
1199}
1200
1201//**********************************************************************
1202
1203enum ClassSpecifierType
1204{
1205    CLASSSPECIFIER_invalid,
1206    CLASSSPECIFIER_parrotkey,
1207    CLASSSPECIFIER_id
1208};
1209
1210class ClassSpecifier : public Annotated
1211{
1212protected:
1213    ClassSpecifier(const Token &t) : Annotated(t)
1214    { }
1215public:
1216    virtual ClassSpecifierType reftype() const
1217    { return CLASSSPECIFIER_invalid; }
1218    virtual ~ClassSpecifier() {}
1219    virtual std::string basename() const = 0;
1220    virtual void emit(Emit &e) = 0;
1221};
1222
1223ClassSpecifier *parseClassSpecifier(const Token &start, Tokenizer &tk,
1224        BlockBase &owner);
1225
1226//**********************************************************************
1227
1228class SubStatement : public BaseStatement, public InBlock
1229{
1230public:
1231    SubStatement(Block &block);
1232};
1233
1234SubStatement::SubStatement(Block &block) :
1235    InBlock(block)
1236{
1237}
1238
1239//**********************************************************************
1240
1241class EmptyStatement : public BaseStatement
1242{
1243private:
1244    bool isempty() { return true; }
1245    void emit (Emit &) { };
1246};
1247
1248//**********************************************************************
1249
1250class BlockStatement : public BaseStatement, public SubBlock
1251{
1252public:
1253    BlockStatement (Block &parentblock) :
1254            SubBlock(parentblock)
1255    {
1256    }
1257};
1258
1259//**********************************************************************
1260
1261class Expr : public InBlock, public Annotated
1262{
1263public:
1264    Expr(BlockBase &block, const Token & tstart) :
1265        InBlock(block),
1266        Annotated(tstart)
1267    {
1268    }
1269    virtual Expr *optimize()
1270    {
1271        return this;
1272    }
1273    virtual bool isleft() const { return false; }
1274    virtual void emitleft(Emit &)
1275    {
1276        std::cerr << typeid(*this).name() << '\n';
1277        throw InternalError("Not a left-side expression");
1278    }
1279    virtual void emitleft(Emit &, const std::string &)
1280    {
1281        std::cerr << typeid(*this).name() << '\n';
1282        throw InternalError("Not a left-side expression");
1283    }
1284    virtual void emitassign(Emit &, Expr &, const std::string &)
1285    {
1286        std::cerr << typeid(*this).name() << '\n';
1287        throw InternalError("Not an assignable expression");
1288    }
1289    virtual void emit(Emit &e, const std::string &result) = 0;
1290    virtual std::string emit_get(Emit &e);
1291    virtual bool issimple() const { return false; }
1292    virtual const Token &gettoken() const
1293    {
1294        std::cerr << typeid(*this).name() << '\n';
1295        throw InternalError("In gettoken: Not a simple expression");
1296    }
1297    virtual bool isidentifier() const { return false; }
1298    virtual std::string getidentifier() const
1299    { throw InternalError("Not an identifier"); }
1300    virtual bool isnull() const { return false; }
1301    virtual bool isliteralinteger() const { return false; }
1302    virtual bool isinteger() const { return false; }
1303    virtual int getintegervalue () const
1304    {
1305        std::cerr << typeid(*this).name() << '\n';
1306        throw InternalError("Not an integer");
1307    }
1308    virtual bool isliteralstring() const { return false; }
1309    virtual std::string getstringvalue () const
1310    { throw InternalError("Not a string"); }
1311    virtual bool isstring() const { return false; }
1312    virtual bool isindex() const { return false; }
1313    char checkresult() const
1314    {
1315        if (isinteger() ) return REGint;
1316        else if (isstring() ) return REGstring;
1317        else return REGvar;
1318    }
1319    void optimize_branch(Expr *&branch)
1320    { branch= branch->optimize(); }
1321};
1322
1323Expr * parseExpr(BlockBase &block, Tokenizer &tk);
1324
1325//**********************************************************************
1326
1327class Condition : public InBlock
1328{
1329public:
1330    Condition (Block &block, Tokenizer &tk);
1331    Condition (BlockBase &block, Expr *condexpr);
1332    Condition *optimize();
1333    bool issimple() const;
1334    bool isinteger() const { return true; }
1335    //bool isstring() const { return expr->isstring(); }
1336    bool isliteralinteger() const;
1337    std::string value() const;
1338    std::string emit(Emit &e);
1339    void emit_if(Emit &e, const std::string &labeltrue);
1340    void emit_else(Emit &e, const std::string &labelfalse);
1341    enum Value { CVtrue, CVfalse, CVruntime };
1342    Value getvalue() const;
1343private:
1344    Expr *expr;
1345};
1346
1347//**********************************************************************
1348
1349void BaseStatement::optimize_branch(BaseStatement *&branch)
1350{
1351    if (branch)
1352        branch= branch->optimize();
1353}
1354
1355void BaseStatement::optimize_branch(Expr *&branch)
1356{
1357    if (branch)
1358        branch= branch->optimize();
1359}
1360
1361//**********************************************************************
1362
1363class Modifier
1364{
1365public:
1366    Modifier(BlockBase &block, Tokenizer &tk)
1367    {
1368        Token t= tk.get();
1369        if (!t.isidentifier())
1370            throw Expected("Modifier name", t);
1371        start = t;
1372        name= t.identifier();
1373        t= tk.get();
1374        if (!t.isop('('))
1375            tk.unget(t);
1376        else
1377        {
1378            do
1379            {
1380                args.push_back(parseExpr(block, tk));
1381            } while ((t= tk.get()).isop(','));
1382            RequireOp(')', t);
1383        }
1384    }
1385    std::string getname() const { return name; }
1386    Token getstart() const { return start; }
1387    void optimize()
1388    {
1389        for (size_t i= 0; i < args.size(); ++i)
1390            args[i]= args[i]->optimize();
1391    }
1392    size_t numargs() const { return args.size(); }
1393    Expr *getarg(size_t narg) const
1394    {
1395        return args.at(narg);
1396    }
1397    int getintegervalue(size_t narg) const
1398    {
1399        Expr *arg= args.at(narg);
1400        return arg->getintegervalue();
1401    }
1402    std::string getstringvalue(size_t narg) const
1403    {
1404        Expr *arg= args.at(narg);
1405        return arg->getstringvalue();
1406    }
1407private:
1408    Token start;
1409    std::string name;
1410    std::vector <Expr *> args;
1411};
1412
1413//**********************************************************************
1414
1415class ModifierList
1416{
1417public:
1418    bool has_modifier(const std::string &name) const
1419    {
1420        return modifiers.find(name) != modifiers.end();
1421    }
1422    const Modifier * getmodifier(const std::string &name) const
1423    {
1424        ModList::const_iterator it= modifiers.find(name);
1425        if (it != modifiers.end())
1426            return &it->second;
1427        else
1428            return NULL;
1429    }
1430    void parse(BlockBase &block, Tokenizer &tk)
1431    {
1432        Token t;
1433        do {
1434            Modifier m(block, tk);
1435            std::string name= m.getname();
1436            modifiers.insert(std::make_pair(name, m));
1437        } while ((t= tk.get()).isop(','));
1438        RequireOp(']', t);
1439    }
1440    void optimize()
1441    {
1442        for (ModList::iterator it= modifiers.begin();
1443                it != modifiers.end(); ++it)
1444           it->second.optimize();
1445    }
1446protected:
1447    typedef std::map<std::string, Modifier> ModList;
1448    ModList modifiers;
1449};
1450
1451//**********************************************************************
1452
1453class FunctionModifiers : public ModifierList
1454{
1455public:
1456    FunctionModifiers(BlockBase &block, Tokenizer &tk)
1457    {
1458        Token t= tk.get();
1459        if (! t.isop('[') )
1460            tk.unget(t);
1461        else
1462            parse(block, tk);
1463    }
1464};
1465
1466//**********************************************************************
1467
1468class ArgumentModifierList : public ModifierList
1469{
1470public:
1471    void emitmodifiers(Emit &e)
1472    {
1473        bool isflat = false, isnamed = false;
1474        Expr * setname = 0;
1475        for (ModList::iterator it = modifiers.begin(); it != modifiers.end();
1476                ++it)
1477        {
1478            std::string name = it->first;
1479            Modifier &modifier = it->second;
1480            if (name == "flat")
1481                isflat = true;
1482            if (name == "named")
1483            {
1484                isnamed = true;
1485                switch (modifier.numargs())
1486                {
1487                  case 0:
1488                    break;
1489                  case 1:
1490                    setname = modifier.getarg(0);
1491                    break;
1492                  default:
1493                    throw SyntaxError("Invalid modifier", modifier.getstart());
1494                }
1495            }
1496        }
1497        if (isflat)
1498        {
1499            if (isnamed)
1500                e << " :flat :named";
1501            else
1502                e << " :flat";
1503        }
1504        else if (isnamed)
1505        {
1506            e << " :named";
1507            if (setname)
1508                e << '(';
1509                setname->emit(e, "");
1510                e << ')';
1511        }
1512    }
1513};
1514
1515class Argument
1516{
1517public:
1518    Argument(BlockBase &block, Tokenizer &tk) :
1519            modifiers(0)
1520    {
1521        expr = parseExpr(block, tk);
1522        Token t = tk.get();
1523        if (t.isop(':'))
1524        {
1525            t = tk.get();
1526            if (! t.isop('['))
1527                throw Expected("modifier list", t);
1528            modifiers = new ArgumentModifierList();
1529            modifiers->parse(block, tk);
1530        }
1531        else
1532            tk.unget(t);
1533    }
1534    Expr *get()
1535    {
1536        return expr;
1537    }
1538    ArgumentModifierList *getmodifiers()
1539    {
1540        return modifiers;
1541    }
1542    Argument *optimize()
1543    {
1544        expr= expr->optimize();
1545        return this;
1546    }
1547    void emit(Emit &e, const std::string &result)
1548    {
1549        expr->emit(e, result);
1550    }
1551private:
1552    Expr *expr;
1553    ArgumentModifierList *modifiers;
1554};
1555
1556class ArgumentList : public InBlock
1557{
1558public:
1559    ArgumentList(BlockBase &block, Tokenizer &tk, char delimiter);
1560    int numargs() const
1561    {
1562        return args ? args->size() : 0;
1563    }
1564    Expr *getfreearg(int i)
1565    {
1566        return args->at(i)->get();
1567    }
1568    void optimize();
1569    void prepare(Emit &e);
1570    void emit(Emit &e);
1571private:
1572    std::vector <Argument *> *args;
1573    std::vector <std::string> argregs;
1574};
1575
1576//**********************************************************************
1577
1578class ExprStatement : public BaseStatement
1579{
1580public:
1581    ExprStatement(Block &parentblock, Tokenizer &tk);
1582private:
1583    BaseStatement *optimize();
1584    void emit (Emit &e);
1585
1586    Expr *expr;
1587};
1588
1589//**********************************************************************
1590
1591class CompoundStatement : public BlockStatement
1592{
1593public:
1594    CompoundStatement(Block &parentblock, Tokenizer &tk);
1595    BaseStatement *optimize();
1596    void emit (Emit &e);
1597    Token getend() const { return tend; }
1598private:
1599    std::vector <BaseStatement *> subst;
1600    Token tend;
1601};
1602
1603//**********************************************************************
1604
1605class ValueStatement : public SubStatement, public Annotated
1606{
1607public:
1608    ValueStatement(Block & block, const Token & tstart);
1609protected:
1610    void parseArray(Tokenizer &tk);
1611    void emit (Emit &e, const std::string &name, char type);
1612
1613    enum ValueType { ValueSimple, ValueArray, ValueFixedArray };
1614    ValueType vtype;
1615    Expr *esize;
1616    std::vector<Expr *> value;
1617private:
1618    BaseStatement *optimize();
1619};
1620
1621//**********************************************************************
1622
1623class IntStatement : public ValueStatement
1624{
1625public:
1626    IntStatement(Block & block, const Token &st, Tokenizer &tk);
1627    void emit (Emit &e);
1628    using ValueStatement::emit;
1629private:
1630    std::string name;
1631};
1632
1633//**********************************************************************
1634
1635class StringStatement : public ValueStatement
1636{
1637public:
1638    StringStatement(Block & block, const Token &st, Tokenizer &tk);
1639    void emit (Emit &e);
1640    using ValueStatement::emit;
1641private:
1642    std::string name;
1643};
1644
1645//**********************************************************************
1646
1647template <class DECST> 
1648BaseStatement *parseDeclare(Block & block, const Token &st, Tokenizer &tk)
1649{
1650    BaseStatement *multi = 0;
1651    Token t;
1652    do {
1653       BaseStatement *item = new DECST(block, st, tk);
1654       multi = addtomulti(multi, item);
1655       t= tk.get();
1656    } while (t.isop(','));
1657    RequireOp (';', t);
1658    return multi;
1659}
1660
1661//**********************************************************************
1662
1663class VarStatement : public ValueStatement
1664{
1665public:
1666    VarStatement(Block & block, const Token &st, Tokenizer &tk);
1667    void emit (Emit &e);
1668private:
1669    std::string name;
1670};
1671
1672//**********************************************************************
1673
1674class ConstStatement : public ValueStatement
1675{
1676public:
1677    ConstStatement(Block & block, const Token &st, Tokenizer &tk, char typed);
1678    BaseStatement *optimize();
1679    void emit (Emit &e);
1680private:
1681    char type;
1682    std::string name;
1683    Expr *value;
1684};
1685
1686BaseStatement * parseConst(Block & block, const Token &st, Tokenizer &tk);
1687
1688//**********************************************************************
1689
1690class LabelStatement: public SubStatement
1691{
1692public:
1693    LabelStatement(Block &block, const std::string &name);
1694    void emit (Emit &e);
1695private:
1696    std::string labelname;
1697    std::string codename;
1698};
1699
1700//**********************************************************************
1701
1702class ReturnStatement : public SubStatement, public Annotated
1703{
1704public:
1705    ReturnStatement(Block & block, const Token & tstart, Tokenizer &tk);
1706    BaseStatement *optimize();
1707    void emit (Emit &e);
1708private:
1709    ArgumentList *values;
1710};
1711
1712//**********************************************************************
1713
1714class BreakStatement : public SubStatement
1715{
1716public:
1717    BreakStatement(Block &block, Tokenizer &tk) :
1718        SubStatement(block)
1719    {
1720        ExpectOp(';', tk);
1721    }
1722private:
1723    void emit (Emit &e)
1724    {
1725        e << INDENT "goto " << getbreaklabel() << " # break\n";
1726    }
1727};
1728
1729//**********************************************************************
1730
1731class ContinueStatement : public SubStatement
1732{
1733public:
1734    ContinueStatement(Block &block, Tokenizer &tk) :
1735        SubStatement(block)
1736    {
1737        ExpectOp(';', tk);
1738    }
1739private:
1740    void emit (Emit &e)
1741    {
1742        e << INDENT "goto " << getcontinuelabel() << " # continue\n";
1743    }
1744};
1745
1746//**********************************************************************
1747
1748class BreakableStatement : public BlockStatement
1749{
1750protected:
1751    BreakableStatement(Block &block) :
1752        BlockStatement(block)
1753    { }
1754    std::string getbreaklabel() const
1755    {
1756        if (breaklabel.empty())
1757            throw InternalError("attempt to use break label before creating");
1758        return breaklabel;
1759    }
1760    std::string genbreaklabel()
1761    {
1762        if (! breaklabel.empty())
1763            throw InternalError("attempt to create break label twice");
1764        breaklabel = genlabel();
1765        return breaklabel;
1766    }
1767private:
1768    std::string breaklabel;
1769};
1770
1771class ContinuableStatement : public BreakableStatement
1772{
1773protected:
1774    ContinuableStatement(Block &block) :
1775        BreakableStatement(block)
1776    { }
1777    std::string getcontinuelabel() const
1778    {
1779        if (continuelabel.empty())
1780            throw InternalError("attempt to use continue label before creating");
1781        return continuelabel;
1782    }
1783    std::string gencontinuelabel()
1784    {
1785        if (! continuelabel.empty())
1786            throw InternalError("attempt to create continue label twice");
1787        continuelabel = genlabel();
1788        return continuelabel;
1789    }
1790private:
1791    std::string continuelabel;
1792};
1793
1794//**********************************************************************
1795
1796class SwitchBaseStatement : public BreakableStatement
1797{
1798protected:
1799    SwitchBaseStatement(Block &block);
1800    void parse_cases(Tokenizer &tk);
1801    std::vector<Expr *> casevalue;
1802    std::vector<std::vector<BaseStatement *> > casest;
1803    std::vector<BaseStatement *> defaultst;
1804    BaseStatement *optimize();
1805};
1806
1807class SwitchStatement : public SwitchBaseStatement
1808{
1809public:
1810    SwitchStatement(Block &block, Tokenizer &tk);
1811private:
1812    BaseStatement *optimize();
1813    void emit (Emit &e);
1814    Expr *condition;
1815};
1816
1817class SwitchCaseStatement : public SwitchBaseStatement
1818{
1819public:
1820    SwitchCaseStatement(Block &block, Tokenizer &tk);
1821private:
1822    void emit (Emit &e);
1823};
1824
1825//**********************************************************************
1826
1827class IfStatement : public BlockStatement
1828{
1829public:
1830    IfStatement(Block &block, Tokenizer &tk);
1831private:
1832    BaseStatement *optimize();
1833    void emit (Emit &e);
1834    Condition *condition;
1835    BaseStatement *st;
1836    BaseStatement *stelse;
1837};
1838
1839//**********************************************************************
1840
1841class WhileStatement : public ContinuableStatement
1842{
1843public:
1844    WhileStatement(Block &block, Tokenizer &tk);
1845private:
1846    BaseStatement *optimize();
1847    void emit (Emit &e);
1848    Condition *condition;
1849    BaseStatement *st;
1850};
1851
1852//**********************************************************************
1853
1854class DoStatement : public ContinuableStatement
1855{
1856public:
1857    DoStatement(Block &block, Tokenizer &tk);
1858private:
1859    BaseStatement *optimize();
1860    void emit (Emit &e);
1861    Condition *condition;
1862    BaseStatement *st;
1863};
1864
1865//**********************************************************************
1866
1867class ForeachStatement : public ContinuableStatement
1868{
1869public:
1870    ForeachStatement(Block &block, Tokenizer &tk);
1871private:
1872    BaseStatement *optimize();
1873    void emit (Emit &e);
1874
1875    Token start;
1876    std::string varname;
1877    char vartype;
1878    Expr * container;
1879    BaseStatement *st;
1880};
1881
1882//**********************************************************************
1883
1884class ForStatement : public ContinuableStatement
1885{
1886public:
1887    ForStatement(Block &block, Tokenizer &tk);
1888private:
1889    BaseStatement *optimize();
1890    void emit (Emit &e);
1891
1892    BaseStatement * initializer;
1893    Expr * condition;
1894    Expr * iteration;
1895    BaseStatement *st;
1896};
1897
1898//**********************************************************************
1899
1900class ThrowStatement : public SubStatement
1901{
1902public:
1903    ThrowStatement(Block &block, const Token &st, Tokenizer &tk);
1904private:
1905    BaseStatement *optimize();
1906    void emit (Emit &e);
1907    Token pos;
1908    Expr * excep;
1909};
1910
1911//**********************************************************************
1912
1913class TryStatement : public BlockStatement, public Annotated
1914{
1915public:
1916    TryStatement(Block &block, const Token &st, Tokenizer &tk);
1917private:
1918    BaseStatement *optimize();
1919    void emit (Emit &e);
1920    BaseStatement *stry;
1921    BaseStatement *scatch;
1922    std::string exname;
1923};
1924
1925//**********************************************************************
1926
1927class FunctionParameter
1928{
1929public:
1930    FunctionParameter(FunctionStatement *owner, Tokenizer &tk);
1931    char gettype() const { return type; }
1932    std::string getname() const { return name; }
1933    void emit (Emit &e);
1934private:
1935    std::string name;
1936    char type;
1937    ModifierList modifiers;
1938    bool has_modifier(const std::string &name) const
1939    {
1940        return modifiers.has_modifier(name);
1941    }
1942};
1943
1944//**********************************************************************
1945
1946class FunctionStatement : protected FunctionModifiers, public FunctionBlock,
1947        public Annotated
1948{
1949public:
1950    FunctionStatement(Tokenizer &tk, const Token & tstart,
1951        Block &parent,
1952        const std::string &funcname);
1953    virtual std::string getsubid() const;
1954    std::string getname() const { return name; }
1955    void optimize();
1956    virtual void emit (Emit &e);
1957    void local(std::string name);
1958    bool islocal(std::string name) const;
1959    virtual void emitparams (Emit &e);
1960    virtual void emitbody (Emit &e);
1961    virtual ~FunctionStatement() {}
1962private:
1963    const std::string name;
1964    std::vector <std::string> params;
1965    std::map <std::string, FunctionParameter *> paraminfo;
1966    std::vector <std::string> loc;
1967    BaseStatement *body;
1968    Token tend;
1969};
1970
1971//**********************************************************************
1972
1973class ClassStatement : public SubBlock
1974{
1975public:
1976    ClassStatement(NamespaceBlockBase &ns_b, Tokenizer &tk);
1977    const std::string &getname() const { return name; }
1978    void emit (Emit &e);
1979    std::vector <Token> attributes() const { return attrs; }
1980    void optimize();
1981    const NamespaceKey &getkey() const;
1982    void emitkey (Emit &e) const;
1983private:
1984    unsigned int subblocks;
1985    unsigned int blockid()
1986    {
1987        return ++subblocks;
1988    }
1989
1990    std::string genlocallabel() { throw InternalError("No Class labels"); }
1991    std::string genlocalregister(char) { throw InternalError("No Class registers"); }
1992
1993    Token start;
1994    std::string name;
1995    NamespaceKey ns;
1996    std::vector <ClassSpecifier *> parents;
1997    std::vector <FunctionStatement *> functions;
1998    std::vector <Token> attrs;
1999    std::vector <BaseStatement *> constants;
2000};
2001
2002//**********************************************************************
2003
2004FunctionParameter::FunctionParameter(FunctionStatement *owner, Tokenizer &tk)
2005{
2006    Token t = tk.get();
2007    type= nativetype(t);
2008    if (type == '\0')
2009        throw Expected("parameter type", t);
2010    t= tk.get();
2011    name= t.identifier();
2012    t= tk.get();
2013    if (t.isop('['))
2014        modifiers.parse(*owner, tk);
2015    else
2016        tk.unget(t);
2017}
2018
2019void FunctionParameter::emit (Emit &e)
2020{
2021    e << ".param " << nameoftype(type) << ' ' <<
2022            name;
2023    bool isslurpy = has_modifier("slurpy");
2024    bool isnamed = has_modifier("named");
2025    if (isslurpy) {
2026        e << " :slurpy";
2027        // Special case for named slurpy
2028        if (isnamed)
2029            e << " :named";
2030    }
2031    else {
2032        // Unfinished
2033        if (isnamed)
2034            e << " :named";
2035    }
2036    if (has_modifier("optional"))
2037        e << " :optional";
2038    if (has_modifier("opt_flag"))
2039        e << " :opt_flag";
2040    e << '\n';
2041}
2042
2043//**********************************************************************
2044
2045BaseStatement *parseFor(Block &block, Tokenizer &tk)
2046{
2047    Token t1= tk.get();
2048    if (t1.isop('(') )
2049    {
2050        Token t2= tk.get();
2051        Token t3= tk.get();
2052        Token t4= tk.get();
2053        if (t2.isidentifier() && (
2054            t3.iskeyword("in") || (t4.iskeyword("in"))))
2055        {
2056            tk.unget(t4);
2057            tk.unget(t3);
2058            tk.unget(t2);
2059            return new ForeachStatement(block, tk);
2060        }
2061        else
2062        {
2063            tk.unget(t4);
2064            tk.unget(t3);
2065            tk.unget(t2);
2066            return new ForStatement(block, tk);
2067        }
2068    }
2069    else
2070        throw Expected("for condition", t1);
2071}
2072
2073BaseStatement *parseSwitch(Block &block, Tokenizer &tk)
2074{
2075    Token t = tk.get();
2076    if (t.isop('('))
2077        return new SwitchStatement(block, tk);
2078    if (t.isop('{'))
2079        return new SwitchCaseStatement(block, tk);
2080    throw Expected("'(' o '{' after switch", t);
2081}
2082
2083BaseStatement *parseStatement(Block &block, Tokenizer &tk)
2084{
2085    Token t= tk.get();
2086    while (t.isspace() )
2087        t= tk.get();
2088
2089    if (t.isop(';'))
2090        return new EmptyStatement();
2091    if (t.isop('{') )
2092        return new CompoundStatement(block, tk);
2093    switch(nativetype(t))
2094    {
2095    case REGint:
2096        return parseDeclare<IntStatement>(block, t, tk);
2097    case REGstring:
2098        return parseDeclare<StringStatement>(block, t, tk);
2099    case REGvar:
2100        return new VarStatement(block, t, tk);
2101    default: /* Not a declaration */ ;
2102    }
2103    if (t.iskeyword("const"))
2104        return parseConst(block, t, tk);
2105
2106    if (t.iskeyword("return"))
2107        return new ReturnStatement(block, t, tk);
2108    if (t.iskeyword("break"))
2109        return new BreakStatement(block, tk);
2110    if (t.iskeyword("continue"))
2111        return new ContinueStatement(block, tk);
2112    if (t.iskeyword("if"))
2113        return new IfStatement(block, tk);
2114    if (t.iskeyword("switch"))
2115        return parseSwitch(block, tk);
2116    if (t.iskeyword("while"))
2117        return new WhileStatement(block, tk);
2118    if (t.iskeyword("do"))
2119        return new DoStatement(block, tk);
2120    if (t.iskeyword("for"))
2121        return parseFor(block, tk);
2122    if (t.iskeyword("throw"))
2123        return new ThrowStatement(block, t, tk);
2124    if (t.iskeyword("try"))
2125        return new TryStatement(block, t, tk);
2126
2127    tk.unget(t);
2128    return new ExprStatement(block, tk);
2129}
2130
2131//**********************************************************************
2132
2133ArgumentList::ArgumentList(BlockBase &block, Tokenizer &tk, char delimiter) :
2134    InBlock(block),
2135    args(0)
2136{
2137    Token t = tk.get();
2138    if (! t.isop(delimiter))
2139    {
2140        args= new std::vector<Argument *>;
2141        tk.unget(t);
2142        do
2143        {
2144            Argument *arg= new Argument(block, tk);
2145            args->push_back(arg);
2146            t= tk.get();
2147        } while (t.isop(','));
2148        if (! t.isop(delimiter))
2149            throw SyntaxError("Unfinished argument list", t);
2150    }
2151}
2152
2153void ArgumentList::optimize()
2154{
2155    if (args)
2156        for (size_t i= 0; i < args->size(); ++i)
2157            (*args)[i]= (*args)[i]->optimize();
2158}
2159
2160void ArgumentList::prepare(Emit &e)
2161{
2162    std::string nullreg;
2163    if (args)
2164    {
2165        for (size_t i= 0; i < args->size(); ++i)
2166        {
2167            Expr &arg= *((*args)[i]->get());
2168            std::string reg;
2169            if (! arg.issimple() )
2170            {
2171                arg.annotate(e);
2172                reg= arg.emit_get(e);
2173            }
2174            else
2175            {
2176                if (arg.isnull())
2177                {
2178                    if (nullreg.empty())
2179                    {
2180                        nullreg= gentemp(REGvar);
2181                        e << op_null(nullreg) << '\n';
2182                    }
2183                    reg= nullreg;
2184                }
2185                else if (arg.isidentifier())
2186                {
2187                    std::string name = arg.getidentifier();
2188                    FunctionStatement *fun = getfunction(name);
2189                    if (fun)
2190                    {
2191                        name = fun->getsubid();
2192                        e << ".const 'Sub' " << name << " = '" << name << "'\n";
2193                        reg = name;
2194                    }
2195                }
2196            }
2197            argregs.push_back(reg);
2198        }
2199    }
2200}
2201
2202void ArgumentList::emit(Emit &e)
2203{
2204    if (args)
2205    {
2206        for (size_t i= 0; i < args->size(); ++i)
2207        {
2208            if (i > 0)
2209                e << ", ";
2210            if (argregs[i].empty() )
2211                (*args)[i]->emit(e, std::string() );
2212            else
2213                e << argregs[i];
2214            if (ArgumentModifierList *modifiers = (*args)[i]->getmodifiers())
2215            {
2216                modifiers->emitmodifiers(e);
2217            }
2218        }
2219    }
2220}
2221
2222//**********************************************************************
2223
2224std::string Expr::emit_get(Emit &e)
2225{
2226    std::string reg = gentemp(checkresult());
2227    emit(e, reg);
2228    return reg;
2229}
2230
2231//**********************************************************************
2232
2233class SimpleBaseExpr : public Expr
2234{
2235public:
2236    SimpleBaseExpr(BlockBase &block, const Token & token) :
2237        Expr(block, token),
2238        t(token)
2239    { }
2240private:
2241    const Token &gettoken() const { return t; }
2242    bool issimple() const { return true; }
2243protected:
2244    const Token t;
2245};
2246
2247//**********************************************************************
2248
2249class StringExpr : public SimpleBaseExpr
2250{
2251public:
2252    StringExpr(BlockBase &block, Token token) :
2253        SimpleBaseExpr(block, token)
2254    {
2255        if (! t.isliteralstring())
2256            throw InternalError("Invalid literal string");
2257    }
2258private:
2259    bool isliteralstring() const { return true; }
2260    bool isstring() const { return true; }
2261    bool issinglequoted() const
2262    {
2263        return t.issinglequoted();
2264    }
2265    std::string getstringvalue() const
2266    {
2267        return t.str();
2268    }
2269    void emit(Emit &e, const std::string &result)
2270    {
2271        if (!result.empty() )
2272            e << INDENT << result << " = ";
2273        e << t.pirliteralstring();
2274        if (!result.empty() )
2275            e << '\n';
2276    }
2277};
2278
2279//**********************************************************************
2280
2281class IntegerExpr : public SimpleBaseExpr
2282{
2283public:
2284    IntegerExpr(BlockBase &block, Token token) :
2285        SimpleBaseExpr(block, token),
2286        value (t.getinteger())
2287    {
2288    }
2289    IntegerExpr(BlockBase &block, Token token, int n) :
2290        SimpleBaseExpr(block, Token(n, token)),
2291        value (n)
2292    {
2293    }
2294private:
2295    bool isliteralinteger() const { return true; }
2296    bool isinteger() const { return true; }
2297    int getintegervalue () const { return value; }
2298
2299    void emit(Emit &e, const std::string &result)
2300    {
2301        if (!result.empty() )
2302            e << INDENT << result << " = ";
2303        e << getintegervalue();
2304        if (!result.empty() )
2305            e << '\n';
2306    }
2307    int value;
2308};
2309
2310//**********************************************************************
2311
2312class IdentifierExpr : public SimpleBaseExpr
2313{
2314public:
2315    IdentifierExpr(BlockBase &block, Token token) :
2316        SimpleBaseExpr(block, token)
2317    { }
2318private:
2319    bool isnull() const
2320    {
2321        return t.iskeyword("null");
2322    }
2323    bool isidentifier() const { return true; }
2324    std::string getidentifier() const
2325    {
2326        if (isnull())
2327            throw SyntaxError("Invalid 'null' usage", t);
2328        return t.identifier();
2329    }
2330    bool isinteger() const
2331    {
2332        return checklocal(t.str()) == REGint;
2333    }
2334    int getintegervalue () const
2335    {
2336        if (checkconstant(t.identifier()) == REGint)
2337        {
2338            ConstantValue cv= getconstant(t.identifier());
2339            if (cv.type () == REGint)
2340                return cv.value().getinteger();
2341        }
2342        throw SyntaxError("Not an integer value", t);
2343    }
2344    bool isstring() const
2345    {
2346        return checklocal(t.str()) == REGstring;
2347    }
2348    std::string getstringvalue() const
2349    {
2350        if (checkconstant(t.identifier()) == REGstring)
2351        {
2352            ConstantValue cv= getconstant(t.identifier());
2353            if (cv.type () == REGstring)
2354                return cv.value().str();
2355        }
2356        throw SyntaxError("Not a string value", t);
2357    }
2358
2359    Expr *optimize();
2360    void emit(Emit &e, const std::string &result);
2361};
2362
2363Expr *IdentifierExpr::optimize()
2364{
2365    char type= checkconstant(t.identifier());
2366    switch (type)
2367    {
2368    case REGint:
2369        {
2370        Token value = getconstant(t.identifier()).value();
2371        return new IntegerExpr(*this, t, value.getinteger());
2372        }
2373    case REGstring:
2374        {
2375        Token value = getconstant(t.identifier()).value();
2376        return new StringExpr(*this, value);
2377        }
2378    default: /* Not a constant */ ;
2379    }
2380    return this;
2381}
2382
2383void IdentifierExpr::emit(Emit &e, const std::string &result)
2384{
2385    if (!result.empty() )
2386        e << INDENT << result << " = ";
2387    e << getidentifier();
2388    if (! result.empty() )
2389        e << '\n';
2390}
2391
2392//**********************************************************************
2393
2394class OpBaseExpr : public Expr
2395{
2396public:
2397    OpBaseExpr(BlockBase &block, const Token & tstart) :
2398            Expr(block, tstart)
2399    { }
2400};
2401
2402//**********************************************************************
2403
2404class OpUnaryBaseExpr : public OpBaseExpr
2405{
2406public:
2407    OpUnaryBaseExpr(BlockBase &block, const Token &t, Expr *subexpr) :
2408        OpBaseExpr(block, t),
2409        expr(subexpr)
2410    { }
2411protected:
2412    Expr * expr;
2413private:
2414    Expr *optimize()
2415    {
2416        optimize_branch(expr);
2417        return this;
2418    }
2419};
2420
2421//**********************************************************************
2422
2423class OpUnaryMinusExpr : public OpUnaryBaseExpr
2424{
2425public:
2426    OpUnaryMinusExpr(BlockBase &block, const Token & tstart, Expr *subexpr) :
2427        OpUnaryBaseExpr(block, tstart, subexpr)
2428    {
2429    }
2430private:
2431    bool isinteger () const { return expr->isinteger(); }
2432    Expr *optimize()
2433    {
2434        optimize_branch(expr);
2435        if (expr->isliteralinteger() )
2436        {
2437            const int n= expr->getintegervalue();
2438            return new IntegerExpr(*this, getstart(), -n);
2439        }
2440        return this;
2441    }
2442    void emit(Emit &e, const std::string &result)
2443    {
2444        std::string arg= gentemp(REGint);
2445        expr->emit(e, arg);
2446        std::string r= result.empty() ? gentemp(REGint) : result;
2447        annotate(e);
2448        e << INDENT << r << " = neg " << arg;
2449        if (! result.empty() )
2450            e << '\n';
2451    }
2452};
2453
2454//**********************************************************************
2455
2456class OpNotExpr : public OpUnaryBaseExpr
2457{
2458public:
2459    OpNotExpr(BlockBase &block, const Token & tstart, Expr *subexpr) :
2460        OpUnaryBaseExpr(block, tstart, subexpr)
2461    {
2462    }
2463private:
2464    bool isinteger () const { return true; }
2465    Expr *optimize()
2466    {
2467        optimize_branch(expr);
2468        if (expr->isnull() )
2469            return new IntegerExpr(*this, getstart(), 1);
2470        if (expr->isliteralinteger() )
2471        {
2472            const int n= expr->getintegervalue();
2473            return new IntegerExpr(*this, getstart(), !n);
2474        }
2475        return this;
2476    }
2477    void emit(Emit &e, const std::string &result)
2478    {
2479        std::string arg= gentemp(expr->isinteger() ? REGint : REGvar);
2480        expr->emit(e, arg);
2481        std::string r= result.empty() ?
2482            gentemp(REGint) :
2483            result;
2484        annotate(e);
2485        e << INDENT;
2486        if (expr->isinteger())
2487            e << "not ";
2488        else
2489            e << "isfalse ";
2490        e << r << ", " << arg;
2491        if (! result.empty() )
2492            e << '\n';
2493    }
2494};
2495
2496//**********************************************************************
2497
2498class BinOpExpr : public OpBaseExpr
2499{
2500protected:
2501    BinOpExpr(BlockBase &block, const Token & tstart, Expr *first, Expr *second) :
2502        OpBaseExpr(block, tstart),
2503        lexpr(first),
2504        rexpr(second)
2505    {
2506    }
2507    void optimize_operands()
2508    {
2509        optimize_branch(lexpr);
2510        optimize_branch(rexpr);
2511    }
2512    Expr *lexpr;
2513    Expr *rexpr;
2514private:
2515    Expr *optimize()
2516    {
2517        optimize_operands();
2518        return this;
2519    }
2520};
2521
2522//**********************************************************************
2523
2524class CommonBinOpExpr : public BinOpExpr
2525{
2526public:
2527    CommonBinOpExpr(BlockBase &block,
2528            const Token & tstart, Expr *first, Expr *second) :
2529        BinOpExpr(block, tstart, first, second)
2530    {
2531    }
2532protected:
2533    bool isstring() const
2534    {
2535        return lexpr->isstring() && rexpr->isstring();
2536    }
2537    bool isinteger() const
2538    {
2539        return lexpr->isinteger() && rexpr->isinteger();
2540    }
2541};
2542
2543
2544//**********************************************************************
2545
2546class CompareOpExpr : public BinOpExpr
2547{
2548public:
2549    CompareOpExpr(BlockBase &block,
2550            const Token & tstart, Expr *first, Expr *second) :
2551        BinOpExpr(block, tstart, first, second)
2552    {
2553    }
2554protected:
2555    bool isinteger() const { return true; }
2556};
2557
2558//**********************************************************************
2559
2560class OpEqualExpr : public CompareOpExpr
2561{
2562public:
2563    OpEqualExpr(BlockBase &block,
2564            const Token & tstart, Expr *first, Expr *second) :
2565        CompareOpExpr(block, tstart, first, second)
2566    { }
2567private:
2568    bool isinteger() const { return true; }
2569    Expr *optimize();
2570    void emit(Emit &e, const std::string &result);
2571};
2572
2573Expr *OpEqualExpr::optimize()
2574{
2575    optimize_operands();
2576    if (lexpr->isnull() && rexpr->isnull())
2577    {
2578        return new IntegerExpr(*this, getstart(), 1);
2579    }
2580    if (lexpr->isliteralinteger() && rexpr->isliteralinteger())
2581    {
2582        return new IntegerExpr(*this, getstart(),
2583            lexpr->getintegervalue() == rexpr->getintegervalue());
2584    }
2585    if (lexpr->isliteralstring() && rexpr->isliteralstring())
2586    {
2587        std::string s1= lexpr->getstringvalue();
2588        std::string s2= rexpr->getstringvalue();
2589        return new IntegerExpr(*this, getstart(), s1 == s2);
2590    }
2591    return this;
2592}
2593
2594void OpEqualExpr::emit(Emit &e, const std::string &result)
2595{
2596    std::string res= gentemp(REGint);
2597    if (lexpr->isnull() || rexpr->isnull())
2598    {
2599        std::string op;
2600        if (lexpr->isnull())
2601            op= rexpr->emit_get(e);
2602        else
2603            op= lexpr->emit_get(e);
2604        e << op_isnull(res, op);
2605    }
2606    else
2607    {
2608        char ltype = lexpr->checkresult();
2609        char rtype = rexpr->checkresult();
2610        if (ltype == rtype)
2611        {
2612            std::string op1= gentemp(ltype);
2613            std::string op2= gentemp(rtype);
2614            lexpr->emit(e, op1);
2615            rexpr->emit(e, op2);
2616            e << op_iseq(res, op1, op2);
2617        }
2618        else if (ltype == REGvar && rtype == REGstring)
2619        {
2620            std::string op1= gentemp(REGstring);
2621            std::string op2= gentemp(REGstring);
2622            std::string aux= gentemp(REGvar);
2623            lexpr->emit(e, aux);
2624            rexpr->emit(e, op2);
2625            e << INDENT << op1 << " = " << aux << '\n';
2626            e << op_iseq(res, op1, op2);
2627        }
2628        else if (ltype == REGstring && rtype == REGvar)
2629        {
2630            std::string op1= gentemp(REGstring);
2631            std::string op2= gentemp(REGstring);
2632            std::string aux= gentemp(REGvar);
2633            lexpr->emit(e, op1);
2634            rexpr->emit(e, aux);
2635            e << INDENT << op2 << " = " << aux << '\n';
2636            e << op_iseq(res, op1, op2);
2637        }
2638        else
2639        {
2640            std::string op1= gentemp(REGvar);
2641            std::string op2= gentemp(REGvar);
2642            if (lexpr->isinteger() )
2643            {
2644                std::string aux= gentemp(REGint);
2645                lexpr->emit(e, aux);
2646                e << op_box(res, aux) << '\n';
2647            }
2648            else if (lexpr->isstring() )
2649            {
2650                std::string aux= gentemp(REGstring);
2651                lexpr->emit(e, aux);
2652                e << op_box(op1, aux) << '\n';
2653            }
2654            else
2655                lexpr->emit(e, op1);
2656            if (rexpr->isinteger() )
2657            {
2658                std::string aux= gentemp(REGint);
2659                rexpr->emit(e, aux);
2660                e << op_box(op2, aux) << '\n';
2661            }
2662            else if (rexpr->isstring() )
2663            {
2664                std::string aux= gentemp(REGstring);
2665                rexpr->emit(e, aux);
2666                e << op_box(op2, aux) << '\n';
2667            }
2668            else
2669                rexpr->emit(e, op2);
2670            e << op_iseq(res, op1, op2);
2671        }
2672    }
2673    if (!result.empty())
2674        e << '\n' << INDENT << result << " = " << res << '\n';
2675}
2676
2677//**********************************************************************
2678
2679class OpNotEqualExpr : public CompareOpExpr
2680{
2681public:
2682    OpNotEqualExpr(BlockBase &block,
2683            const Token & tstart, Expr *first, Expr *second) :
2684        CompareOpExpr(block, tstart, first, second)
2685    { }
2686private:
2687    Expr *optimize();
2688    void emit(Emit &e, const std::string &result);
2689};
2690
2691Expr *OpNotEqualExpr::optimize()
2692{
2693    optimize_operands();
2694    if (lexpr->isnull() && rexpr->isnull())
2695        return new IntegerExpr(*this, getstart(), 0);
2696    if (lexpr->isliteralinteger() && rexpr->isliteralinteger())
2697        return new IntegerExpr(*this, getstart(),
2698            lexpr->getintegervalue() != rexpr->getintegervalue());
2699    if (lexpr->isliteralstring() && rexpr->isliteralstring())
2700        return new IntegerExpr(*this, getstart(),
2701            lexpr->getstringvalue() != rexpr->getstringvalue());
2702    return this;
2703}
2704
2705void OpNotEqualExpr::emit(Emit &e, const std::string &result)
2706{
2707    std::string res= gentemp(REGint);
2708    if (lexpr->isnull() || rexpr->isnull())
2709    {
2710        std::string op;
2711        if (lexpr->isnull())
2712            op= rexpr->emit_get(e);
2713        else
2714            op= lexpr->emit_get(e);
2715        e << op_isnull(res, op) << '\n' <<
2716            INDENT "not " << res;
2717    }
2718    else if (lexpr->isinteger() && rexpr->isinteger())
2719    {
2720        std::string op1= gentemp(REGint);
2721        std::string op2= gentemp(REGint);
2722        lexpr->emit(e, op1);
2723        rexpr->emit(e, op2);
2724        e << op_isne(res, op1, op2);
2725    }
2726    else if (lexpr->isstring() && rexpr->isstring())
2727    {
2728        std::string op1= gentemp(REGstring);
2729        std::string op2= gentemp(REGstring);
2730        lexpr->emit(e, op1);
2731        rexpr->emit(e, op2);
2732        e << op_isne(res, op1, op2);
2733    }
2734    else
2735    {
2736        std::string op1= gentemp(REGvar);
2737        std::string op2= gentemp(REGvar);
2738        if (lexpr->isinteger() )
2739        {
2740            std::string aux= gentemp(REGint);
2741            lexpr->emit(e, aux);
2742            e << op_box(op1, aux) << '\n';
2743        }
2744        else if (lexpr->isstring() )
2745        {
2746            std::string aux= gentemp(REGstring);
2747            lexpr->emit(e, aux);
2748            e << op_box(op1, aux) << '\n';
2749        }
2750        else
2751            lexpr->emit(e, op1);
2752        if (rexpr->isinteger() )
2753        {
2754            std::string aux= gentemp(REGint);
2755            rexpr->emit(e, aux);
2756            e << op_box(op2, aux) << '\n';
2757        }
2758        else if (rexpr->isstring() )
2759        {
2760            std::string aux= gentemp(REGstring);
2761            rexpr->emit(e, aux);
2762            e << op_box(op2, aux) << '\n';
2763        }
2764        else
2765            rexpr->emit(e, op2);
2766        e << INDENT << res << " = isne " << op1 << " , " << op2;
2767    }
2768    if (!result.empty())
2769        e << '\n' << INDENT << result << " = " << res << '\n';
2770}
2771
2772//**********************************************************************
2773
2774class OpSameExpr : public CompareOpExpr
2775{
2776public:
2777    OpSameExpr(bool positiveform, BlockBase &block,
2778            const Token & tstart, Expr *first, Expr *second) :
2779        CompareOpExpr(block, tstart, first, second),
2780        positive(positiveform)
2781    { }
2782private:
2783    bool isinteger() const { return true; }
2784    void emit(Emit &e, const std::string &result)
2785    {
2786        char ltype = lexpr->checkresult();
2787        char rtype = rexpr->checkresult();
2788        if (! ((ltype == REGvar && rtype == REGvar) ||
2789                (ltype == REGstring && rtype == REGstring)))
2790            throw SyntaxError(std::string(positive ? "===" : "!==") +
2791                    " operator requires val types", getstart());
2792        std::string op1= gentemp(ltype);
2793        std::string op2= gentemp(rtype);
2794        lexpr->emit(e, op1);
2795        rexpr->emit(e, op2);
2796        std::string res= result.empty() ? gentemp(REGint) : result;
2797        e << INDENT << res << " = " << (positive ? "issame" : "isntsame") <<
2798            ' ' << op1 << " , " << op2;
2799        if (!result.empty())
2800            e << '\n' << INDENT << result << " = " << res << '\n';
2801    }
2802    bool positive;
2803};
2804
2805//**********************************************************************
2806
2807class ComparatorBaseExpr : public CompareOpExpr
2808{
2809protected:
2810    ComparatorBaseExpr(BlockBase &block,
2811            const Token & tstart, Expr *first, Expr *second) :
2812        CompareOpExpr(block, tstart, first, second)
2813    {
2814    }
2815    virtual void emitop(Emit &e, 
2816        const std::string &res,
2817        const std::string &op1, const std::string &op2) = 0;
2818private:
2819    void emit(Emit &e, const std::string &result);
2820};
2821
2822void ComparatorBaseExpr::emit(Emit &e, const std::string &result)
2823{
2824    std::string res= result.empty() ? gentemp(REGint) : result;
2825    char type1= lexpr->checkresult();
2826    char type2= rexpr->checkresult();
2827    if (type1 == REGint || type2 == REGint)
2828    {
2829        std::string op1= gentemp(REGint);
2830        std::string op2= gentemp(REGint);
2831        if (type1 == REGint)
2832            lexpr->emit(e, op1);
2833        else {
2834            std::string aux= gentemp(REGvar);
2835            lexpr->emit(e, aux);
2836            e << INDENT << op1 << " = " << aux << '\n';
2837        }
2838        if (type2 == REGint)
2839            rexpr->emit(e, op2);
2840        else {
2841            std::string aux= gentemp(REGvar);
2842            rexpr->emit(e, aux);
2843            e << INDENT << op2 << " = " << aux << '\n';
2844        }
2845        emitop(e, res, op1, op2);
2846        if (!result.empty())
2847            e << '\n';
2848    }
2849    else if (type1 == REGstring || type2 == REGstring)
2850    {
2851        std::string op1= gentemp(REGstring);
2852        std::string op2= gentemp(REGstring);
2853        if (type1 == REGstring)
2854            lexpr->emit(e, op1);
2855        else {
2856            std::string aux= gentemp(REGvar);
2857            lexpr->emit(e, aux);
2858            e << INDENT << op1 << " = " << aux << '\n';
2859        }
2860        if (type2 == REGstring)
2861            rexpr->emit(e, op2);
2862        else {
2863            std::string aux= gentemp(REGvar);
2864            rexpr->emit(e, aux);
2865            e << INDENT << op2 << " = " << aux << '\n';
2866        }
2867        emitop(e, res, op1, op2);
2868        if (!result.empty())
2869            e << '\n';
2870    }
2871    else
2872    {
2873        std::string op1= gentemp(REGvar);
2874        std::string op2= gentemp(REGvar);
2875        lexpr->emit(e, op1);
2876        rexpr->emit(e, op2);
2877        emitop(e, res, op1, op2);
2878        if (!result.empty())
2879            e << '\n';
2880    }
2881}
2882
2883//**********************************************************************
2884
2885class OpLessExpr : public ComparatorBaseExpr
2886{
2887public:
2888    OpLessExpr(BlockBase &block,
2889            const Token & tstart, Expr *first, Expr *second) :
2890        ComparatorBaseExpr(block, tstart, first, second)
2891    {
2892    }
2893private:
2894    void emitop(Emit &e, 
2895        const std::string &res,
2896        const std::string &op1, const std::string &op2)
2897    {
2898        e << op_islt(res, op1, op2);
2899    }
2900};
2901
2902//**********************************************************************
2903
2904class OpGreaterExpr : public ComparatorBaseExpr
2905{
2906public:
2907    OpGreaterExpr(BlockBase &block,
2908            const Token & tstart, Expr *first, Expr *second) :
2909        ComparatorBaseExpr(block, tstart, first, second)
2910    {
2911    }
2912private:
2913    void emitop(Emit &e, 
2914        const std::string &res,
2915        const std::string &op1, const std::string &op2)
2916    {
2917        e << op_isgt(res, op1, op2);
2918    }
2919};
2920
2921//**********************************************************************
2922
2923class OpLessEqualExpr : public ComparatorBaseExpr
2924{
2925public:
2926    OpLessEqualExpr(BlockBase &block,
2927            const Token & tstart, Expr *first, Expr *second) :
2928        ComparatorBaseExpr(block, tstart, first, second)
2929    {
2930    }
2931private:
2932    void emitop(Emit &e, 
2933        const std::string &res,
2934        const std::string &op1, const std::string &op2)
2935    {
2936        e << op_isle(res, op1, op2);
2937    }
2938};
2939
2940//**********************************************************************
2941
2942class OpGreaterEqualExpr : public ComparatorBaseExpr
2943{
2944public:
2945    OpGreaterEqualExpr(BlockBase &block,
2946            const Token & tstart, Expr *first, Expr *second) :
2947        ComparatorBaseExpr(block, tstart, first, second)
2948    {
2949    }
2950private:
2951    void emitop(Emit &e, 
2952        const std::string &res,
2953        const std::string &op1, const std::string &op2)
2954    {
2955        e << op_isge(res, op1, op2);
2956    }
2957};
2958
2959//**********************************************************************
2960
2961class OpAssignExpr : public BinOpExpr
2962{
2963public:
2964    OpAssignExpr(BlockBase &block,
2965            const Token & tstart, Expr *first, Expr *second) :
2966        BinOpExpr(block, tstart, first, second)
2967    {
2968    }
2969private:
2970    bool isinteger() const { return rexpr->isinteger(); }
2971    bool isstring() const { return rexpr->isstring(); }
2972    void emit(Emit &e, const std::string &result)
2973    {
2974        if (lexpr->isidentifier())
2975        {
2976            std::string varname= lexpr->getidentifier();
2977            char type= checklocal(varname);
2978            if (rexpr->isindex())
2979            {
2980                rexpr->emit(e, varname);
2981                if (! result.empty() )
2982                    e << INDENT << result << " = " << varname << '\n';
2983                return;
2984            }
2985            switch (type)
2986            {
2987            case REGint:
2988                if (!(rexpr->isinteger() || rexpr->isstring()))
2989                {
2990                    std::string r= gentemp(REGvar);
2991                    rexpr->emit(e, r);
2992                    annotate(e);
2993                    e << INDENT << varname << " = " << r << '\n';
2994                    if (! result.empty() )
2995                        e << INDENT << result << " = " << r << '\n';
2996                }
2997                else {
2998                    if (result.empty() )
2999                        rexpr->emit(e, varname);
3000                    else
3001                    {
3002                        std::string r= gentemp(REGint);
3003                        rexpr->emit(e, r);
3004                        annotate(e);
3005                        e << INDENT << varname << " = " << r << '\n';
3006                        e << INDENT << result << " = " << r << '\n';
3007                    }
3008                }
3009                break;
3010            case REGstring:
3011                if (rexpr->isnull())
3012                {
3013                    annotate(e);
3014                    e << op_null(varname) << '\n';
3015                }
3016                else if (!(rexpr->isinteger() || rexpr->isstring()))
3017                {
3018                    std::string r= gentemp(REGstring);
3019                    rexpr->emit(e, r);
3020                    annotate(e);
3021                    e << INDENT << varname << " = " << r << '\n';
3022                    if (! result.empty() )
3023                        e << INDENT << result << " = " << r << '\n';
3024                }
3025                else {
3026                    if (result.empty() )
3027                        rexpr->emit(e, varname);
3028                    else
3029                    {
3030                        std::string r= gentemp(REGstring);
3031                        rexpr->emit(e, r);
3032                        annotate(e);
3033                        e << INDENT << varname << " = " << r << '\n';
3034                        e << INDENT << result << " = " << r << '\n';
3035                    }
3036                }
3037                break;
3038            default:
3039                if (rexpr->isnull())
3040                {
3041                    annotate(e);
3042                    e << op_null(varname) << '\n';
3043                }
3044                else if (rexpr->isinteger() || rexpr->isstring() )
3045                {
3046                    annotate(e);
3047                    std::string r= gentemp(rexpr->checkresult());
3048                    rexpr->emit(e, r);
3049                    e << op_box(varname, r);
3050                    e << '\n';
3051                    if (! result.empty() )
3052                        e << INDENT << result << " = " << varname << '\n';
3053                }
3054                else
3055                {
3056                    rexpr->emit(e, varname);
3057                    if (! result.empty() )
3058                        e << INDENT << result << " = " << varname << '\n';
3059                }
3060            }
3061        }
3062        else
3063        {
3064            if (!lexpr->isleft() )
3065                throw SyntaxError("Not a left-side expression for '='", getstart());
3066
3067            std::string reg= result.empty() ? std::string() :
3068                gentemp(rexpr->checkresult());
3069            lexpr->emitassign(e, *rexpr, reg);
3070            if (! result.empty() )
3071                e << INDENT << result << " = " << reg << '\n';
3072        }
3073    }
3074};
3075
3076//**********************************************************************
3077
3078class OpAddExpr : public CommonBinOpExpr
3079{
3080public:
3081    OpAddExpr(BlockBase &block,
3082            const Token & tstart, Expr *first, Expr *second) :
3083        CommonBinOpExpr(block, tstart, first, second)
3084    {
3085    }
3086private:
3087    bool isstring () const
3088    {
3089        return (lexpr->isstring() &&
3090            (rexpr->isstring() || rexpr->isinteger()) ) ||
3091            (rexpr->isstring() &&
3092            (lexpr->isstring() || lexpr->isinteger()) );
3093    }
3094    Expr *optimize();
3095    void emit(Emit &e, const std::string &result);
3096};
3097
3098Expr *OpAddExpr::optimize()
3099{
3100    optimize_operands();
3101    if (lexpr->isliteralinteger() && rexpr->isliteralinteger())
3102    {
3103        return new IntegerExpr(*this, getstart(),
3104            lexpr->getintegervalue() + rexpr->getintegervalue());
3105    }
3106    if (lexpr->isliteralstring() && rexpr->isliteralstring())
3107    {
3108        Token newt= Token(TokenTQuoted, lexpr->getstringvalue() + rexpr->getstringvalue(), lexpr->gettoken());
3109        return new StringExpr(*this, newt);
3110    }
3111    return this;
3112}
3113
3114void OpAddExpr::emit(Emit &e, const std::string &result)
3115{
3116    if (lexpr->isstring() && rexpr->isstring())
3117    {
3118        std::string res= result.empty() ? gentemp(REGstring) : result;
3119        std::string op1= gentemp(REGstring);
3120        std::string op2= gentemp(REGstring);
3121        lexpr->emit(e, op1);
3122        rexpr->emit(e, op2);
3123        e << INDENT << res << " = concat " << op1 << " , " << op2;
3124    }
3125    else if (isinteger())
3126    {
3127        std::string res= result.empty() ? gentemp(REGint) : result;
3128        std::string op1= gentemp(REGint);
3129        std::string op2= gentemp(REGint);
3130        lexpr->emit(e, op1);
3131        rexpr->emit(e, op2);
3132        e << op_add(res, op1, op2);
3133    }
3134    else if (lexpr->isstring() && rexpr->isinteger())
3135    {
3136        std::string res= result.empty() ? gentemp(REGstring) : result;
3137        std::string op1= gentemp(REGstring);
3138        std::string op2= gentemp(REGint);
3139        std::string op2_s= gentemp(REGstring);
3140        lexpr->emit(e, op1);
3141        rexpr->emit(e, op2);
3142        e << op_set(op2_s, op2) << '\n' <<
3143            INDENT << res << " = concat " << op1 << " , " << op2_s;
3144    }
3145    else if (lexpr->isinteger() && rexpr->isstring())
3146    {
3147        std::string res= result.empty() ? gentemp(REGstring) : result;
3148        std::string op1= gentemp(REGint);
3149        std::string op2= gentemp(REGstring);
3150        std::string op1_s= gentemp(REGstring);
3151        lexpr->emit(e, op1);
3152        rexpr->emit(e, op2);
3153        e << op_set(op1_s, op1) << '\n' <<
3154            res << " = concat " << op1_s << " , " << op2;
3155    }
3156    else
3157    {
3158        std::string res= result.empty() ? gentemp(REGvar) : result;
3159        std::string op1= gentemp(REGvar);
3160        std::string op2= gentemp(REGvar);
3161        switch (lexpr->checkresult() )
3162        {
3163        case REGint:
3164            e << INDENT << op1 << " = new 'Integer'\n";
3165            break;
3166        case REGstring:
3167            e << INDENT << op1 << " = new 'String'\n";
3168            break;
3169        default:
3170            e << op_null(op1) << '\n';
3171        }
3172        switch (rexpr->checkresult() )
3173        {
3174        case REGint:
3175            e << INDENT << op2 << " = new 'Integer'\n";
3176            break;
3177        case REGstring:
3178            e << INDENT << op2 << " = new 'String'\n";
3179            break;
3180        default:
3181            e << op_null(op2) << '\n';
3182        }
3183        lexpr->emit(e, op1);
3184        rexpr->emit(e, op2);
3185        e << op_add(res, op1, op2);
3186    }
3187    if (!result.empty())
3188        e << '\n';
3189}
3190
3191//**********************************************************************
3192
3193class OpSubExpr : public CommonBinOpExpr
3194{
3195public:
3196    OpSubExpr(BlockBase &block,
3197            const Token & tstart, Expr *first, Expr *second) :
3198        CommonBinOpExpr(block, tstart, first, second)
3199    {
3200    }
3201private:
3202    Expr *optimize()
3203    {
3204        optimize_operands();
3205        if (lexpr->isliteralinteger() && rexpr->isliteralinteger())
3206        {
3207            int n1= lexpr->getintegervalue();
3208            int n2= rexpr->getintegervalue();
3209            return new IntegerExpr(*this, getstart(), n1 - n2);
3210        }
3211        return this;
3212    }
3213    void emit(Emit &e, const std::string &result)
3214    {
3215        std::string res= result.empty() ? gentemp(REGint) : result;
3216        std::string op1= gentemp(REGint);
3217        std::string op2= gentemp(REGint);
3218        lexpr->emit(e, op1);
3219        rexpr->emit(e, op2);
3220        e << op_sub(res, op1, op2);
3221        if (!result.empty())
3222            e << '\n';
3223    }
3224};
3225
3226//**********************************************************************
3227
3228class OpBoolOrExpr : public BinOpExpr
3229{
3230public:
3231    OpBoolOrExpr(BlockBase &block,
3232            const Token & tstart, Expr *first, Expr *second) :
3233        BinOpExpr(block, tstart, first, second)
3234    { }
3235private:
3236    bool isinteger() const { return true; }
3237    void emit(Emit &e, const std::string &result)
3238    {
3239        std::string res= result.empty() ? gentemp(REGint) : result;
3240        std::string op1= gentemp(REGint);
3241        std::string op2= gentemp(REGint);
3242        if (rexpr->issimple())
3243        {
3244            lexpr->emit(e, op1);
3245            rexpr->emit(e, op2);
3246            e << INDENT << res << " = or " << op1 << ", " << op2;
3247        }
3248        else
3249        {
3250            std::string l = genlocallabel();
3251            lexpr->emit(e, res);
3252            annotate(e);
3253            e << INDENT "if " << res << " goto " << l << '\n';
3254            rexpr->emit(e, res);
3255            e << INDENTLABEL << l << ":\n";
3256        }
3257        if (!result.empty())
3258            e << '\n';
3259    }
3260};
3261
3262//**********************************************************************
3263
3264class OpBinAndExpr : public CommonBinOpExpr
3265{
3266public:
3267    OpBinAndExpr(BlockBase &block,
3268            const Token & tstart, Expr *first, Expr *second) :
3269        CommonBinOpExpr(block, tstart, first, second)
3270    {
3271    }
3272private:
3273    bool isinteger() const { return true; }
3274    void emit(Emit &e, const std::string &result)
3275    {
3276        std::string res= result.empty() ? gentemp(REGint) : result;
3277        std::string op1= gentemp(REGint);
3278        std::string op2= gentemp(REGint);
3279        lexpr->emit(e, op1);
3280        rexpr->emit(e, op2);
3281        e << INDENT << res << " = band " << op1 << ", " << op2;
3282        if (!result.empty())
3283            e << '\n';
3284    }
3285};
3286
3287//**********************************************************************
3288
3289class OpBinOrExpr : public CommonBinOpExpr
3290{
3291public:
3292    OpBinOrExpr(BlockBase &block,
3293            const Token & tstart, Expr *first, Expr *second) :
3294        CommonBinOpExpr(block, tstart, first, second)
3295    {
3296    }
3297private:
3298    bool isinteger() const { return true; }
3299    void emit(Emit &e, const std::string &result)
3300    {
3301        std::string res= result.empty() ? gentemp(REGint) : result;
3302        std::string op1= gentemp(REGint);
3303        std::string op2= gentemp(REGint);
3304        lexpr->emit(e, op1);
3305        rexpr->emit(e, op2);
3306        e << INDENT <<  res << " = bor " << op1 << ", " << op2;
3307        if (!result.empty())
3308            e << '\n';
3309    }
3310};
3311
3312//**********************************************************************
3313
3314class OpBoolAndExpr : public OpBaseExpr
3315{
3316public:
3317    OpBoolAndExpr(BlockBase &block,
3318            const Token & tstart, Expr *first, Expr *second) :
3319        OpBaseExpr(block, tstart),
3320        lexpr(first),
3321        rexpr(second)
3322    { }
3323private:
3324    bool isinteger() const { return true; }
3325    Expr *optimize()
3326    {
3327        optimize_branch(lexpr);
3328        optimize_branch(rexpr);
3329        return this;
3330    }
3331    void emit(Emit &e, const std::string &result)
3332    {
3333        std::string res= result.empty() ? gentemp(REGint) : result;
3334        std::string op1= gentemp(REGint);
3335        std::string op2= gentemp(REGint);
3336        if (rexpr->issimple())
3337        {
3338            lexpr->emit(e, op1);
3339            rexpr->emit(e, op2);
3340            annotate(e);
3341            e << INDENT << res << " = and " << op1 << ", " << op2;
3342        }
3343        else
3344        {
3345            std::string l = genlocallabel();
3346            lexpr->emit(e, res);
3347            annotate(e);
3348            e << INDENT "unless " << res << " goto " << l << '\n';
3349            rexpr->emit(e, res);
3350            e << INDENTLABEL << l << ":\n";
3351        }
3352        if (!result.empty())
3353            e << '\n';
3354    }
3355    Expr *lexpr;
3356    Expr *rexpr;
3357};
3358
3359//**********************************************************************
3360
3361class OpMulExpr : public CommonBinOpExpr
3362{
3363public:
3364    OpMulExpr(BlockBase &block,
3365            const Token & tstart, Expr *first, Expr *second) :
3366        CommonBinOpExpr(block, tstart, first, second)
3367    { }
3368private:
3369    bool isinteger() const
3370    {
3371        return lexpr->isinteger() && rexpr->isinteger();
3372    }
3373    Expr *optimize()
3374    {
3375        optimize_operands();
3376        if (lexpr->isliteralinteger() && rexpr->isliteralinteger())
3377        {
3378            return new IntegerExpr(*this, getstart(),
3379                lexpr->getintegervalue() * rexpr->getintegervalue());
3380        }
3381        return this;
3382    }
3383    void emit(Emit &e, const std::string &result)
3384    {
3385        char type= isinteger() ? REGint : REGvar;
3386        std::string res= result.empty() ? gentemp(type) : result;
3387        std::string op1= gentemp(type);
3388        std::string op2= gentemp(type);
3389        lexpr->emit(e, op1);
3390        rexpr->emit(e, op2);
3391        e << op_mul(res, op1, op2);
3392        if (!result.empty())
3393            e << '\n';
3394    }
3395};
3396
3397
3398//**********************************************************************
3399
3400class OpDivExpr : public CommonBinOpExpr
3401{
3402public:
3403    OpDivExpr(BlockBase &block,
3404            const Token & tstart, Expr *first, Expr *second) :
3405        CommonBinOpExpr(block, tstart, first, second)
3406    {
3407    }
3408private:
3409    void emit(Emit &e, const std::string &result)
3410    {
3411        char type= lexpr->isinteger() && rexpr->isinteger() ? REGint : REGvar;
3412        std::string res= result.empty() ? gentemp(type) : result;
3413        std::string op1= gentemp(type);
3414        std::string op2= gentemp(type);
3415        if (lexpr->isinteger() && type != REGint) {
3416            std::string i1= gentemp(REGint);
3417            lexpr->emit(e, i1);
3418            e << op_box(op1, i1);
3419        }
3420        else
3421            lexpr->emit(e, op1);
3422        if (rexpr->isinteger() && type != REGint) {
3423            std::string i2= gentemp(REGint);
3424            rexpr->emit(e, i2);
3425            e << op_box(op2, i2) << '\n';
3426        }
3427        else
3428            rexpr->emit(e, op2);
3429        if (result.empty())
3430            e << INDENT "new " << res << ", 'Integer'" << '\n';
3431        e << op_div(res, op1, op2);
3432        if (!result.empty())
3433            e << '\n';
3434    }
3435};
3436
3437//**********************************************************************
3438
3439class ArrayExpr : public Expr
3440{
3441public:
3442    ArrayExpr(BlockBase &block, Tokenizer &tk, const Token & tstart) :
3443            Expr(block, tstart)
3444    {
3445        Token t = tk.get();
3446        if (! t.isop (']') )
3447        {
3448            tk.unget(t);
3449            do {
3450                elems.push_back(parseExpr(block, tk));
3451                t= tk.get();
3452            } while (t.isop(',') );
3453            RequireOp (']', t);
3454        }
3455    }
3456private:
3457    Expr *optimize()
3458    {
3459        for (size_t i= 0; i < elems.size(); ++i)
3460            optimize_branch(elems[i]);
3461        return this;
3462    }
3463    void emit(Emit &e, const std::string &result);
3464    std::vector<Expr *> elems;
3465};
3466
3467static void emit_maybeboxed(Emit &e, BlockBase &bl,
3468        Expr &elem, const std::string &el)
3469{
3470    char type = elem.checkresult();
3471    switch (type)
3472    {
3473    case REGint: case REGstring:
3474        {
3475            std::string aux = bl.gentemp(type);
3476            elem.emit(e, aux);
3477            e << op_box(el, aux) << '\n';
3478        }
3479        break;
3480    default:
3481        elem.emit(e, el);
3482    }
3483}
3484
3485void ArrayExpr::emit(Emit &e, const std::string &result)
3486{
3487    std::string reg = gentemp(REGvar);
3488    e << INDENT << reg << " = root_new ['parrot';'ResizablePMCArray']\n";
3489    for (size_t i= 0; i < elems.size(); ++i)
3490    {
3491        Expr *elem= elems[i];
3492        std::string el = gentemp(REGvar);
3493        if (elem->issimple())
3494        {
3495            if (elem->isidentifier())
3496            {
3497                std::string id= elem->getidentifier();
3498                if (checklocal(id))
3499                    emit_maybeboxed(e, *this, *elem, el);
3500                else if (FunctionStatement *fun = getfunction(id))
3501                {
3502                    std::string subid = fun->getsubid();
3503                    e << INDENT ".const 'Sub' " << subid << " = '" << subid << "'\n";
3504                    el = subid;
3505                }
3506                else
3507                    emit_maybeboxed(e, *this, *elem, el);
3508            }
3509            else
3510            {
3511                e << INDENT << el << " = box ";
3512                elem->emit(e, std::string());
3513                e << "\n";
3514            }
3515        }
3516        else
3517            emit_maybeboxed(e, *this, *elem, el);
3518        e << INDENT "push " << reg << " , " << el << '\n';
3519    }
3520
3521    if (!result.empty())
3522        e << INDENT << result << " = " << reg << '\n';
3523}
3524
3525//**********************************************************************
3526
3527class HashExpr : public Expr
3528{
3529public:
3530    HashExpr(BlockBase &block, Tokenizer &tk, const Token & tstart);
3531private:
3532    Expr *optimize()
3533    {
3534        for (std::map<std::string, Expr *>::iterator
3535            it= elems.begin();
3536            it != elems.end();
3537            ++it)
3538        {
3539            optimize_branch(it->second);
3540        }
3541        return this;
3542    }
3543    void emit(Emit &e, const std::string &result);
3544    std::map<std::string, Expr *> elems;
3545};
3546
3547HashExpr::HashExpr(BlockBase &block, Tokenizer &tk, const Token & tstart) :
3548    Expr(block, tstart)
3549{
3550    Token t = tk.get();
3551    if (! t.isop ('}') )
3552    {
3553        tk.unget(t);
3554        do {
3555            Token tkey= tk.get();
3556            if (! (tkey.isliteralstring() || tkey.isidentifier() ) )
3557                throw Expected("key", t);
3558            t= tk.get();
3559            RequireOp (':', t);
3560            Expr *value= parseExpr(block, tk);
3561            std::string key;
3562            if (tkey.isidentifier())
3563                key= "'" + tkey.identifier() + "'";
3564            else if (tkey.isliteralstring())
3565                key= tkey.pirliteralstring();
3566            else
3567                throw Expected("Identifier or string", tkey);
3568            elems[key]= value;
3569            t= tk.get();
3570        } while (t.isop(',') );
3571        RequireOp ('}', t);
3572    }
3573}
3574
3575class EmitItem
3576{
3577public:
3578    EmitItem(Emit &em, HashExpr &block,
3579            const std::string reg) :
3580        e(&em), bl(block), r(reg) { }
3581    void operator() (std::pair<std::string, Expr *> elem)
3582    {
3583        Expr *value= elem.second;
3584        std::string reg;
3585        if (value->isidentifier() )
3586        {
3587            std::string id= value->getidentifier();
3588            if (bl.checklocal(id))
3589                reg= id;
3590            else if (FunctionStatement *fun = bl.getfunction(id))
3591            {
3592                std::string subid = fun->getsubid();
3593                (*e) << INDENT ".const 'Sub' " << subid << " = '" << subid << "'\n";
3594                reg = subid;
3595            }
3596            else
3597            {
3598                reg = bl.gentemp(REGvar);
3599                (*e) << INDENT "get_hll_global " << reg << ", '" <<
3600                    id << "'\n";
3601            }
3602        }
3603        else if (value->isinteger())
3604        {
3605            reg = bl.gentemp(REGint);
3606            value->emit(*e, reg);
3607        }
3608        else if (value->isstring())
3609        {
3610            reg = bl.gentemp(REGstring);
3611            value->emit(*e, reg);
3612        }
3613        else
3614        {
3615            reg = bl.gentemp(REGvar);
3616            value->emit(*e, reg);
3617        }
3618        (*e) << INDENT << r << " [" << elem.first << "] = " << reg << '\n';
3619    }
3620private:
3621    Emit *e;
3622    HashExpr &bl;
3623    std::string r;
3624};
3625
3626void HashExpr::emit(Emit &e, const std::string &result)
3627{
3628    std::string reg = gentemp(REGvar);
3629    e << INDENT << reg << " = root_new ['parrot';'Hash']\n";
3630    std::for_each(elems.begin(), elems.end(), EmitItem(e, *this, reg) );
3631    if (!result.empty())
3632        e << INDENT << result << " = " << reg << '\n';
3633}
3634
3635//**********************************************************************
3636
3637class MemberExpr : public Expr
3638{
3639public:
3640    MemberExpr(BlockBase &block, Tokenizer &tk, const Token & tstart,
3641            Expr *leftexpr) :
3642        Expr(block, tstart),
3643        left(leftexpr),
3644        right(tk.get())
3645    {
3646        if (!right.isidentifier())
3647            throw Expected("identifier", right);
3648    }
3649    void emit(Emit &e, const std::string &result)
3650    {
3651        std::string reg = gentemp(REGvar);
3652        std::string r = (result.empty() ||
3653                (result[0] == '$' && result.substr(0, 2) != "$P") ) ?
3654            gentemp(REGvar) : result;
3655        left->emit(e, reg);
3656        annotate(e);
3657        e << INDENT "getattribute " << r << ", " << reg <<
3658            ", '" << right.identifier() << "'\n";
3659        if (result != r)
3660            e << op_set(result, r) << '\n';
3661    }
3662    std::string getmember() const { return right.identifier(); }
3663    void emitleft(Emit &e, const std::string &result)
3664    {
3665        char type= left->checkresult();
3666        switch(type)
3667        {
3668        case REGint: case REGstring:
3669            {
3670                std::string aux= gentemp(type);
3671                left->emit(e, aux);
3672                e << op_box(result, aux) << '\n';
3673            }
3674            break;
3675        default:
3676            left->emit(e, result);
3677        }
3678    }
3679    bool isleft() const { return true; }
3680    void emitleft(Emit &)
3681    {
3682        throw InternalError("here");
3683    }
3684    void emitassign(Emit &e, Expr& value, const std::string &to)
3685    {
3686        annotate(e);
3687        std::string reg = gentemp(REGvar);
3688        left->emit(e, reg);
3689        char typevalue= value.checkresult();
3690        std::string regval= gentemp(typevalue);
3691        if (value.isnull())
3692            e << op_null(regval) << '\n';
3693        else
3694            value.emit(e, regval);
3695        e << '\n';
3696        std::string regattrval;
3697        if (typevalue == REGvar)
3698            regattrval= regval;
3699        else
3700        {
3701            regattrval= gentemp(REGvar);
3702            e << op_box(regattrval, regval) << '\n';
3703        }
3704        e << INDENT "setattribute " << reg << ", '" << right.identifier() <<
3705                "', " << regattrval << '\n';
3706
3707        if (! to.empty())
3708            e << INDENT "set " << to << ", " << regattrval << '\n';
3709    }
3710private:
3711    Expr *left;
3712    Token right;
3713};
3714
3715//**********************************************************************
3716
3717class CallExpr : public Expr
3718{
3719public:
3720    CallExpr(BlockBase &block, Tokenizer &tk, const Token & tstart,
3721            Expr *function) :
3722        Expr(block, tstart),
3723        called(function),
3724        args(0)
3725    {
3726        Token t= tk.get();
3727        if (! t.isop (')') )
3728        {
3729            tk.unget(t);
3730            args= new ArgumentList(block, tk, ')');
3731        }
3732    }
3733    Expr * optimize()
3734    {
3735        if (args)
3736            args->optimize();
3737        return this;
3738    }
3739    bool isinteger() const;
3740    bool isstring() const;
3741private:
3742    void emit(Emit &e, const std::string &result);
3743    Expr *called;
3744    ArgumentList *args;
3745};
3746
3747
3748bool CallExpr::isinteger() const
3749{
3750    if (called->isidentifier())
3751    {
3752        std::string name= called->getidentifier();
3753        int numargs = args ? args->numargs() : 0;
3754        if (const BuiltinFunction *builtin=
3755                BuiltinFunction::find(name, numargs))
3756        {
3757            return builtin->resulttype() == REGint;
3758        }
3759    }
3760    return false;
3761}
3762
3763bool CallExpr::isstring() const
3764{
3765    if (called->isidentifier())
3766    {
3767        std::string name= called->getidentifier();
3768        int numargs = args ? args->numargs() : 0;
3769        if (const BuiltinFunction *builtin=
3770                BuiltinFunction::find(name, numargs))
3771        {
3772            return builtin->resulttype() == REGstring;
3773        }
3774    }
3775    return false;
3776}
3777
3778void CallExpr::emit(Emit &e, const std::string &result)
3779{
3780    const int numargs = args ? args->numargs() : 0;
3781    if (called->isidentifier())
3782    {
3783        annotate(e);
3784        std::string name= called->getidentifier();
3785
3786    if (const BuiltinFunction *builtin=
3787            BuiltinFunction::find(name, numargs))
3788    {
3789        std::vector<std::string> argregs;
3790        for (int i= 0; i < numargs; ++i)
3791        {
3792            Expr &arg= * (args->getfreearg(i));
3793            char paramtype= builtin->paramtype(i);
3794            switch (paramtype)
3795            {
3796            case REGint:
3797                if (arg.isliteralinteger())
3798                    argregs.push_back(arg.gettoken().str());
3799                else if (arg.isinteger() && arg.isidentifier())
3800                    argregs.push_back(arg.getidentifier());
3801                else
3802                {
3803                    std::string reg= gentemp(REGint);
3804                    arg.emit(e, reg);
3805                    argregs.push_back(reg);
3806                }
3807                break;
3808            case REGstring:
3809                if (arg.isliteralstring())
3810                    argregs.push_back(arg.gettoken().pirliteralstring());
3811                else if (arg.isstring() && arg.isidentifier())
3812                    argregs.push_back(arg.getidentifier());
3813                else
3814                {
3815                    std::string reg= gentemp(REGstring);
3816                    arg.emit(e, reg);
3817                    argregs.push_back(reg);
3818                }
3819                break;
3820            case REGany:
3821                argregs.push_back(arg.emit_get(e));
3822                break;
3823            default:
3824                {
3825                    std::string reg= gentemp(REGvar);
3826                    char type= arg.checkresult();
3827                    switch(type)
3828                    {
3829                    case REGint:
3830                    case REGstring:
3831                        {
3832                        std::string reg2= gentemp(type);
3833                        arg.emit(e, reg2);
3834                        e << op_box(reg, reg2) << '\n';
3835                        }
3836                        break;
3837                    default:
3838                        arg.emit(e, reg);
3839                    }
3840                    argregs.push_back(reg);
3841                }
3842            }
3843        }
3844        if (builtin->resulttype())
3845        {
3846            std::string r;
3847            if (result.empty())
3848                r= gentemp(builtin->resulttype());
3849            else
3850                r= result;
3851            builtin->emit(e, r, argregs);
3852        }
3853        else
3854            builtin->emit(e, std::string(), argregs);
3855        return;
3856    }
3857    }
3858
3859    if (args)
3860        args->prepare(e);
3861
3862    std::string reg;
3863    if (called->isidentifier())
3864    {
3865        std::string name= called->getidentifier();
3866        bool is_local = islocal(name);
3867        if (! is_local) {
3868            FunctionStatement *fun = getfunction(name);
3869            if (fun) {
3870                name = fun->getsubid();
3871                e << INDENT ".const 'Sub' " << name << " = '" << name << "'\n";
3872                is_local = true;
3873            }
3874        }
3875        std::string quote(is_local ? "" : "'");
3876        name = quote + name + quote;
3877        annotate(e);
3878        e << INDENT;
3879        if (!result.empty() )
3880            e << result << " = ";
3881        e << name << '(';
3882    }
3883    else
3884    {
3885        reg= gentemp(REGvar);
3886        if (MemberExpr *me= dynamic_cast<MemberExpr*>(called))
3887        {
3888            std::string mefun= gentemp(REGvar);
3889            me->emitleft(e, mefun);
3890            annotate(e);
3891            e << INDENT << reg << " = " << mefun << ".'" << me->getmember() << "'(";
3892        }
3893        else
3894        {
3895            called->emit(e, reg);
3896            annotate(e);
3897            e << INDENT << reg << '(';
3898        }
3899    }
3900
3901    // Arguments
3902    if (args)
3903        args->emit(e);
3904
3905    e << ')';
3906
3907    if (! reg.empty() )
3908    {
3909        e << '\n';
3910        if (!result.empty() )
3911            e << INDENT << result << " = " << reg << '\n';
3912    }
3913    else
3914    {
3915        if (!result.empty() )
3916            e << '\n';
3917    }
3918}
3919
3920//**********************************************************************
3921
3922class OpInstanceOf : public Expr
3923{
3924public:
3925    OpInstanceOf(BlockBase &block, const Token & tstart,
3926            Expr *subexpr, Tokenizer &tk) :
3927        Expr(block, tstart),
3928        obj(subexpr),
3929        checked(tk.get())
3930    {
3931    }
3932private:
3933    bool isinteger() const { return true; }
3934    Expr *optimize()
3935    {
3936        optimize_branch(obj);
3937        return this;
3938    }
3939    void emit(Emit &e, const std::string &result)
3940    {
3941        std::string checkedval;
3942        if (checked.isliteralstring())
3943            checkedval= checked.pirliteralstring();
3944        else if (checked.isidentifier())
3945        {
3946            ClassKey key;
3947            key.push_back(checked.identifier());
3948            ClassStatement *cl = findclass(key);
3949            if (cl)
3950                checkedval = cl->getkey().get_key();
3951            else
3952                checkedval= "'" + checked.identifier() + "'";
3953        }
3954        else
3955            throw CompileError("Unimplemented", checked);
3956
3957        std::string reg= gentemp(REGvar);
3958        obj->emit(e, reg);
3959        annotate(e);
3960
3961        if (result.empty() ) {
3962            std::string regcheck = gentemp(REGint);
3963            e << op_isa(regcheck, reg, checkedval) << '\n';
3964        }
3965        else
3966        {
3967            e << op_isa(result, reg, checkedval) << '\n';
3968        }
3969    }
3970    Expr *obj;
3971    Token checked;
3972};
3973
3974//**********************************************************************
3975
3976class NewExpr : public Expr
3977{
3978public:
3979    NewExpr(BlockBase &block, Tokenizer &tk, const Token & tstart);
3980private:
3981    Expr *optimize();
3982    void emit(Emit &e, const std::string &result);
3983    unsigned int ln;
3984    ClassSpecifier *claspec;
3985    ArgumentList *init;
3986};
3987
3988NewExpr::NewExpr(BlockBase &block, Tokenizer &tk, const Token & tstart) :
3989    Expr(block, tstart),
3990    ln(tstart.linenum()),
3991    init(0)
3992{
3993    Token t= tk.get();
3994
3995    claspec = parseClassSpecifier(t, tk, block);
3996
3997    t= tk.get();
3998
3999    if (t.isop('('))
4000        init = new ArgumentList(block, tk, ')');
4001    else
4002        tk.unget(t);
4003}
4004
4005Expr *NewExpr::optimize()
4006{
4007    if (init)
4008        init->optimize();
4009    return this;
4010}
4011
4012void NewExpr::emit(Emit &e, const std::string &result)
4013{
4014    std::string reg;
4015    std::string regnew = result;
4016    int numinits = init ? init->numargs() : -1;
4017    switch (numinits)
4018    {
4019    case -1:
4020    case 0:
4021        break;
4022    case 1:
4023        if (claspec->reftype() == CLASSSPECIFIER_id)
4024            regnew = gentemp(REGvar);
4025        else
4026        {
4027            reg = gentemp(REGvar);
4028            init->getfreearg(0)->emit(e, reg);
4029        }
4030        break;
4031    default:
4032        regnew = gentemp(REGvar);
4033        break;
4034    }
4035
4036    
4037    if (! result.empty())
4038        e << INDENT << regnew << " = ";
4039
4040    e << "new ";
4041    claspec->emit(e);
4042    if (! result.empty())
4043    {
4044        if (! reg.empty())
4045            e << ", " << reg;
4046    }
4047    e << '\n';
4048
4049    if (numinits > 1 ||
4050            (numinits >= 0 && claspec->reftype() == CLASSSPECIFIER_id))
4051    {
4052        init->prepare(e);
4053
4054        e << INDENT << regnew << ".'" << claspec->basename() << "'(";
4055        init->emit(e);
4056        e << ")\n";
4057        e << op_set(result, regnew) << '\n';
4058    }
4059}
4060
4061//**********************************************************************
4062
4063class NewIndexedExpr : public Expr
4064{
4065public:
4066    NewIndexedExpr(BlockBase &block, Tokenizer &tk, const Token & tstart) :
4067            Expr(block, tstart),
4068            init(0)
4069    {
4070        Token first = tk.get();
4071        if (!first.isliteralstring())
4072            throw Expected("string literal", first);
4073        Token t = tk.get();
4074        if (t.isop(':')) {
4075            hll = first.pirliteralstring();
4076            first = tk.get();
4077            if (!first.isliteralstring())
4078                throw Expected("string literal", first);
4079            t = tk.get();
4080        }
4081        nskey.push_back(first.pirliteralstring());
4082        while (t.isop(',')) {
4083            first = tk.get();
4084            if (!first.isliteralstring())
4085                throw Expected("string literal", first);
4086            nskey.push_back(first.pirliteralstring());
4087            t = tk.get();
4088        }
4089        t= tk.get();
4090
4091        if (t.isop('('))
4092            init = new ArgumentList(block, tk, ')');
4093        else
4094            tk.unget(t);
4095    }
4096private:
4097    Expr *optimize()
4098    {
4099        return this;
4100    }
4101    void emit(Emit &e, const std::string &result)
4102    {
4103        if (init) {
4104            if (init->numargs() != 1)
4105                throw SyntaxError("Wrong number of arguments", getstart());
4106            init->prepare(e);
4107        }
4108        std::string sep;
4109        if (!hll.empty()) {
4110            e << INDENT "root_new " << result << ", [" << hll;
4111            sep = ";";
4112        }
4113        else {
4114            e << INDENT "new " << result << ", ";
4115            sep = "[";
4116        }
4117        for (std::vector<std::string>::iterator it = nskey.begin();
4118            it != nskey.end(); ++it)
4119        {
4120            e << sep << *it;
4121            sep = ";";
4122        }
4123        e << "]";
4124        if (init) {
4125            e << ", ";
4126            init->emit(e);
4127        }
4128        e << "\n";
4129    }
4130
4131    std::string hll;
4132    std::vector<std::string> nskey;
4133    ArgumentList *init;
4134};
4135
4136//**********************************************************************
4137
4138Expr *parseNew(BlockBase &block, Tokenizer &tk, const Token & tstart)
4139{
4140    Token t = tk.get();
4141    if (t.isop('['))
4142        return new NewIndexedExpr(block, tk, tstart);
4143    else {
4144        tk.unget(t);
4145        return new NewExpr(block, tk, tstart);
4146    }
4147}
4148
4149//**********************************************************************
4150
4151class IndexExpr : public Expr
4152{
4153public:
4154    IndexExpr(BlockBase &block, Tokenizer &tk, const Token & tname) :
4155        Expr(block, tname),
4156        name(tname.identifier())
4157    {
4158        Token t;
4159        do {
4160            Expr *newarg = parseExpr(block, tk);
4161            arg.push_back(newarg);
4162        } while ((t= tk.get()).isop(','));
4163        RequireOp (']', t);
4164    }
4165private:
4166    bool isleft() const { return true; }
4167    bool isindex() const { return true; }
4168    Expr *optimize();
4169    void emit(Emit &e, const std::string &result);
4170    void emitleft(Emit &e);
4171    void emitassign(Emit &e, Expr& value, const std::string &to);
4172    std::string name;
4173    std::vector <Expr *> arg;
4174};
4175
4176Expr *IndexExpr::optimize()
4177{
4178    for (size_t i= 0; i < arg.size(); ++i)
4179        arg[i]= arg[i]->optimize();
4180    return this;
4181}
4182
4183void IndexExpr::emit(Emit &e, const std::string &result)
4184{
4185    std::string reg;
4186    size_t nitems= arg.size();
4187    std::vector <std::string> argvalue(nitems);
4188    for (size_t i= 0; i < nitems; ++i)
4189    {
4190        if (! arg[i]->issimple() )
4191        {
4192            reg= arg[i]->emit_get(e);
4193            argvalue[i]= reg;
4194        }
4195    }
4196    if (!result.empty() )
4197        e << INDENT << result << " = ";
4198    e << name << '[';
4199    for (size_t i= 0; i < nitems; ++i)
4200    {
4201        if (i > 0) e << ';';
4202        if (argvalue[i].empty() )
4203            arg[i]->emit(e, std::string());
4204        else
4205            e << argvalue[i];
4206    }
4207    e << ']';
4208    if (!result.empty() )
4209        e << '\n';
4210}
4211
4212void IndexExpr::emitleft(Emit &e)
4213{
4214    std::string reg;
4215    size_t nitems= arg.size();
4216    std::vector <std::string> argvalue(nitems);
4217    for (size_t i= 0; i < nitems; ++i)
4218    {
4219        if (! arg[i]->issimple() )
4220        {
4221            reg= gentemp(REGvar);
4222            arg[i]->emit(e, reg);
4223            argvalue[i]= reg;
4224        }
4225    }
4226    e << name << '[';
4227    for (size_t i= 0; i < nitems; ++i)
4228    {
4229        if (i > 0) e << ';';
4230        if (argvalue[i].empty() )
4231            arg[i]->emit(e, std::string());
4232        else
4233            e << argvalue[i];
4234    }
4235    e << ']';
4236}
4237
4238void IndexExpr::emitassign(Emit &e, Expr& value, const std::string &to)
4239{
4240    std::string reg2;
4241    if (value.isnull()) {
4242        reg2= gentemp(REGvar);
4243        e << op_null(reg2) << '\n';
4244    }
4245    else
4246    {
4247        reg2= value.emit_get(e);
4248        e << '\n';
4249    }
4250
4251    size_t nitems= arg.size();
4252    std::vector <std::string> argvalue(nitems);
4253    for (size_t i= 0; i < nitems; ++i)
4254    {
4255        if (! arg[i]->issimple() )
4256            argvalue[i]= arg[i]->emit_get(e);
4257    }
4258    e << INDENT << name << '[';
4259    for (size_t i= 0; i < nitems; ++i)
4260    {
4261        if (i > 0) e << ';';
4262        if (argvalue[i].empty() )
4263            arg[i]->emit(e, std::string());
4264        else
4265            e << argvalue[i];
4266    }
4267    e << "] = " << reg2 << '\n';
4268
4269    if (!to.empty())
4270        e << INDENT "set " << to << ", " << reg2 << '\n';
4271}
4272
4273//**********************************************************************
4274
4275class OpConditionalExpr : public Expr
4276{
4277public:
4278    OpConditionalExpr(BlockBase &block, const Token & tstart,
4279            Expr *econd, Expr *etrue, Expr *efalse) :
4280        Expr(block, tstart),
4281        condition(new Condition(block, econd)),
4282        exprtrue(etrue),
4283        exprfalse(efalse)
4284    {
4285    }
4286private:
4287    bool isinteger() const { return exprtrue->isinteger(); }
4288    bool isstring() const { return exprtrue->isstring(); }
4289    Expr *optimize()
4290    {
4291        condition= condition->optimize();
4292        switch (condition->getvalue() )
4293        {
4294        case Condition::CVfalse:
4295            return exprfalse->optimize();
4296        case Condition::CVtrue:
4297            return exprtrue->optimize();
4298        default:
4299            exprtrue = exprtrue->optimize();
4300            exprfalse = exprfalse->optimize();
4301            return this;
4302        }
4303    }
4304    void emit(Emit &e, const std::string &result)
4305    {
4306        std::string label_false= genlocallabel();
4307        std::string label_end= genlocallabel();
4308        condition->emit_else(e, label_false);
4309        exprtrue->emit(e, result);
4310        e << INDENT "goto " << label_end << '\n';
4311        e << INDENTLABEL << label_false << ":\n";
4312        if (exprfalse->isnull())
4313            e << op_null(result) << '\n';
4314        else
4315            exprfalse->emit(e, result);
4316        e << INDENTLABEL << label_end << ":\n";
4317    }
4318    Condition *condition;
4319    Expr *exprtrue;
4320    Expr *exprfalse;
4321};
4322
4323//**********************************************************************
4324
4325Expr * parseExpr_16(BlockBase &block, Tokenizer &tk);
4326Expr * parseExpr_15(BlockBase &block, Tokenizer &tk);
4327Expr * parseExpr_14(BlockBase &block, Tokenizer &tk);
4328Expr * parseExpr_13(BlockBase &block, Tokenizer &tk);
4329Expr * parseExpr_9(BlockBase &block, Tokenizer &tk);
4330Expr * parseExpr_8(BlockBase &block, Tokenizer &tk);
4331Expr * parseExpr_6(BlockBase &block, Tokenizer &tk);
4332Expr * parseExpr_5(BlockBase &block, Tokenizer &tk);
4333Expr * parseExpr_4(BlockBase &block, Tokenizer &tk);
4334Expr * parseExpr_2(BlockBase &block, Tokenizer &tk);
4335Expr * parseExpr_0(BlockBase &block, Tokenizer &tk);
4336
4337Expr * parseExpr_0(BlockBase &block, Tokenizer &tk)
4338{
4339    Expr *subexpr= NULL;
4340    Token t= tk.get();
4341
4342    if (t.isop('(') )
4343    {
4344        subexpr = parseExpr(block, tk);
4345        t= tk.get();
4346        RequireOp (')', t);
4347    }
4348    else if (t.isop('[') )
4349    {
4350        subexpr = new ArrayExpr(block, tk, t);
4351    }
4352    else if (t.isop('{') )
4353    {
4354        subexpr = new HashExpr(block, tk, t);
4355    }
4356    else if (t.iskeyword("new"))
4357            subexpr = parseNew(block, tk, t);
4358    else
4359    {
4360        Token t2= tk.get();
4361        if (t2.isop('[') )
4362            subexpr = new IndexExpr(block, tk, t);
4363        else
4364        {
4365            tk.unget(t2);
4366            if (t.isidentifier())
4367                subexpr = new IdentifierExpr(block, t);
4368            else if (t.isinteger())
4369                subexpr = new IntegerExpr(block, t);
4370            else if (t.isliteralstring())
4371                subexpr = new StringExpr(block, t);
4372            else
4373                throw SyntaxError("Invalid statement", t);
4374        }
4375    }
4376    return subexpr;
4377}
4378
4379Expr *parseExpr_2(BlockBase &block, Tokenizer &tk)
4380{
4381    Expr *subexpr= parseExpr_0(block, tk);
4382    Token t;
4383    while ((t= tk.get()).isop('.') || t.isop('('))
4384    {
4385        if (t.isop('.'))
4386            subexpr= new MemberExpr(block, tk, t, subexpr);
4387        else
4388        {
4389            subexpr = new CallExpr(block, tk, t, subexpr);
4390        }
4391    }
4392    tk.unget(t);
4393    return subexpr;
4394}
4395
4396Expr * parseExpr_4(BlockBase &block, Tokenizer &tk)
4397{
4398    Token t= tk.get();
4399    if (t.isop('-') )
4400    {
4401        Expr *subexpr= parseExpr_4(block, tk);
4402        return new OpUnaryMinusExpr(block, t, subexpr);
4403    }
4404    else if (t.isop('!') )
4405    {
4406        Expr *subexpr= parseExpr_4(block, tk);
4407        return new OpNotExpr(block, t, subexpr);
4408    }
4409    else
4410    {
4411        tk.unget(t);
4412        return parseExpr_2(block, tk);
4413    }
4414}
4415
4416
4417Expr * parseExpr_5(BlockBase &block, Tokenizer &tk)
4418{
4419    Expr *subexpr= parseExpr_4(block, tk);
4420    Token t;
4421    while ((t= tk.get()).isop('*') || t.isop('/'))
4422    {
4423        Expr *subexpr2= parseExpr_4(block, tk);
4424        if (t.isop('*'))
4425            subexpr= new OpMulExpr(block, t, subexpr, subexpr2);
4426        else if (t.isop('/'))
4427            subexpr= new OpDivExpr(block, t, subexpr, subexpr2);
4428    }
4429    tk.unget(t);
4430    return subexpr;
4431}
4432
4433Expr * parseExpr_6(BlockBase &block, Tokenizer &tk)
4434{
4435    Expr *subexpr= parseExpr_5(block, tk);
4436    Token t;
4437    while ((t= tk.get()).isop('+') || t.isop('-'))
4438    {
4439        Expr *subexpr2= parseExpr_5(block, tk);
4440        if (t.isop('+'))
4441            subexpr= new OpAddExpr(block, t, subexpr, subexpr2);
4442        else
4443            subexpr= new OpSubExpr(block, t, subexpr, subexpr2);
4444    }
4445    tk.unget(t);
4446    return subexpr;
4447}
4448
4449Expr * parseExpr_8(BlockBase &block, Tokenizer &tk)
4450{
4451    Expr *subexpr= parseExpr_6(block, tk);
4452    Token t= tk.get();
4453    if (t.isop('<'))
4454    {
4455        Expr *subexpr2= parseExpr_6(block, tk);
4456        subexpr= new OpLessExpr(block, t, subexpr, subexpr2);
4457    }
4458    else if (t.isop('>'))
4459    {
4460        Expr *subexpr2= parseExpr_6(block, tk);
4461        subexpr= new OpGreaterExpr(block, t, subexpr, subexpr2);
4462    }
4463    else if (t.isop("<="))
4464    {
4465        Expr *subexpr2= parseExpr_6(block, tk);
4466        subexpr= new OpLessEqualExpr(block, t, subexpr, subexpr2);
4467    }
4468    else if (t.isop(">="))
4469    {
4470        Expr *subexpr2= parseExpr_6(block, tk);
4471        subexpr= new OpGreaterEqualExpr(block, t, subexpr, subexpr2);
4472    }
4473    else if (t.iskeyword("instanceof"))
4474    {
4475        subexpr= new OpInstanceOf(block, t, subexpr, tk);
4476    }
4477    else
4478    {
4479        tk.unget(t);
4480    }
4481    return subexpr;
4482}
4483
4484Expr * parseExpr_9(BlockBase &block, Tokenizer &tk)
4485{
4486    Expr *subexpr= parseExpr_8(block, tk);
4487    Token t= tk.get();
4488    if (t.isop("=="))
4489    {
4490        Expr *subexpr2= parseExpr_8(block, tk);
4491        subexpr= new OpEqualExpr(block, t, subexpr, subexpr2);
4492    }
4493    else if (t.isop("!="))
4494    {
4495        Expr *subexpr2= parseExpr_8(block, tk);
4496        subexpr= new OpNotEqualExpr(block, t, subexpr, subexpr2);
4497    }
4498    else if (t.isop("==="))
4499    {
4500        Expr *subexpr2= parseExpr_8(block, tk);
4501        subexpr= new OpSameExpr(true, block, t, subexpr, subexpr2);
4502    }
4503    else if (t.isop("!=="))
4504    {
4505        Expr *subexpr2= parseExpr_8(block, tk);
4506        subexpr= new OpSameExpr(false, block, t, subexpr, subexpr2);
4507    }
4508    else
4509    {
4510        tk.unget(t);
4511    }
4512    return subexpr;
4513}
4514
4515Expr * parseExpr_10(BlockBase &block, Tokenizer &tk)
4516{
4517    Expr *subexpr= parseExpr_9(block, tk);
4518    Token t;
4519    while ((t= tk.get()).isop('&'))
4520    {
4521        Expr *subexpr2= parseExpr_9(block, tk);
4522        subexpr= new OpBinAndExpr(block, t, subexpr, subexpr2);
4523    }
4524    tk.unget(t);
4525    return subexpr;
4526}
4527
4528Expr * parseExpr_12(BlockBase &block, Tokenizer &tk)
4529{
4530    Expr *subexpr= parseExpr_10(block, tk);
4531    Token t;
4532    while ((t= tk.get()).isop('|'))
4533    {
4534        Expr *subexpr2= parseExpr_10(block, tk);
4535        subexpr= new OpBinOrExpr(block, t, subexpr, subexpr2);
4536    }
4537    tk.unget(t);
4538    return subexpr;
4539}
4540
4541Expr * parseExpr_13(BlockBase &block, Tokenizer &tk)
4542{
4543    Expr *subexpr= parseExpr_12(block, tk);
4544    Token t;
4545    while ((t= tk.get()).isop("&&"))
4546    {
4547        Expr *subexpr2= parseExpr_12(block, tk);
4548        subexpr= new OpBoolAndExpr(block, t, subexpr, subexpr2);
4549    }
4550    tk.unget(t);
4551    return subexpr;
4552}
4553
4554Expr * parseExpr_14(BlockBase &block, Tokenizer &tk)
4555{
4556    Expr *subexpr= parseExpr_13(block, tk);
4557    Token t;
4558    while ((t= tk.get()).isop("||"))
4559    {
4560        Expr *subexpr2= parseExpr_13(block, tk);
4561        subexpr= new OpBoolOrExpr(block, t, subexpr, subexpr2);
4562    }
4563    tk.unget(t);
4564    return subexpr;
4565}
4566
4567Expr * parseExpr_15(BlockBase &block, Tokenizer &tk)
4568{
4569    Expr *subexpr= parseExpr_14(block, tk);
4570    Token t = tk.get();
4571    if (t.isop('?')) {
4572        Expr *extrue = parseExpr_16(block, tk);
4573        ExpectOp(':', tk);
4574        Expr *exfalse = parseExpr_16(block, tk);
4575        return new OpConditionalExpr(block, t, subexpr, extrue, exfalse);
4576    }
4577    else
4578    {
4579        tk.unget(t);
4580        return subexpr;
4581    }
4582}
4583
4584Expr * parseExpr_16(BlockBase &block, Tokenizer &tk)
4585{
4586    Expr *subexpr= parseExpr_15(block, tk);
4587    Token t;
4588    while ((t= tk.get()).isop('='))
4589    {
4590        Expr *subexpr2= parseExpr_16(block, tk);
4591        subexpr= new OpAssignExpr(block, t, subexpr, subexpr2);
4592    }
4593    tk.unget(t);
4594    return subexpr;
4595}
4596
4597Expr * parseExpr(BlockBase &block, Tokenizer &tk)
4598{
4599    return parseExpr_16(block, tk);
4600}
4601
4602//**********************************************************************
4603
4604ExprStatement::ExprStatement(Block &parentblock, Tokenizer &tk)
4605{
4606    expr= parseExpr(parentblock, tk);
4607    ExpectOp(';', tk);
4608}
4609
4610BaseStatement *ExprStatement::optimize ()
4611{
4612    optimize_branch(expr);
4613    return this;
4614}
4615
4616void ExprStatement::emit (Emit &e)
4617{
4618    expr->annotate(e);
4619    expr->emit(e, std::string());
4620    e << '\n';
4621}
4622
4623//**********************************************************************
4624
4625ValueStatement::ValueStatement(Block & block, const Token & tstart) :
4626    SubStatement (block),
4627    Annotated(tstart),
4628    vtype(ValueSimple),
4629    esize(0)
4630{
4631}
4632
4633void ValueStatement::parseArray(Tokenizer &tk)
4634{
4635    Token t= tk.get();
4636    if (t.isop(']') )
4637    {
4638        vtype= ValueArray;
4639        t= tk.get();
4640        if (t.isop('='))
4641        {
4642            ExpectOp('[', tk);
4643            do
4644            {
4645                value.push_back(parseExpr(*this, tk));
4646                t= tk.get();
4647            } while (t.isop(','));
4648            RequireOp(']', t);
4649        }
4650        else
4651            tk.unget(t);
4652    }
4653    else
4654    {
4655        vtype= ValueFixedArray;
4656        tk.unget(t);
4657        esize= parseExpr(*this, tk);
4658        ExpectOp(']', tk);
4659        t= tk.get();
4660        if (t.isop('='))
4661        {
4662            ExpectOp('[', tk);
4663            do
4664            {
4665                value.push_back(parseExpr(*this, tk));
4666                t= tk.get();
4667            } while (t.isop(','));
4668            RequireOp(']', t);
4669        }
4670        else
4671            tk.unget(t);
4672    }
4673}
4674
4675BaseStatement *ValueStatement::optimize()
4676{
4677    optimize_branch(esize);
4678    for (size_t i= 0; i < value.size(); ++i)
4679        optimize_branch(value[i]);
4680    return this;
4681}
4682
4683void ValueStatement::emit (Emit &e, const std::string &name, char type)
4684{
4685    std::string arraytype(type == REGint ? "Integer" : "String");
4686
4687    annotate(e);
4688    e << INDENT ".local " <<
4689        (vtype == ValueSimple ?
4690                (type == REGint ? "int" : "string") :
4691                "pmc") <<
4692        ' ' << name << '\n';
4693
4694    switch (vtype)
4695    {
4696    case ValueSimple:
4697        if (value.size() == 1)
4698        {
4699            char vtype= value[0]->checkresult();
4700            if (((vtype == REGint || vtype == REGstring) && vtype == type) ||
4701                    (dynamic_cast<IndexExpr *>(value[0])))
4702                value[0]->emit(e, name);
4703            else
4704            {
4705                std::string reg= gentemp(vtype);
4706                value[0]->emit(e, reg);
4707                e << op_set(name, reg) << '\n';
4708            }
4709        }
4710        break;
4711    case ValueArray:
4712        e << INDENT "root_new " << name << ", ['parrot';"
4713                "'Resizable" << arraytype << "Array' ]\n";
4714        if (value.size() > 0)
4715        {
4716            std::string reg= gentemp(type);
4717            for (size_t i= 0; i < value.size(); ++i)
4718            {
4719                value[i]->emit(e, reg);
4720                e << INDENT << name << '[' << i << "] = " << reg << '\n';
4721                if (type == REGvar)
4722                    e << op_null(reg) << '\n';
4723            }
4724        }
4725        break;
4726    case ValueFixedArray:
4727        {
4728        size_t vsize;
4729        std::string regsize;
4730        if (esize->isliteralinteger() )
4731            vsize= esize->getintegervalue();
4732        else
4733        {
4734            regsize= gentemp(REGint);
4735            esize->emit(e, regsize);
4736        }
4737        e << INDENT "root_new " << name << ", ['parrot';"
4738                 "'Fixed" << arraytype << "Array' ]\n" <<
4739            INDENT << name << " = ";
4740        if (regsize.empty())
4741            e << vsize;
4742        else
4743            e << regsize;
4744        e << '\n';
4745        if (value.size() > 0)
4746        {
4747            std::string reg= gentemp(type);
4748            for (size_t i= 0; i < value.size(); ++i)
4749            {
4750                value[i]->emit(e, reg);
4751                e << name << '[' << i << "] = " << reg << '\n';
4752                if (type == REGvar)
4753                    e << op_null(reg) << '\n';
4754            }
4755        }
4756        }
4757        break;
4758    default:
4759        throw InternalError("Unexpected initializer type");
4760    }
4761}
4762
4763//**********************************************************************
4764
4765IntStatement::IntStatement(Block &block,  const Token &st, Tokenizer &tk) :
4766    ValueStatement (block, st)
4767{
4768    Token t= tk.get();
4769    name= t.identifier();
4770    t= tk.get();
4771    if (t.isop('['))
4772    {
4773        genlocal(name, REGvar);
4774        parseArray(tk);
4775        t= tk.get();
4776    }
4777    else
4778    {
4779        genlocal(name, REGint);
4780        if (t.isop('='))
4781        {
4782            value.push_back(parseExpr(block, tk));
4783            t= tk.get();
4784        }
4785    }
4786    tk.unget(t);
4787}
4788
4789void IntStatement::emit (Emit &e)
4790{
4791    annotate(e);
4792    emit(e, name, REGint);
4793}
4794
4795//**********************************************************************
4796
4797StringStatement::StringStatement(Block & block, const Token &st, Tokenizer &tk) :
4798    ValueStatement (block, st)
4799{
4800    Token t= tk.get();
4801    name= t.identifier();
4802    t= tk.get();
4803    if (t.isop('['))
4804    {
4805        genlocal(name, REGvar);
4806        parseArray(tk);
4807        t= tk.get();
4808    }
4809    else
4810    {
4811        genlocal(name, REGstring);
4812        if (t.isop('='))
4813        {
4814            value.push_back(parseExpr(block, tk));
4815            t= tk.get();
4816        }
4817    }
4818    tk.unget(t);
4819}
4820
4821void StringStatement::emit (Emit &e)
4822{
4823    annotate(e);
4824    emit(e, name, REGstring);
4825}
4826
4827//**********************************************************************
4828
4829VarStatement::VarStatement(Block & block, const Token &st, Tokenizer &tk) :
4830    ValueStatement (block, st)
4831{
4832    Token t= tk.get();
4833    name= t.identifier();
4834    genlocal(name, REGvar);
4835    t= tk.get();
4836    if (t.isop('='))
4837    {
4838        value.push_back(parseExpr(block, tk));
4839        t= tk.get();
4840    }
4841    RequireOp (';', t);
4842}
4843
4844void VarStatement::emit (Emit &e)
4845{
4846    annotate(e);
4847    e << INDENT ".local pmc " << name << '\n';
4848    if (value.size() == 1)
4849    {
4850        Expr & v = *value[0];
4851        if (v.isnull())
4852            e << op_null(name) << '\n';
4853        else
4854        {
4855            const char type = v.checkresult();
4856            std::string reg;
4857            switch (type) {
4858            case REGint:
4859            case REGstring:
4860                reg = gentemp(type);
4861                v.emit(e, reg);
4862                e << op_box(name, reg) << '\n';
4863                break;
4864            case REGvar:
4865                v.emit(e, name);
4866                break;
4867            default:
4868                throw InternalError("Unexpected value type in var statement");
4869            }
4870        }
4871    }
4872}
4873
4874//**********************************************************************
4875
4876ConstStatement::ConstStatement(Block & block, const Token &st, Tokenizer &tk,
4877        char typed) :
4878    ValueStatement (block, st),
4879    type(typed),
4880    value(0)
4881{
4882    Token t= tk.get();
4883    name= t.identifier();
4884    ExpectOp('=', tk);
4885    value= parseExpr(block, tk);
4886}
4887
4888BaseStatement *ConstStatement::optimize()
4889{
4890    optimize_branch(value);
4891    genconstant(name, type, value->gettoken());
4892    return this;
4893}
4894
4895void ConstStatement::emit (Emit &e)
4896{
4897    if (! value->issimple() )
4898        throw Expected("constant expression", getstart());
4899
4900    // Put a hint in the generated code.
4901    e.comment("Constant " + name + " evaluated at compile time");
4902}
4903
4904BaseStatement * parseConst(Block & block, const Token &st, Tokenizer &tk)
4905{
4906    Token t= tk.get();
4907    const char type = nativetype(t);
4908
4909    switch (type) {
4910    case REGint:
4911    case REGstring:
4912        break;
4913    default:
4914        throw SyntaxError("Invalid const type", t);
4915    }
4916
4917    BaseStatement *multi = 0;
4918    do {
4919        BaseStatement *statement = new ConstStatement(block, st, tk, type);
4920        multi = addtomulti(multi, statement);
4921        t= tk.get();
4922    } while (t.isop(','));
4923    RequireOp (';', t);
4924    return multi;
4925}
4926
4927//**********************************************************************
4928
4929ReturnStatement::ReturnStatement(Block & block,
4930        const Token & tstart, Tokenizer &tk) :
4931    SubStatement (block), Annotated(tstart), values(0)
4932{
4933    Token t= tk.get();
4934    if (! t.isop(';') )
4935    {
4936        tk.unget(t);
4937        values= new ArgumentList(block, tk, ';');
4938    }
4939}
4940
4941BaseStatement *ReturnStatement::optimize()
4942{
4943    if (values)
4944        values->optimize();
4945    return this;
4946}
4947
4948void ReturnStatement::emit (Emit &e)
4949{
4950    if (values)
4951        values->prepare(e);
4952    annotate(e);
4953    e << INDENT ".return (";
4954    if (values)
4955        values->emit(e);
4956    e << " )\n";
4957}
4958
4959//**********************************************************************
4960
4961CompoundStatement::CompoundStatement(Block &parentblock,
4962        Tokenizer &tk) :
4963    BlockStatement (parentblock)
4964{
4965    Token t;
4966    for (t= tk.get(); ! t.isop('}'); t= tk.get() )
4967    {
4968        tk.unget(t);
4969        BaseStatement *st= parseStatement(*this, tk);
4970        subst.push_back(st);
4971    }
4972    tend= t;
4973}
4974
4975BaseStatement *CompoundStatement::optimize ()
4976{
4977    bool empty= true;
4978    for (size_t i= 0; i < subst.size(); ++i) {
4979        optimize_branch(subst[i]);
4980        if (!subst[i]->isempty() )
4981            empty= false;
4982    }
4983    if (empty)
4984        return new EmptyStatement();
4985    else
4986        return this;
4987}
4988
4989void CompoundStatement::emit (Emit &e)
4990{
4991    for (size_t i= 0; i < subst.size(); ++i)
4992    {
4993        subst[i]->emit(e);
4994        freetempregs();
4995    }
4996}
4997
4998//**********************************************************************
4999
5000ForeachStatement::ForeachStatement(Block &block, Tokenizer &tk) :
5001    ContinuableStatement (block),
5002    vartype('\0'),
5003    container(0)
5004{
5005    Token t= tk.get();
5006    vartype = nativetype(t);
5007    if (vartype != '\0')
5008        t= tk.get();
5009    start = t;
5010    varname= t.identifier();
5011    if (vartype != '\0')
5012        genlocal(varname, vartype);
5013    t= tk.get();
5014    if (!t.iskeyword("in"))
5015        throw Expected ("'in'", t);
5016    container= parseExpr(*this, tk);
5017    ExpectOp(')', tk);
5018    st= parseStatement(*this, tk);
5019}
5020
5021BaseStatement *ForeachStatement::optimize()
5022{
5023    optimize_branch(container);
5024    optimize_branch(st);
5025    return this;
5026}
5027
5028void ForeachStatement::emit(Emit &e)
5029{
5030    std::string label= genlabel();
5031    std::string continuelabel = gencontinuelabel();
5032    std::string breaklabel= genbreaklabel();
5033    std::string regcont = genlocalregister(REGvar);
5034    if (container-> isstring() )
5035    {
5036        std::string value= gentemp(REGstring);
5037        container->emit(e, value);
5038        e.annotate(start);
5039        e << op_box(regcont, value) << '\n';
5040    }
5041    else
5042        container->emit(e, regcont);
5043
5044    e.annotate(start);
5045    if (vartype != '\0')
5046        e << INDENT ".local " << nameoftype(vartype) << ' ' << varname << '\n';
5047    const std::string iter= "iter_" + varname;
5048
5049    e << INDENT ".local pmc " << iter << "\n" <<
5050        INDENT "if null " << regcont << " goto " << breaklabel << '\n' <<
5051        INDENT "iter " << iter << ", " << regcont << "\n" <<
5052        INDENT << iter << " = 0\n" << // ITERATE_FROM_START
5053        INDENTLABEL << continuelabel << ": # FOR IN\n" <<
5054        INDENT "unless " << iter << " goto " << breaklabel<< "\n"
5055        INDENT "shift " << varname << ", " << iter << '\n'
5056        ;
5057    st->emit(e);
5058    e << INDENT "goto " << continuelabel << '\n' <<
5059        INDENTLABEL << breaklabel << ": # FOR IN END\n";
5060    freelocalregister(regcont);
5061}
5062
5063//**********************************************************************
5064
5065ForStatement::ForStatement(Block &block, Tokenizer &tk) :
5066    ContinuableStatement (block),
5067    initializer(0),
5068    condition(0),
5069    iteration(0),
5070    st(0)
5071{
5072    Token t= tk.get();
5073    if (! t.isop(';'))
5074    {
5075        tk.unget(t);
5076        initializer= parseStatement(*this, tk);
5077    }
5078    t= tk.get();
5079    if (! t.isop(';'))
5080    {
5081        tk.unget(t);
5082        condition= parseExpr(*this, tk);
5083        ExpectOp(';', tk);
5084    }
5085    t= tk.get();
5086    if (! t.isop(')'))
5087    {
5088        tk.unget(t);
5089        iteration= parseExpr(*this, tk);
5090        ExpectOp(')', tk);
5091    }
5092    st= parseStatement(*this, tk);
5093}
5094
5095BaseStatement *ForStatement::optimize()
5096{
5097    optimize_branch(initializer);
5098    optimize_branch(condition);
5099    optimize_branch(iteration);
5100    optimize_branch(st);
5101    return this;
5102}
5103
5104void ForStatement::emit(Emit &e)
5105{
5106    e.comment("for loop");
5107
5108    std::string continuelabel= gencontinuelabel();
5109    std::string l_condition= genlabel();
5110    std::string breaklabel = genbreaklabel();
5111
5112    if (initializer)
5113        initializer->emit(e);
5114
5115    e << INDENTLABEL << l_condition << ": # for condition\n";
5116    if (condition)
5117    {
5118        std::string reg= condition->emit_get(e);
5119        e << INDENT "unless " << reg << " goto " << breaklabel << " # for end\n";
5120    }
5121
5122    e << "# for body\n";
5123    st->emit(e);
5124
5125    e << INDENTLABEL << continuelabel << ": # for iteration\n";
5126
5127    if (iteration)
5128    {
5129        iteration->emit(e, std::string());
5130        e << '\n';
5131    }
5132    e << INDENT "goto " << l_condition << " # for condition\n";
5133
5134    e << INDENTLABEL << breaklabel << ": # for end\n";
5135    e.comment("for loop end");
5136}
5137
5138//**********************************************************************
5139
5140ThrowStatement::ThrowStatement(Block &block, const Token &st,
5141        Tokenizer &tk) :
5142    SubStatement (block),
5143    pos(st), excep(0)
5144{
5145    excep = parseExpr(block, tk);
5146}
5147
5148BaseStatement *ThrowStatement::optimize()
5149{
5150    optimize_branch(excep);
5151    return this;
5152}
5153
5154void ThrowStatement::emit (Emit &e)
5155{
5156    e.annotate(pos);
5157
5158    char type = excep->checkresult();
5159    std::string reg = gentemp(type);
5160    excep->emit(e, reg);
5161    switch (type)
5162    {
5163    case REGvar:
5164        e << INDENT "throw" << ' ' << reg << '\n';
5165        break;
5166    case REGstring:
5167        {
5168            std::string aux = gentemp(REGvar);
5169            e <<
5170                INDENT "root_new " << aux << ", ['parrot';'Exception']\n"
5171                INDENT << aux << "['message'] = " << reg << "\n"
5172                INDENT "throw " << aux << "\n"
5173                ;
5174        }
5175        break;
5176    default:
5177        throw SyntaxError("Invalid throw argument", pos);
5178    }
5179}
5180
5181//**********************************************************************
5182
5183TryStatement::TryStatement(Block &block, const Token &st, Tokenizer &tk) :
5184    BlockStatement (block),
5185    Annotated(st),
5186    stry(0), scatch(0)
5187{
5188    stry = parseStatement (block, tk);
5189    Token t= tk.get();
5190    if (! t.iskeyword("catch"))
5191        throw Expected("catch", t);
5192    ExpectOp ('(', tk);
5193    t= tk.get();
5194    if (! t.isop(')'))
5195    {
5196        exname= t.identifier();
5197        ExpectOp (')', tk);
5198    }
5199    scatch= parseStatement (block, tk);
5200}
5201
5202BaseStatement *TryStatement::optimize()
5203{
5204    optimize_branch(stry);
5205    optimize_branch(scatch);
5206    return this;
5207}
5208
5209void TryStatement::emit (Emit &e)
5210{
5211    annotate(e);
5212    std::string label= genlabel();
5213    std::string handler = label + "_HANDLER";
5214    std::string pasthandler = label + "_PAST_HANDLER";
5215    std::string except = exname.empty() ?
5216        gentemp(REGvar) :
5217        exname;
5218
5219    std::string reghandler= gentemp(REGvar);
5220    e << INDENT <