cvsuser     02/09/22 10:38:47

  Modified:    languages/imcc imcc.l imcc.y
  Log:
  Large patch from Leo, see ChangeLog.
  
  Revision  Changes    Path
  1.12      +61 -53    parrot/languages/imcc/imcc.l
  
  Index: imcc.l
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imcc.l,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- imcc.l    8 Sep 2002 03:51:23 -0000       1.11
  +++ imcc.l    22 Sep 2002 17:38:47 -0000      1.12
  @@ -16,8 +16,10 @@
   #include "imc.h"
   #include "imcparser.h"
   
  +#define YY_NO_UNPUT
   extern long line;
  -extern int expect_eol;
  +extern int expect_pasm;
  +int state;
   int yyerror(char *);
   %}
   
  @@ -31,50 +33,47 @@
   STRINGCONSTANT  \"(\\.|[^"\n]*)*["\n]
   CHARCONSTANT    \'[^'\n]*\'
   RANKSPEC        \[[,]*\]
  +EOL          \r?\n
   
  -%x emit2
  -%s expecteol
  +%x emit
   %%
           /* for emacs: ' */
  -        if (expect_eol)
  -            BEGIN(expecteol);
  -
  -^".emit\n"(.|\n)*".eom\n" {
  -        char * s = strstr(yytext, ".eom");
  -        if(s) {
  -            s[0] = '\n';
  -            s[1] = 0;
  -        }
  -        yylval.s = str_dup(&yytext[5]);
  -        return EMIT;
  -    }
  -
  -^".emit2"\n {
  -        BEGIN(emit2);
  +        if (expect_pasm == 1) {
  +         expect_pasm = 2;
  +            BEGIN(emit);
       }
   
  -<emit2>^".eom"\n {
  +<INITIAL,emit>{EOL} {
  +        if (expect_pasm == 2)
           BEGIN(INITIAL);
  +        expect_pasm = 0;
  +        line++;
  +        return '\n';
       }
   
  -<emit2>.|\n      ;
  -
  -<expecteol>[\n] {
  +<INITIAL,emit>#.*{EOL} {
  +        if (expect_pasm == 2)
           BEGIN(INITIAL);
  -        expect_eol = 0;
  +        expect_pasm = 0;
           line++;
           return '\n';
       }
   
  -<expecteol>#.*[\n] {
  +
  +^".emit"\n {
  +     BEGIN(emit);
  +     return(EMIT);
  +    }
  +
  +<emit>^".eom"\n {
           BEGIN(INITIAL);
  -        expect_eol = 0;
  -        line++;
  -        return '\n';
  +     return EOM;
       }
   
  -[\n]            line++;
  -#.*\n           line++;
  +<emit,INITIAL>[ISNP]{DIGIT}{DIGIT}? {
  +     yylval.s = str_dup(yytext);
  +     return REG;
  +     }
   
   ".sym"          return(SYM);
   ".arg"          return(ARG);
  @@ -118,59 +117,75 @@
   "=="            return(RELOP_EQ);
   "!="            return(RELOP_NE);
   "**"            return(POW);
  -","             return(COMMA);
   
  -{LETTER}{LETTERDIGIT}*":" {
  +<emit,INITIAL>","             return(COMMA);
  +
  +<emit,INITIAL>{LETTER}{LETTERDIGIT}*":" {
        yytext[yyleng-1] = 0;  /* trim last ':' */
           yylval.s = str_dup(yytext);
           return(LABEL);
       }
   
  -{DOT}?{LETTER}{LETTERDIGIT}* {
  +<emit>{DOT}{LETTER}{LETTERDIGIT}* {  /* XXX */
           yylval.s = str_dup(yytext);
  -        return(IDENTIFIER);
  +        return(MACRO);
  +    }
  +<INITIAL>{DOT}?{LETTER}{LETTERDIGIT}* {
  +     SymReg *r = get_sym(yytext);
  +     if (r && r->type & VTIDENTIFIER) {
  +         yylval.sr = r;
  +         return VAR;
  +     }
  +        yylval.s = str_dup(yytext);
  +        return(is_op(yylval.s) ? PARROT_OP : IDENTIFIER);
  +    }
  +<emit,INITIAL>{LETTER}{LETTERDIGIT}* {
  +     SymReg *r = get_sym(yytext);
  +     if (r && r->type & VTIDENTIFIER) {
  +         yylval.sr = r;
  +         return VAR;
  +     }
  +        yylval.s = str_dup(yytext);
  +        return(is_op(yylval.s) ? PARROT_OP : IDENTIFIER);
       }
   
  -{SIGN}?{DIGIT}+"."{DIGIT}+ {
  +<emit,INITIAL>{SIGN}?{DIGIT}+"."{DIGIT}+ {
           yylval.s = str_dup(yytext);
           return(FLOATC);
       }
   
  -{SIGN}?{DIGIT}+ {
  +<emit,INITIAL>{SIGN}?{DIGIT}+ {
           yylval.s = str_dup(yytext);
           return(INTC);
       }
   
  -{STRINGCONSTANT} {
  -        yylval.s = str_dup(yytext);
  +<emit,INITIAL>{STRINGCONSTANT} {
  +        yylval.s = str_dup(yytext); /* XXX delete quotes, -> emit, pbc */
           return(STRINGC);
       }
   
  -\$I[0-9]+ {
  +<emit,INITIAL>\$I[0-9]+ {
           yylval.s = str_dup(yytext);
           return(IREG);
       }
   
  -\$N[0-9]+ {
  +<emit,INITIAL>\$N[0-9]+ {
           yylval.s = str_dup(yytext);
           return(NREG);
       }
   
  -\$S[0-9]+ {
  +<emit,INITIAL>\$S[0-9]+ {
           yylval.s = str_dup(yytext);
           return(SREG);
       }
   
  -\$P[0-9]+ {
  +<emit,INITIAL>\$P[0-9]+ {
           yylval.s = str_dup(yytext);
           return(PREG);
       }
   
  -[\t\f\r ]+        ;
  -.     {
  -#if 0
  -        fprintf(stderr, "token[%s]\n", yytext);
  -#endif
  +<emit,INITIAL>[\t\f\r ]+        ;
  +<emit,INITIAL>.     {
           return yytext[0];
       }
   
  @@ -187,11 +202,4 @@
       yy_delete_buffer(YY_CURRENT_BUFFER);
       return 1;
   }
  -
  -#if 0
  -char * str_dup(const char * buf) {
  -    char * s = malloc(strlen(buf)+1);
  -    return s;
  -}
  -#endif
   
  
  
  
  1.22      +685 -513  parrot/languages/imcc/imcc.y
  
  Index: imcc.y
  ===================================================================
  RCS file: /cvs/public/parrot/languages/imcc/imcc.y,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -w -r1.21 -r1.22
  --- imcc.y    6 Sep 2002 07:13:52 -0000       1.21
  +++ imcc.y    22 Sep 2002 17:38:47 -0000      1.22
  @@ -13,16 +13,20 @@
   #include <stdio.h>
   #include <stdlib.h>
   #include <assert.h>
  +
  +#define _PARSER
  +#define MAIN
   #include "imc.h"
  -#include "anyop.h"
  +#include "parrot/embed.h"
  +#include "pbc.h"
   
   #define YYDEBUG 1
  +/* #define OPTEST */
   
   int         yyerror(char *);
   int         yylex();
   extern char yytext[];
  -long        line;
  -int         expect_eol;
  +int         expect_pasm;
   
   /*
    * Choosing instructions for Parrot is pretty easy since
  @@ -30,7 +34,11 @@
    */
   
   
  -static SymReg *regs[PARROT_MAX_ARGS];
  +static SymReg *regs[IMCC_MAX_REGS];
  +static int nargs = 0;
  +static SymReg *keys[IMCC_MAX_REGS];
  +static int nkeys = 0;
  +
   static SymReg ** RR(int n, ...)
   {
       va_list ap;
  @@ -40,502 +48,412 @@
       while (n--) {
        regs[i++] = va_arg(ap, SymReg *);
       }
  -    while (i < PARROT_MAX_ARGS)
  +    while (i < IMCC_MAX_REGS)
        regs[i++] = 0;
       return regs;
   }
   
  -/* intermediate macros for registers */
  -#define R2(r0,r1) RR(2,r0,r1)
  -#define R regs[0],regs[1],regs[2],regs[3]
  -
  -SymReg * iMOVE(SymReg *r0, SymReg*r1) {
  -    int flags = IF_unary;
  -    R2(r0, r1);
  -    if (r0->set == 'P' && r1->set != 'P') {
  -     /* r0 needs read access because set Px, Ax calls Px's set
  -      * method, instead of just clobbering it. */
  -     flags = IF_r0_write|IF_r0_read|IF_r1_read;
  -    }
  -    emitb(mk_instruction("set %s, %s", R, flags));
  -    return r0;
  -}
  -
  -SymReg * iNOT(SymReg *r0, SymReg*r1) {
  -    emitb(mk_instruction("not %s, %s", r0, r1, NULL, NULL, IF_unary));
  -    return r0;
  -}
  -
  -SymReg * iNEG(SymReg *r0, SymReg*r1) {
  -    if (r0->set != 'S' || r0->set == r1->set) {
  -     emitb(mk_instruction("neg %s, %s", r0, r1, NULL, NULL, IF_unary));
  -    }
  -    else {
  -        fprintf(stderr, "line %ld: Syntax error, neg arguments must be int, float, 
or PMC\n",
  -                line);
  -        exit(EX_DATAERR);
  -    }
  -    return r0;
  -}
  -
  -SymReg * iINC(SymReg *r0) {
  -    emitb(mk_instruction("inc %s", r0, NULL, NULL, NULL, IF_inplace));
  -    return r0;
  -}
  -
  -SymReg * iDEC(SymReg *r0) {
  -    emitb(mk_instruction("dec %s", r0, NULL, NULL, NULL, IF_inplace));
  -    return r0;
  -}
  -
  -SymReg * iADD(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("add %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iSUB(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("sub %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iMUL(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("mul %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iPOW(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("pow %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -SymReg * iDIV(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("div %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iMOD(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("mod %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iSHL(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("shl %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iSHR(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("shr %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  -
  -SymReg * iXOR(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    if ((r0->set == 'I' && r1->set == 'I' && r2->set == 'I')
  -     || (r0->set == 'P' && r1->set == 'P' && r2->set == 'P')) {
  -     emitb(mk_instruction("xor %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    }
  -    else {
  -        fprintf(stderr, "line %ld: Syntax error, xor arguments must be int or 
PMC\n",
  -                line);
  -        exit(EX_DATAERR);
  -    }
  -    return r0;
  -}
  -
  -SymReg * iBAND(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("band %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  +/* macros for registers */
  +#define R0()                 RR(nargs=0)
  +#define R1(r0)               RR(nargs=1,r0)
  +#define R2(r0,r1)    RR(nargs=2,r0,r1)
  +#define R3(r0,r1,r2)         RR(nargs=3,r0,r1,r2)
  +#define R4(r0,r1,r2,r3) RR(nargs=4,r0,r1,r2,r3)
   
  -SymReg * iBOR(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("bor %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  -}
  +Instruction * iANY(char * name, char *fmt, SymReg **r, int emit);
   
  -SymReg * iBXOR(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    emitb(mk_instruction("bxor %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    return r0;
  +/*
  + * MK_I: build and emitb instruction by iANY
  + *
  + * fmt may contain:
  + *   op %s, %s # comment
  + * or just
  + *   op
  + *
  + */
  +static Instruction * MK_I(char * fmt, SymReg ** r) {
  +    char opname[64];
  +    char *p, *q;
  +    for (p = opname, q = fmt; *q && *q != ' '; )
  +     *p++ = *q++;
  +    *p = 0;
  +    if (!*q)
  +     fmt = 0;
  +    else
  +     fmt = ++q;
  +#if OPDEBUG
  +    fprintf(stderr, "op '%s' format '%s' (%d)\n", opname, fmt?:"",nargs);
  +#endif
  +    return iANY(opname, fmt, r, 1);
   }
   
  -SymReg * iCONCAT(SymReg *r0, SymReg*r1, SymReg *r2) {
  -    if((r0->set == 'S' && r1->set == 'S' && r2->set == 'S')
  -       || (r0->set == 'P' && r1->set == 'P' && r2->set == 'P')) {
  -        emitb(mk_instruction("concat %s, %s, %s", r0, r1, r2, NULL, IF_binary));
  -    }
  -    else {
  -        fprintf(stderr, "line %ld: Syntax error, concat arguments must be all 
strings or all PMC's\n",
  -                line);
  -        exit(EX_DATAERR);
  -    }
  -    return r0;
  -}
  +/*
  + * special instructions
  + *
  + * labels and such
  + */
   
  -SymReg * iCALL(SymReg * r0) {
  -    emitb(mk_instruction("bsr %s", r0, NULL, NULL, NULL, IF_r0_read));
  -    return r0;
  -}
   
  -SymReg * iBRANCH(SymReg * r0) {
  -    Instruction * i = emitb(mk_instruction("branch %s", r0, NULL, NULL, NULL, 
IF_r0_branch | IF_goto));
  -    i->type = ITBRANCH;
  -    return r0;
  -}
   
  -SymReg * iLABEL(SymReg * r0) {
  -    Instruction *i = emitb(mk_instruction("%s:", r0, NULL, NULL, NULL,
  -                                       0)); /* IF_r0_read ? */
  +static Instruction * iLABEL(SymReg * r0) {
  +    Instruction *i = emitb(_mk_instruction("","%s:", R1(r0), 0));
       i->type = ITLABEL;
  -    return r0;
  -}
  -
  -SymReg * iARG(SymReg * r0) {
  -    emitb(mk_instruction("save %s", r0, NULL, NULL, NULL, IF_r0_read));
  -    return r0;
  -}
  -
  -SymReg * iPUSH(SymReg * r0) {
  -    emitb(mk_instruction("save %s", r0, NULL, NULL, NULL, IF_r0_read));
  -    return r0;
  +    return i;
   }
   
  -SymReg * iPOP(SymReg * r0) {
  -    emitb(mk_instruction("restore %s", r0, NULL, NULL, NULL, IF_r0_write));
  -    return r0;
  -}
  -
  -SymReg * iRESULT(SymReg * r0) {
  -    return iPOP(r0);
  -}
  -
  -SymReg * iRETURN(SymReg * r0) {
  -    return iPUSH(r0);
  -}
  -
  -SymReg * iSAVEALL() {
  -    emitb(mk_instruction("saveall", NULL, NULL, NULL, NULL, 0));
  -    return 0;
  -}
   
  -SymReg * iRESTOREALL() {
  -    emitb(mk_instruction("restoreall", NULL, NULL, NULL, NULL, 0));
  -    return 0;
  -}
  -
  -SymReg * iPRINT(SymReg * r0) {
  -    emitb(mk_instruction("print %s", r0, NULL, NULL, NULL, IF_r0_read));
  -    return r0;
  -}
  -
  -SymReg * iSUBROUTINE(SymReg * r0) {
  -    emitb(mk_instruction("%s:", r0, NULL, NULL, NULL, IF_r0_read)); /* IF_r0_read? 
*/
  -    return r0;
  +static Instruction * iSUBROUTINE(SymReg * r0) {
  +    function = r0->name;
  +    return iLABEL(r0); /* XXX mark label global */
   }
   
  -SymReg * iRET() {
  -    emitb(mk_instruction("ret", NULL, NULL, NULL, NULL, 0));
  -    return 0;
  -}
   
  -SymReg * iINDEXFETCH(SymReg * r0, SymReg * r1, SymReg * r2) {
  +/*
  + * substr or X = P[key]
  + */
  +static Instruction * iINDEXFETCH(SymReg * r0, SymReg * r1, SymReg * r2) {
       if(r0->set == 'S' && r1->set == 'S' && r2->set == 'I') {
  -        emitb(mk_instruction("substr %s, %s, %s, 1", r0, r1, r2, NULL, IF_binary));
  -    }
  -    else if (r1->set == 'P') {
  -     emitb(mk_instruction("set %s, %s[%s]", r0, r1, r2, NULL, IF_binary));
  -     r1->score = 1000;
  -    }
  -    else {
  -        fprintf(stderr, "FIXME: Internal error, unsupported indexed fetch 
operation\n");
  -        exit(EX_SOFTWARE);
  +        return MK_I("substr %s, %s, %s, 1", R3(r0, r1, r2));
       }
  -    return r0;
  +    return MK_I("set %s, %s[%s]", R3(r0,r1,r2));
   }
   
  -SymReg * iINDEXSET(SymReg * r0, SymReg * r1, SymReg * r2) {
  -    if(r0->set == 'S' && r1->set == 'I' && r2->set == 'S') {
  -        /* Temporaries assigned by IMCC are of form (T.n)
  -            SymReg * temp = mk_symreg("(S.0)", 'S');
  +/*
  + * substr or P[key] = X
           */
  -        emitb(mk_instruction("substr %s, %s, 1, %s", r0, r1, r2, NULL, IF_binary));
  +
  +static Instruction * iINDEXSET(SymReg * r0, SymReg * r1, SymReg * r2) {
  +    if(r0->set == 'S' && r1->set == 'I' && r2->set == 'S') {
  +        MK_I("substr %s, %s, 1, %s", R3(r0, r1, r2));
       }
       else if (r0->set == 'P') {
  -     /* XXX: SEAN: is "read" right for setting an array?  */
  -     emitb(mk_instruction("set %s[%s], %s", r0, r1, r2, NULL,
  -                          IF_r0_write | IF_r1_read | IF_r2_read));
  -     r0->score = 1000;
  +     MK_I("set %s[%s], %s", R3(r0,r1,r2));
       }
       else {
  -        fprintf(stderr, "FIXME: Internal error, unsupported indexed set 
operation\n");
  -        exit(EX_SOFTWARE);
  +        fataly(EX_SOFTWARE, "iINDEXSET", line,"unsupported indexed set op\n");
       }
  -    return r0;
  -}
  -
  -SymReg * iIF(int relop, SymReg * r0, SymReg * r1, SymReg * r2) {
  -    Instruction * i;
  -    char op[256];
  -    relop_to_op(relop, op);
  -    strcat(op, " %s, %s, %s");
  -    i = emitb(mk_instruction(op, r0, r1, r2, NULL, IF_r0_read | IF_r1_read | 
IF_r2_branch));
  -    i->type = ITBRANCH;
       return 0;
   }
   
  -SymReg * iIF1(char *f, SymReg * r0, SymReg * dest)
  +/* return the index of a PMC class */
  +static int get_pmc_num(char *pmc_type)
   {
  -    Instruction * i;
  -    char op[256];
  -    sprintf(op, "%s %%s, %%s", f);
  -    i = emitb(mk_instruction(op, r0, dest, 0, NULL, IF_r0_read | IF_r1_branch));
  -    i->type = ITBRANCH;
  -    return 0;
  -}
  -
  -SymReg * iNEW(SymReg * r0, char * type) {
  -    char op[256];
  -    strcpy(op, "new %s, .");
  -    strcat(op, type);
  -    emitb(mk_instruction(op, r0, NULL, NULL, NULL, IF_r0_write ));
  -    free(type);
  -    return r0;
  +    STRING * s = string_make(interpreter, pmc_type,
  +            (UINTVAL) strlen(pmc_type), NULL, 0, NULL);
  +    PMC * key = key_new_string(interpreter, s);
  +    return Parrot_base_classname_hash->vtable->get_integer_keyed(
  +            interpreter, Parrot_base_classname_hash, key);
   }
   
  -SymReg * iDEFINED(SymReg * r0, SymReg * r1) {
  -    if (r0->set == 'I' && r1->set == 'P') {
  -     emitb(mk_instruction("defined %s, %s", r0, r1, NULL, NULL,
  -                          IF_r0_write | IF_r1_read ));
  -    }
  -    else {
  -        fprintf(stderr, "line %ld: Syntax error, defined: arguments must be int, 
PMC\n",
  -                line);
  -     exit(EX_DATAERR);
  -    }
  -    return r0;
  +/* only .PmcType */
  +static SymReg * macro(char *name)
  +{
  +    SymReg * r;
  +    char buf[16];
  +    int type = get_pmc_num(name);
  +    sprintf(buf, "%d", type);
  +    r =  mk_const(str_dup(buf), 'I');
  +    return r;
   }
  -
  -/* XXX -lt
  -   the address may be the target of a jump
  -   must we deal with this - think try/CATCH
  +/*
  + * new P, .SomeThing
   */
  -
  -SymReg * iSET_ADDR(SymReg * r0, SymReg * r1) {
  -    if (r0->set == 'I') {
  -     emitb(mk_instruction("set_addr %s, %s", r0, r1, NULL, NULL,
  -                          IF_r0_write));
  -    }
  -    else {
  -     fprintf(stderr, "line %ld: Syntax error, set_addr destination must be int 
register\n", line);
  -     exit(EX_DATAERR);
  -    }
  -    return r0;
  +static Instruction * iNEW(SymReg * r0, char * type) {
  +    char fmt[256];
  +    SymReg *pmc = macro(type);
  +    /* XXX check, if type exists, but aove keyed search
  +     * gives 0 for non existing  PMCs */
  +    sprintf(fmt, "new %%s, %d\t # .%s", atoi(pmc->name), type);
  +    r0->usage = U_NEW;
  +    if (!strcmp(type, "PerlArray") || !strcmp(type, "PerlHash"))
  +        r0->usage |= U_KEYED;
  +    MK_I(fmt, R2(r0, pmc));  /* new_p_ic */
  +    free(type);
  +    return 0;
   }
   
  -SymReg * iSET_GLOBAL(SymReg * r0, SymReg * r1) {
  -    if (r0->set == 'S' && r1->set == 'P') {
  -     emitb(mk_instruction("store_global %s, %s", r0, r1,
  -                          NULL, NULL, IF_r0_read | IF_r1_read));
  -    }
  -    else {
  -     fprintf(stderr, "line %ld: store_global arguments must be PMC, string\n",
  -             line);
  -     exit(EX_DATAERR);
  -    }
  -    return r0;
  -}
  +/* TODO get rid of nargs */
  +void
  +op_fullname(char * dest, const char * name, SymReg * args[], int nargs) {
  +    int i;
   
  -SymReg * iGET_GLOBAL(SymReg * r0, SymReg * r1) {
  -    if (r0->set == 'P' && r1->set == 'S') {
  -     emitb(mk_instruction("find_global %s, %s", r0, r1,
  -                          NULL, NULL, IF_r0_write | IF_r1_read));
  -    }
  -    else {
  -     fprintf(stderr, "line %ld: find_global arguments must be PMC, string\n",
  -             line);
  -     exit(EX_DATAERR);
  +    strcpy(dest, name);
  +    dest += strlen(name);
  +    for (i = 0; i < nargs && args[i]; i++) {
  +        *dest++ = '_';
  +        if (args[i]->type == VTADDRESS) {
  +            *dest++ = 'i';
  +            *dest++ = 'c';
  +            continue;
       }
  -    return r0;
  +        /* if one ever wants num keys, they go with 'S' */
  +        if (args[i]->type & VTKEY) {
  +            *dest++ = 'k';
  +            if (args[i]->set == 'S' || args[i]->set == 'N' ||
  +                args[i]->set == 'K') {
  +                *dest++ = 'c';
  +                continue;
   }
  -
  -SymReg * iCLONE(SymReg * r0, SymReg * r1) {
  -    if (r0->set == r1->set && (r0->set == 'S' || r0->set == 'P')) {
  -     emitb(mk_instruction("clone %s, %s", r0, r1,
  -                          NULL, NULL, IF_r0_write | IF_r1_read));
       }
  -    else {
  -     fprintf(stderr, "line %ld: clone arguments must be PMCs or strings\n",
  -             line);
  -     exit(EX_DATAERR);
  +        *dest++ = tolower(args[i]->set);
  +        if (args[i]->type & VTCONST)
  +            *dest++ = 'c';
       }
  -    return r0;
  +    *dest = '\0';
   }
  -
  -SymReg * iEMIT(char * assembly) {
  -    emitb(mk_instruction(assembly, NULL, NULL, NULL, NULL, 0));
  -    free(assembly);
  -    return 0;
  +#if 0
  +#define OP_HASH_SIZE 1511
  +typedef struct hop {
  +    op_info_t * info;
  +    struct hop *next;
  +} HOP;
  +static HOP **hop;
  +static void hop_init();
  +
  +static void store_op(op_info_t *info, int full) {
  +    HOP *p = malloc(sizeof(HOP));
  +    int index = hash_str(full ? info->full_name : info->name) % OP_HASH_SIZE;
  +    p->info = info;
  +    p->next = hop[index];
  +    hop[index] = p;
  +}
  +int get_op(const char * name, int full) {
  +    HOP * p;
  +    int index = hash_str(name) % OP_HASH_SIZE;
  +    if (!hop) {
  +        hop = calloc(OP_HASH_SIZE, sizeof(HOP*));
  +        hop_init();
  +    }
  +    for(p = hop[index]; p; p = p->next) {
  +     if(!strcmp(name, full ? p->info->full_name : p->info->name))
  +         return p->info - interpreter->op_info_table;
   }
  -
  -SymReg * iEND() {
  -    emitb(mk_instruction("end", NULL, NULL, NULL, NULL, 0));
  -    return 0;
  +    return -1;
   }
  -
  -int nargs = 0;
  -SymReg * args[16] = { NULL };
  -
  -static void
  -op_fullname(char * dest, const char * name, SymReg * args[], int nargs) {
  +static void hop_init() {
       int i;
  -    int key_index = -1;
  -
  -    strcpy(dest, name);
  -    dest += strlen(name);
  -    if (strcmp(name, "set") == 0) {
  -     if (args[0]->set == 'P' && args[1]->set != 'P') {
  -         key_index = 1;
  +    op_info_t * info = interpreter->op_info_table;
  +    /* store full names */
  +    for (i = 0; i < interpreter->op_count; i++)
  +        store_op(info + i, 1);
  +    /* plus one short name */
  +    for (i = 0; i < interpreter->op_count; i++)
  +        if (get_op(info[i].name, 0) == -1)
  +            store_op(info + i, 0);
        }
  -     else if (args[1]->set == 'P' && args[2]->set != 'P') {
  -         key_index = 2;
  -     }
  -     else {
  -         fprintf(stderr, "Can't figure out keyed op!\n");
  -         exit(EX_SOFTWARE);
  +void hop_deinit()
  +{
  +    HOP *p, *next;
  +    int i;
  +    for (i = 0; i < OP_HASH_SIZE; i++)
  +        for(p = hop[i]; p; ) {
  +            next = p->next;
  +            free(p);
  +            p = next;
        }
  +    free(hop);
  +    hop = 0;
       }
  -    for (i = 0; i < nargs; i++) {
  -     char set;
  -     if (args[i]->type == VTADDRESS)
  -         set = 'I';
  -     else
  -         set = args[i]->set;
  +#endif
  +
  +int check_op(char *fullname, char *name, SymReg *regs[])
  +{
  +    int op, nargs;
  +    for (nargs = 0; regs[nargs]; nargs++) ;
  +    op_fullname(fullname, name, regs, nargs);
  +    op = interpreter->op_lib->op_code(fullname, 1);
  +    return op;
   
  -     *dest++ = '_';
  -     if (key_index == i)
  -         *dest++ = 'k';
  -     *dest++ = tolower(set);
  -     if (args[i]->type == VTCONST || args[i]->type == VTADDRESS)
  -         *dest++ = 'c';
       }
  -    *dest = '\0';
  +
  +int is_op(char *name)
  +{
  +    return interpreter->op_lib->op_code(name, 0) >= 0;
   }
   
  -SymReg * iANY(char * name) {
  +Instruction * iANY(char * name, char *fmt, SymReg **regs, int emit) {
       char fullname[64];
       int i;
       int dirs = 0;
  -    op_t op;
  -    op_fullname(fullname, name, args, nargs);
  -    op = op_find_exact(fullname);
  -    if (!same_op(op, NULLOP)) {
  -     op_info_t * info = op_info(op);
  +    int op;
  +    Instruction * ins;
  +
  +    op_fullname(fullname, name, regs, nargs);
  +    op = interpreter->op_lib->op_code(fullname, 1);
  +    if (op >= 0) {
  +        op_info_t * info = &interpreter->op_info_table[op];
        char format[128];
        int len;
  -     if (IMCC_DEBUG) {
  -         fprintf(stderr, "Op %s (%d, %d)\n", name, op.lib, op.op);
  -         print_op_info(stderr, info);
  -     }
   
  -     sprintf(format, "%s  ", name);
  -     for (i = 1; i < info->arg_count; i++) {
  -         switch (info->dirs[i]) {
  +        *format = '\0';
  +        /* info->arg_count is offset by one, first is opcode
  +         * build instruction format
  +         * set LV_in / out flags */
  +        for (i = 0; i < info->arg_count-1; i++) {
  +            switch (info->dirs[i+1]) {
  +                case PARROT_ARGDIR_INOUT:
  +                    /* inout is actually in for imcc, the PMC has to exist
  +                     * previously, so:
  +                     * goon
  +                     */
            case PARROT_ARGDIR_IN:
  -             dirs |= 1 << (i - 1);
  +                    dirs |= 1 << i ;
                break;
   
            case PARROT_ARGDIR_OUT:
  -             dirs |= 1 << (4 + i - 1);
  -             break;
  -
  -         case PARROT_ARGDIR_INOUT:
  -             dirs |= 1 << (i - 1) | 1 << (4 + i - 1);
  +                    dirs |= 1 << (16 + i);
                break;
   
            default:
                assert(0);
            };
  -         strcat(format, "%s, ");
  +            if (regs[i]->type & VTKEY) {
  +                len = strlen(format);
  +                len -= 2;
  +                format[len] = '\0';
  +                strcat(format, "[%s], ");
        }
  -     if (info->jump) {
  -         /* XXX: assume the jump is relative to the last arg.
  -          * usually true. */
  -         dirs |= 1 << (8 + nargs - 2);
  +            else
  +                strcat(format, "%s, ");
        }
        len = strlen(format);
        len -= 2;
        format[len] = '\0';
  -     emitb(mk_instruction(format, args[0], args[1], args[2], args[3],
  -                          dirs));
  -    } else {
  -     fprintf(stderr, "line %ld: no op %s (%s<%d>)\n",
  -             line, fullname, name, nargs);
  -     exit(EX_SOFTWARE);
  +        if (fmt && *fmt)
  +            strcpy(format, fmt);
  +        for (i = nargs; i < IMCC_MAX_REGS; i++)
  +            regs[i] = 0;
  +#if 1
  +        debug(1,"%s %s\t%s\n", name, format, fullname);
  +#endif
  +        /* make the instruction */
  +        ins = emitb(_mk_instruction(name, format, regs, dirs));
  +        /* fill iin oplib's info */
  +        ins->opnum = op;
  +        ins->opsize = info->arg_count;
  +        /* reset the VTKEY flag and remeber the info in ins->keys */
  +        for (i = 0; ins->r[i]; i++)
  +            if (ins->r[i]->type & VTKEY) {
  +                ins->r[i]->type &= ~VTKEY;
  +                ins->keys |= (1<<i);
       }
  -    return NULL;
  +        /* set up branch flags */
  +        if (info->jump) {
  +            if (!strcmp(name, "bsr") || !strcmp(name, "ret")) {
  +                /* ignore subcalls and ret
  +                 * because they saveall
  +                 */
   }
  -
  -void relop_to_op(int relop, char * op) {
  -    switch(relop) {
  -        case RELOP_EQ:    strcpy(op, "eq"); return;
  -        case RELOP_NE:    strcpy(op, "ne"); return;
  -        case RELOP_GT:    strcpy(op, "gt"); return;
  -        case RELOP_GTE:   strcpy(op, "ge"); return;
  -        case RELOP_LT:    strcpy(op, "lt"); return;
  -        case RELOP_LTE:   strcpy(op, "le"); return;
  -        default:
  -            fprintf(stderr, "relop_to_op: Invalid relop [%d]\n", relop);
  -         abort();
  +            else {
  +                /* XXX: assume the jump is relative and to the last arg.
  +                 * usually true.
  +                 */
  +                ins->type = ITBRANCH | (1 << (nargs-1));
  +                if (!strcmp(name, "branch"))
  +                    ins->type |= IF_goto;
  +            }
  +        }
  +        else if (!strcmp(name, "set") && nargs == 2) {
  +            /* set Px, Py: both PMCs have the same address */
  +            if (regs[0]->set == 'P' && regs[1]->set == 'P')
  +                ins->type |= ITALIAS;
  +        }
  +        else if (!strcmp(name, "set_addr")) {
  +            /* XXX propably a CATCH block */
  +            ins->type = ITADDR | IF_r1_branch | ITBRANCH;
  +        }
  +    } else {
  +        fataly(EX_SOFTWARE, "iANY", line,"op not found '%s' (%s<%d>)\n",
  +                fullname, name, nargs);
       }
  +    return NULL;
   }
   
   %}
   
   %union {
  -    int i;
  +    int t;
       char * s;
       SymReg * sr;
  +    Instruction *i;
   }
   
  -%token <i> CALL GOTO BRANCH ARG RET PRINT IF UNLESS NEW END SAVEALL RESTOREALL
  -%token <i> SUB NAMESPACE CLASS ENDCLASS SYM LOCAL PARAM PUSH POP INC DEC
  -%token <i> SHIFT_LEFT SHIFT_RIGHT INTV FLOATV STRINGV DEFINED LOG_XOR
  -%token <i> RELOP_EQ RELOP_NE RELOP_GT RELOP_GTE RELOP_LT RELOP_LTE
  -%token <i> GLOBAL ADDR CLONE RESULT RETURN POW
  -%token <i> COMMA
  -%token <s> EMIT LABEL
  -%token <s> IREG NREG SREG PREG IDENTIFIER STRINGC INTC FLOATC
  -%type <i> type program subs sub sub_start relop
  -%type <s> classname opname
  -%type <sr> labels _labels label statements statement
  -%type <sr> instruction assignment if_statement labeled_inst
  +%token <t> CALL GOTO BRANCH ARG RET PRINT IF UNLESS NEW END SAVEALL RESTOREALL
  +%token <t> SUB NAMESPACE CLASS ENDCLASS SYM LOCAL PARAM PUSH POP INC DEC
  +%token <t> SHIFT_LEFT SHIFT_RIGHT INTV FLOATV STRINGV DEFINED LOG_XOR
  +%token <t> RELOP_EQ RELOP_NE RELOP_GT RELOP_GTE RELOP_LT RELOP_LTE
  +%token <t> GLOBAL ADDR CLONE RESULT RETURN POW
  +%token <t> COMMA
  +%token <s> LABEL
  +%token <t> EMIT EOM
  +%token <s> IREG NREG SREG PREG IDENTIFIER STRINGC INTC FLOATC REG MACRO
  +%token <s> PARROT_OP
  +%type <t> type
  +%type <i> program subs sub sub_start emit
  +%type <s> classname relop
  +%type <i> labels _labels label statements statement
  +%type <i> instruction assignment if_statement labeled_inst
   %type <sr> target reg const var rc string
  -%type <sr> vars _vars var_or_i
  +%type <sr> key keylist _keylist
  +%type <sr> vars _vars var_or_i _var_or_i
  +%type <i> pasmcode pasmline pasm_inst
  +%type <sr> pasm_args lhs
  +%token <sr> VAR
  +
   
   %start program
  +%expect 2
   
   %%
   
   program:
  -    subs emit                                { $$ = 0; }
  +    subs  { $$ = 0; }
  +    ;
  +
  +
  +pasmcode: pasmline
  +    | pasmcode pasmline
  +    ;
  +
  +pasmline: labels  pasm_inst '\n'  { $$ = 0; }
  +    ;
  +pasm_inst: PARROT_OP                       { nargs = 0;
  +                                        memset(regs, 0, sizeof(regs)); }
  +       pasm_args                     { $$ = iANY($1,0,regs,1); free($1); }
  +    | /* none */                               { $$ = 0;}
  +
  +    ;
  +pasm_args:
  +    vars
       ;
   
   emit:
  -    |   EMIT                         { iEMIT($1); }
  +      EMIT   pasmcode                    { $$ = 0 }
  +       EOM '\n'                              { emit_flush(); clear_tables();$$=0 }
       ;
   
  +nls:
  +    '\n'
  +    | nls '\n'
  +
   subs:        subs sub
       |   sub
       ;
   
  -sub: sub_start statements labels RET
  +sub: sub_start statements RET
           {
  -          $$ = 0; iRET();
  +          $$ = 0; MK_I("ret", R0());
          allocate();
          emit_flush();
          clear_tables();
           }
  +        | emit{ $$=0 }
  +        | nls { $$=0 }
       ;
   
  -sub_start: SUB IDENTIFIER
  +sub_start: SUB IDENTIFIER '\n'
           { $$ = 0;
  -          iSUBROUTINE(mk_address($2));
  +          iSUBROUTINE(mk_address($2, U_add_uniq_sub));
           }
       ;
   
  @@ -552,45 +470,53 @@
   
   _labels: _labels label
       |   label
  +    | label '\n'
       ;
   
  -label:  LABEL                                { $$ = iLABEL(mk_address($1)); }
  +label:  LABEL                { $$ = iLABEL(mk_address($1, U_add_uniq_label)); }
       ;
   
   instruction:
  -     labels  { expect_eol = 1; } labeled_inst '\n'  { $$ = $3; }
  +     labels  labeled_inst '\n'  { $$ = $2; }
       ;
   labeled_inst:
        assignment
       |   if_statement
       |   SYM type IDENTIFIER          { mk_ident($3, $2); }
       |   LOCAL type IDENTIFIER                { mk_ident($3, $2); }
  -    |   PARAM type IDENTIFIER                { $$ = iPOP(mk_ident($3, $2));}
  -    |   PARAM reg                    { $$ = iPOP($2); }
  -    |   ARG var                              { $$ = iARG($2); }
  -    |   RESULT var                   { $$ = iRESULT($2); }
  -    |   RETURN var                   { $$ = iRETURN($2); }
  -    |   CALL IDENTIFIER                      { $$ = iCALL(mk_address($2)); }
  -    |   GOTO IDENTIFIER                      { $$ = iBRANCH(mk_address($2));}
  -    |   PUSH var                     { $$ = iPUSH($2); }
  -    |   POP var                              { $$ = iPOP($2); }
  -    |   INC var                              { $$ = iINC($2); }
  -    |   DEC var                              { $$ = iDEC($2); }
  -    |   PRINT var                    { $$ = iPRINT($2); }
  -    |   SAVEALL                              { iSAVEALL(); }
  -    |   RESTOREALL                   { iRESTOREALL(); }
  -    |   END                          { iEND(); }
  -    |  opname                                { nargs = 0;
  -                                       memset(args, 0, sizeof(args));
  +    |   LOCAL type VAR               { $$ = 0;
  +            warning("parser", "file %s line %d: %s already defined\n",
  +            sourcefile, line, $3->name); }
  +    |   PARAM type IDENTIFIER                { $$ = MK_I("restore",
  +                                         R1(mk_ident($3, $2)));}
  +    |   PARAM reg                    { $$ = MK_I("restore", R1($2)); }
  +    |   RESULT var                   { $$ = MK_I("restore", R1($2)); }
  +    |   POP var                              { $$ = MK_I("restore", R1($2)); }
  +    |   ARG var                              { $$ = MK_I("save", R1($2)); }
  +    |   PUSH var                     { $$ = MK_I("save", R1($2)); }
  +    |   RETURN var                   { $$ = MK_I("save", R1($2)); }
  +    |   CALL IDENTIFIER                      { $$ = MK_I("bsr",
  +                                              R1(mk_address($2, U_add_once)));}
  +    |   GOTO IDENTIFIER                      { $$ = MK_I("branch",
  +                                              R1(mk_address($2, U_add_once)));}
  +    |   INC var                              { $$ = MK_I("inc",R1($2)); }
  +    |   DEC var                              { $$ = MK_I("dec",R1($2)); }
  +    |   PRINT var                    { $$ = MK_I("print",R1($2)); }
  +    |   SAVEALL                              { $$ = MK_I("saveall" ,R0()); }
  +    |   RESTOREALL                   { $$ = MK_I("restoreall" ,R0()); }
  +    |   END                          { $$ = MK_I("end" ,R0()); }
  +    |  PARROT_OP                             { nargs = 0;
  +                                       memset(regs, 0, sizeof(regs));
                                        }
  -       vars                          { $$ = iANY($1); }
  +       vars                          { $$ = iANY($1,0,regs, 1); free($1); }
  +    | /* none */                               { $$ = 0;}
       ;
   
   type:
           INTV { $$ = 'I'; }
       |   FLOATV { $$ = 'N'; }
       |   STRINGV { $$ = 'S'; }
  -    |   classname { $$ = 'P'; }
  +    |   classname { $$ = 'P'; free($1); }
       ;
   
   classname:
  @@ -598,54 +524,57 @@
       ;
   
   assignment:
  -       target '=' var                        { $$ = iMOVE($1, $3); }
  -    |  target '=' '!' var            { $$ = iNOT($1, $4); }
  -    |  target '=' '-' var            { $$ = iNEG($1, $4); }
  -    |  target '=' var '+' var                { $$ = iADD($1, $3, $5); }
  -    |  target '=' var '-' var                { $$ = iSUB($1, $3, $5); }
  -    |  target '=' var '*' var                { $$ = iMUL($1, $3, $5); }
  -    |  target '=' var POW var                { $$ = iPOW($1, $3, $5); }
  -    |  target '=' var '/' var                { $$ = iDIV($1, $3, $5); }
  -    |  target '=' var '%' var                { $$ = iMOD($1, $3, $5); }
  -    |  target '=' var '.' var                { $$ = iCONCAT($1, $3, $5); }
  -    |  target '=' var SHIFT_LEFT var { $$ = iSHL($1, $3, $5); }
  -    |  target '=' var SHIFT_RIGHT var        { $$ = iSHR($1, $3, $5); }
  -    |  target '=' var LOG_XOR var    { $$ = iXOR($1, $3, $5); }
  -    |  target '=' var '&' var                { $$ = iBAND($1, $3, $5); }
  -    |  target '=' var '|' var                { $$ = iBOR($1, $3, $5); }
  -    |  target '=' var '~' var                { $$ = iBXOR($1, $3, $5); }
  -    |  target '=' var '[' var ']'    { $$ = iINDEXFETCH($1, $3, $5); }
  -    |  var '[' var ']' '=' var               { $$ = iINDEXSET($1, $3, $6); }
  +       target '=' var                        { $$ = MK_I("set", R2($1, $3)); }
  +    |  target '=' '!' var            { $$ = MK_I("not", R2($1, $4));}
  +    |  target '=' '-' var            { $$ = MK_I("neg", R2($1, $4));}
  +    |  target '=' var '+' var                { $$ = MK_I("add", R3($1, $3, $5)); }
  +    |  target '=' var '-' var                { $$ = MK_I("sub", R3($1, $3, $5)); }
  +    |  target '=' var '*' var                { $$ = MK_I("mul", R3($1, $3, $5)); }
  +    |  target '=' var POW var                { $$ = MK_I("pow", R3($1, $3, $5)); }
  +    |  target '=' var '/' var                { $$ = MK_I("div", R3($1, $3, $5)); }
  +    |  target '=' var '%' var                { $$ = MK_I("mod", R3($1, $3, $5)); }
  +    |  target '=' var '.' var                { $$ = MK_I("concat", R3($1,$3,$5)); }
  +    |  target '=' var SHIFT_LEFT var { $$ = MK_I("shl", R3($1, $3, $5)); }
  +    |  target '=' var SHIFT_RIGHT var        { $$ = MK_I("shr", R3($1, $3, $5)); }
  +    |  target '=' var LOG_XOR var    { $$ = MK_I("xor", R3($1, $3, $5)); }
  +    |  target '=' var '&' var                { $$ = MK_I("band", R3($1, $3, $5)); }
  +    |  target '=' var '|' var                { $$ = MK_I("bor", R3($1, $3, $5)); }
  +    |  target '=' var '~' var                { $$ = MK_I("bxor", R3($1, $3, $5)); }
  +    |  target '=' var '[' keylist ']'{ $$ = iINDEXFETCH($1, $3, $5); }
  +    |  var '[' keylist ']' '=' var   { $$ = iINDEXSET($1, $3, $6); }
       |  target '=' NEW classname              { $$ = iNEW($1, $4); }
  -    |  target '=' DEFINED var                { $$ = iDEFINED($1, $4); }
  -    |  target '=' CLONE var          { $$ = iCLONE($1, $4); }
  -    |  target '=' ADDR IDENTIFIER    { $$ = iSET_ADDR($1, mk_address($4)); }
  -    |  target '=' GLOBAL string              { $$ = iGET_GLOBAL($1, $4); }
  -    |  GLOBAL string '=' var         { $$ = iSET_GLOBAL($2, $4); }
  +    |  target '=' DEFINED var        { $$ = MK_I("defined %s, %s",R2($1,$4)); }
  +    |  target '=' CLONE var          { $$ = MK_I("clone %s, %s",R2($1, $4));
  +    }
  +    |  target '=' ADDR IDENTIFIER    { $$ = MK_I("set_addr",
  +                                          R2($1, mk_address($4,U_add_once))); }
  +    |  target '=' GLOBAL string      { $$ = MK_I("find_global",R2($1,$4)); }
  +    |  GLOBAL string '=' var { $$ = MK_I("store_global",R2($2,$4)); }
       ;
   
   if_statement:
  -       IF var relop var GOTO IDENTIFIER
  -                             { $$ = iIF($3, $2, $4, mk_address($6)); }
  -    |  IF var GOTO IDENTIFIER
  -                             { $$ = iIF1("if",$2, mk_address($4)); }
  -    |  UNLESS var GOTO IDENTIFIER
  -                             { $$ = iIF1("unless", $2, mk_address($4)); }
  +       IF var relop var GOTO IDENTIFIER { $$=MK_I($3,R3($2,$4,
  +                                          mk_address($6,U_add_once))); }
  +    |  IF var GOTO IDENTIFIER           {$$= MK_I("if", R2($2,
  +                                          mk_address($4, U_add_once))); }
  +    |  UNLESS var GOTO IDENTIFIER       {$$= MK_I("unless",R2($2,
  +                                          mk_address($4, U_add_once))); }
       ;
   
   relop:
  -       RELOP_EQ                              { $$ = RELOP_EQ; }
  -    |  RELOP_NE                              { $$ = RELOP_NE; }
  -    |  RELOP_GT                              { $$ = RELOP_GT; }
  -    |  RELOP_GTE                     { $$ = RELOP_GTE; }
  -    |  RELOP_LT                              { $$ = RELOP_LT; }
  -    |  RELOP_LTE                     { $$ = RELOP_LTE; }
  +       RELOP_EQ                              { $$ = "eq"; }
  +    |  RELOP_NE                              { $$ = "ne"; }
  +    |  RELOP_GT                              { $$ = "gt"; }
  +    |  RELOP_GTE                     { $$ = "ge"; }
  +    |  RELOP_LT                              { $$ = "lt"; }
  +    |  RELOP_LTE                     { $$ = "le"; }
       ;
   
  -opname: IDENTIFIER
  -    ;
   
  -target: IDENTIFIER                   { $$ = get_sym($1); free($1); }
  +target: VAR
  +    |  reg
  +    ;
  +lhs: VAR
       |  reg
       ;
   
  @@ -653,19 +582,34 @@
       |  _vars  { $$ = $1; }
       ;
   
  -_vars: _vars COMMA var_or_i          { args[nargs++] = $3; $$ = args[0]; }
  -    |  var_or_i                              { args[nargs++] = $1; $$ = $1; }
  +_vars: _vars COMMA _var_or_i         { $$ = regs[0]; }
  +    |  _var_or_i
       ;
   
  +_var_or_i: var_or_i                     { regs[nargs++] = $1 }
  +    | lhs '[' keylist ']'               { regs[nargs++] = $1;
  +                                          regs[nargs++] = $3; $$= $1; }
  +    ;
   var_or_i:
  -       IDENTIFIER                    { $$ = mk_address($1); }
  -    |  rc
  +       IDENTIFIER                    { $$ = mk_address($1, U_add_once); }
  +    |  var
  +    | MACRO                             { $$ = macro($1+1); free($1)}
       ;
   
  -var:   IDENTIFIER                   { $$ = get_sym($1); free($1); }
  +var:   VAR
       |  rc
       ;
   
  +keylist:                                { nkeys=0 }
  +       _keylist                         { $$ = link_keys(nkeys, keys); }
  +    ;
  +
  +_keylist: key                            { keys[nkeys++] = $1; }
  +     | _keylist ';' key                  { keys[nkeys++] = $3; $$ =  keys[0] }
  +    ;
  +
  +key:  var
  +
   rc:  reg
       |        const
       ;
  @@ -674,6 +618,7 @@
       |  NREG                          { $$ = mk_symreg($1, 'N'); }
       |  SREG                          { $$ = mk_symreg($1, 'S'); }
       |  PREG                          { $$ = mk_symreg($1, 'P'); }
  +    |  REG                              { $$ = mk_pasm_reg($1); }
       ;
   
   const: INTC                          { $$ = mk_const($1, 'I'); }
  @@ -687,86 +632,303 @@
   %%
   
   extern FILE *yyin;
  -int IMCC_DEBUG = 0;
  +int IMCC_DEBUG;
  +int gc_off;
  +static int pbc, write_pbc;
  +char* output;
   
  -int main(int argc, char * argv[])
  +static void usage(FILE *fp)
   {
  -    char* output;
  -    while (argc > 1) {
  -     if(! strcmp (argv[1], "--debug")) {
  -         IMCC_DEBUG = 1;
  -         argc--;
  -         argv++;
  -         continue;
  +    fprintf(fp, "imcc [-h|--help] [-V|--version] [-d|--debug] [-v|--verbose]\n");
  +    fprintf(fp, "\t[-y|--yydebug] [-r|--runpbc] [-t|--trace] [-o outfile] 
infile\n");
  +    exit(fp != stdout);
        }
  -     if(! strcmp (argv[1], "--yydebug")) {
  -         yydebug = 1;
  -         argc--;
  -         argv++;
  -         continue;
  +
  +
  +static void help()
  +{
  +    usage(stdout);
        }
  -     if(! strcmp (argv[1], "--verbose")) {
  -         IMCC_VERBOSE = 1;
  -         argc--;
  -         argv++;
  -         continue;
  +
  +static void version()
  +{
  +    printf("imcc version " IMCC_VERSION "\n");
  +    exit(0);
        }
  -     if(! strcmp (argv[1], "--life-info")) {
  -         IMCC_LIFE_INFO = 1;
  -         argc--;
  -         argv++;
  -         continue;
  +
  +#define setopt(flag) Parrot_setflag(interpreter, flag, (*argv)[0]+2);
  +#define unsetopt(flag) Parrot_setflag(interpreter, flag, 0)
  +
  +/* most stolen from test_main.c */
  +char *
  +parseflags(Parrot_Interp interpreter, int *argc, char **argv[])
  +{
  +    if (*argc == 1) {
  +        usage(stderr);
        }
  +
  +    /* skip the program name arg */
  +    (*argc)--;
  +    (*argv)++;
  +
  +#ifdef HAVE_COMPUTED_GOTO
  +    setopt(PARROT_CGOTO_FLAG);
  +#endif
  +
  +    while ((*argc) && (*argv)[0][0] == '-') {
  +        switch ((*argv)[0][1]) {
  +        case 'b':
  +            setopt(PARROT_BOUNDS_FLAG);
  +            break;
  +        case 'j':
  +            setopt(PARROT_JIT_FLAG);
  +            break;
  +        case 'p':
  +            setopt(PARROT_PROFILE_FLAG);
  +            break;
  +        case 'P':
  +            setopt(PARROT_PREDEREF_FLAG);
  +            break;
  +        case 'g':
  +            unsetopt(PARROT_CGOTO_FLAG);
  +            break;
  +        case 't':
  +            setopt(PARROT_TRACE_FLAG);
  +            break;
  +        case 'd':
  +            setopt(PARROT_DEBUG_FLAG);
  +            IMCC_DEBUG++;
        break;
  +        case 'w':
  +            Parrot_setwarnings(interpreter, PARROT_WARNINGS_ALL_FLAG);
  +            break;
  +        case 'G':
  +            gc_off = 1;
  +            break;
  +        case '.':  /* Give Windows Parrot hackers an opportunity to
  +                    * attach a debuggger. */
  +            fgetc(stdin);
  +            break;
  +        case 'h':
  +            usage(stdin);
  +            break;
  +        case 'V':
  +            version();
  +            break;
  +        case 'r':
  +            pbc = 1;
  +            break;
  +        case 'c':
  +            write_pbc = 1;
  +            break;
  +        case 'v':
  +         IMCC_VERBOSE++;
  +            break;
  +        case 'y':
  +         yydebug = 1;
  +            break;
  +        case 'o':
  +            if ((*argv)[0][2])
  +                output = str_dup((*argv)[0]+2);
  +            else {
  +                (*argc)--;
  +                output = str_dup((++(*argv))[0]);
       }
  +     break;
   
  -    if (argc <= 1) {
  -        fprintf(stderr, "No source file specified.\n" );
  -        exit(EX_NOINPUT);
  +        case 'O':
  +         strncpy(optimizer_opt, (*argv)[0]+2,sizeof(optimizer_opt));
  +         optimizer_opt[sizeof(optimizer_opt)-1] = '\0';
  +            break;
  +        case '-':
  +            /* XXX long options */
  +            (*argc)--;
  +            (*argv)++;
  +
  +            goto OUT;
  +        case '\0':             /* bare '-' means read from stdin */
  +            goto OUT;
  +        default:
  +            fatal(1, "main", "Invalid flag %s used\n", (*argv)[0]);
  +            exit(1);
       }
   
  -    if(!(yyin = fopen(argv[1], "r")))    {
  -        fprintf(stderr, "Error reading source file %s.\n", argv[1] );
  -        exit(EX_IOERR);
  +        (*argc)--;
  +        (*argv)++;
       }
   
  -    if (IMCC_DEBUG)
  -     fprintf(stderr, "loading libs...");
  +  OUT:
   
  -    op_load_file("../../blib/lib/libparrot" PARROT_DLL_EXTENSION);
  -    op_load_lib("core", PARROT_MAJOR_VERSION,
  -                        PARROT_MINOR_VERSION,
  -                        PARROT_PATCH_VERSION);
  -    if (IMCC_DEBUG)
  -     fprintf(stderr, "done\n");
  +    return (*argv)[0];
  +}
   
  -    line = 1;
  +#ifdef OPTEST
  +#define USE_HOP
   
  -    if (IMCC_DEBUG)
  -     fprintf(stderr, "Pass 1: Starting parse...\n");
  +#define OP_HASH_SIZE 1511
  +typedef struct hop {
  +    op_info_t * info;
  +    struct hop *next;
  +} HOP;
  +static HOP **hop;
   
  -    if (argc > 2) {
  -        output = argv[2];
  +static void store_op(op_info_t *info) {
  +    HOP *p = malloc(sizeof(HOP));
  +    int index = hash_str(info->full_name) % OP_HASH_SIZE;
  +    p->info = info;
  +    p->next = hop[index];
  +    hop[index] = p;
       }
  -    else {
  -        output = "a.pasm";
  +static void hop_init() {
  +    int i;
  +    op_info_t * info = interpreter->op_info_table;
  +    for (i = 0; i < interpreter->op_count; i++)
  +        store_op(info + i);
  +}
  +int get_op(const char * name) {
  +    HOP * p;
  +    int index = hash_str(name) % OP_HASH_SIZE;
  +    if (!hop) {
  +        hop = calloc(OP_HASH_SIZE, sizeof(HOP*));
  +        hop_init();
  +    }
  +    for(p = hop[index]; p; p = p->next) {
  +     if(!strcmp(name, p->info->full_name))
  +         return p->info - interpreter->op_info_table;
  +    }
  +    return -1;
  +}
  +void hop_deinit()
  +{
  +    HOP *p, *next;
  +    int i;
  +    for (i = 0; i < OP_HASH_SIZE; i++)
  +        for(p = hop[i]; p; ) {
  +            next = p->next;
  +            free(p);
  +            p = next;
  +    }
  +    free(hop);
  +    hop = 0;
       }
   
  -    freopen(output, "w", stdout);
   
  -    yyparse();
  +static void test_ops()
  +{
  +    int i,j,n = interpreter->op_count;
  +    op_info_t * info = interpreter->op_info_table;
  +    int op;
  +
  +    printf("testing op_code for %d ops 10000 times\n", n);
  +    /* 10.000 runs for 889 ops: 8.3-8.5 s */
  +    for (i = 0; i < n; i++) {
  +        for (j = 0; j < 10000 ; j++) {
  +#ifdef USE_HOP
  +            op = get_op(info[i].full_name);
  +            if (op != i) {
  +                printf("Op %d %s not found\n", i, info[i].full_name);
  +                exit(1);
  +            }
  +#else
  +            op = interpreter->op_lib->op_code(info[i].full_name);
  +            if (i != op) {
  +                printf("Op %d %s not found\n", i, info[i].full_name);
  +                exit(1);
  +            }
  +#endif
  +        }
  +    }
  +#ifdef USE_HOP
  +    hop_deinit();
  +#endif
  +}
   
  -    /* Flush any pending code such as .emits */
  -    emit_flush();
  +#endif
   
  -    fclose(yyin);
  -    fclose(stdout);
  -    op_close_lib();
  +int main(int argc, char * argv[])
  +{
  +    void * stacktop;
  +    struct PackFile *pf;
  +
  +    interpreter = Parrot_new();
  +    Parrot_init(interpreter, stacktop);
  +    pf = PackFile_new();
  +    interpreter->code = pf;
  +#ifdef OPTEST
  +    test_ops();
  +    exit(0);
  +#endif
  +    interpreter->DOD_block_level++;
  +
  +    sourcefile = parseflags(interpreter, &argc, &argv);
  +
  +    /* default optimizations, s. optimizer.c */
  +    if (!*optimizer_opt)
  +     strcpy(optimizer_opt, "0");
  +
  +    if (!sourcefile || !*sourcefile) {
  +        fatal(EX_NOINPUT, "main", "No source file specified.\n" );
  +    }
  +    else if (!strcmp(sourcefile, "-"))
  +       yyin = stdin;
  +    else
  +        if(!(yyin = fopen(sourcefile, "r")))    {
  +            fatal(EX_IOERR, "main", "Error reading source file %s.\n",
  +                    sourcefile);
  +    }
  +
  +    if (!output)
  +        output = str_dup(pbc ? "a.pbc" : "a.pasm");
   
       if (IMCC_VERBOSE) {
  -     fprintf(stderr, "%ld lines compiled.\n", line);
  -     fprintf(stderr, "Compiling assembly module %s\n", output);
  +        info(1,"Reading %s", yyin == stdin ? "stdin":sourcefile);
  +        if (pbc)
  +            info(1, ", executing");
  +        if (write_pbc)
  +            info(1, " and writing %s\n", output);
  +        else
  +            info(1,"\n");
  +    }
  +    info(1, "using optimization '%s'\n", optimizer_opt);
  +
  +    line = 1;
  +    emit_open(write_pbc | pbc, output);
  +
  +    debug(1, "Starting parse...\n");
  +
  +    yyparse();
  +    emit_close();
  +    fclose(yyin);
  +
  +    info(1, "%ld lines compiled.\n", line);
  +    if (write_pbc) {
  +        size_t size;
  +        opcode_t *packed;
  +        FILE *fp;
  +
  +        size = PackFile_pack_size(interpreter->code);
  +        info(1, "packed code %d bytes\n", size);
  +        packed = (opcode_t*) mem_sys_allocate(size);
  +        if (!packed)
  +            fatal(1, "main", "Out of mem\n");
  +        PackFile_pack(interpreter->code, packed);
  +        if ((fp = fopen(output, "wb")) == 0)
  +            fatal(1, "main", "Couldn't open %s\n", output);
  +        if ((1 != fwrite(packed, size, 1, fp)) )
  +            fatal(1, "main", "Couldn't write %s\n", output);
  +        fclose(fp);
  +        info(1, "%s written.\n", output);
  +        free(packed);
  +    }
  +    if (pbc == 1) {
  +        if (!gc_off)
  +            interpreter->DOD_block_level--;
  +        info(1, "Running...\n");
  +        Parrot_runcode(interpreter, argc, argv);
  +        /* XXX no return value :-( */
  +        Parrot_destroy(interpreter);
       }
  +    free(output);
   
       return 0;
   }
  @@ -778,3 +940,13 @@
       fprintf(stderr, "Didn't create output asm.\n" );
       exit(EX_UNAVAILABLE);
   }
  +
  +/*
  + * Local variables:
  + * c-indentation-style: bsd
  + * c-basic-offset: 4
  + * indent-tabs-mode: nil
  + * End:
  + *
  + * vim: expandtab shiftwidth=4:
  +*/
  
  
  


Reply via email to