static void eval(Node *p) { int i, lbl1, lbl2; char *name; if (p == 0) return; switch(p->attrib) { case INTEGER: fprintf(out, pfIMM, p->value.i); /* push an integer immediate */ break; case STRING: /* generate the string */ fprintf(out, pfRODATA); /* strings are DATA readonly */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); /* name the string */ fprintf(out, pfSTR, p->value.s); /* output string characters */ /* make the call */ fprintf(out, pfTEXT); /* return to the TEXT segment */ fprintf(out, pfADDR, mklbl(lbl1)); /* the string to be printed */ fprintf(out, pfCALL, "_prints"); /* call the print rotine */ fprintf(out, pfCALL, "_println"); /* print a newline */ fprintf(out, pfTRASH, sizeof(regint)); /* remove the string address: 4/8 bytes */ break; case VARIABLE: if (IDfind(p->value.s, 0) >= 0) { fprintf(out, pfADDR, p->value.s); fprintf(out, pfLOAD); } break; case WHILE: fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); eval(p->SUB(0)); fprintf(out, pfJZ, mklbl(lbl2 = ++lbl)); eval(p->SUB(1)); fprintf(out, pfJMP, mklbl(lbl1)); fprintf(out, pfLABEL, mklbl(lbl2)); break; case IF: eval(p->SUB(0)); fprintf(out, pfJZ, mklbl(lbl1 = ++lbl)); eval(p->SUB(1)); if (p->value.sub.num > 2) { /* if else */ fprintf(out, pfJMP, mklbl(lbl2 = ++lbl)); fprintf(out, pfLABEL, mklbl(lbl1)); eval(p->SUB(2)); lbl1 = lbl2; } fprintf(out, pfLABEL, mklbl(lbl1)); break; case READ: if (IDfind(p->value.s, 0) >= 0) { fprintf(out, pfCALL, "_readi"); fprintf(out, pfPUSH); fprintf(out, pfADDR, p->value.s); fprintf(out, pfSTORE); } break; case PRINT: eval(p->SUB(0)); /* determine the value */ fprintf(out, pfCALL, "_printi"); /* call the print function */ fprintf(out, pfCALL, "_println"); /* print a newline */ fprintf(out, pfTRASH, sizeof(regint)); /* remove the printed value: 4/8 bytes */ break; case ';': for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case '=': name = p->SUB(0)->value.s; if (IDfind(name, (int*)IDtest) == -1) { /* variable not found ? */ fprintf(out, pfDATA); /* variables are DATA */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfLABEL, name); /* name variable location */ #ifdef _64bits_ fprintf(out, pfLONG, 0LL); /* initialize it to 0 (zero) */ #else fprintf(out, pfINTEGER, 0); /* initialize it to 0 (zero) */ #endif fprintf(out, pfTEXT); /* return to the TEXT segment */ IDnew(INTEGER, name, 0); /* put in the symbol table */ } eval(p->SUB(1)); /* determine the new value */ fprintf(out, pfADDR, name); /* where to store the value */ fprintf(out, pfSTORE); /* store the value at address */ break; case UMINUS: eval(p->SUB(0)); /* determine the value */ fprintf(out, pfNEG); /* make the 2-compliment */ break; default: eval(p->SUB(0)); /* evaluate first argument */ eval(p->SUB(1)); /* evaluate second argument */ switch(p->attrib) { /* make the operation ... */ case '+': fprintf(out, pfADD); break; case '-': fprintf(out, pfSUB); break; case '*': fprintf(out, pfMUL); break; case '/': fprintf(out, pfDIV); break; case '%': fprintf(out, pfMOD); break; case '<': fprintf(out, pfLT); break; case '>': fprintf(out, pfGT); break; case GE: fprintf(out, pfGE); break; case LE: fprintf(out, pfLE); break; case NE: fprintf(out, pfNE); break; case EQ: fprintf(out, pfEQ); break; default: printf("unknown %d\n", p->attrib); } } }
static void eval(Node *p){ int i, lbl1, lbl2, size, temp = 0, attrib = 1; char *name; if (p == 0) return; switch(p->attrib){ case CONTINUE: /* JMP cond*/ break; case BREAK: /* JMP fim */ break; case ELIF: break; case FOR: eval(p->SUB(0)); fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); eval(p->SUB(1)); fprintf(out, pfJZ, mklbl(lbl2 = ++lbl)); IDpush(); eval(p->SUB(3)); eval(p->SUB(2)); IDpop(); fprintf(out, pfJMP, mklbl(lbl1)); fprintf(out, pfLABEL, mklbl(lbl2)); break; case ALLOCA: eval(p->SUB(1)); fprintf(out, pfALLOC); fprintf(out, pfSP); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case EXTERN: /* extern declarations */ for (i = 0; i < p->value.sub.num; i++){ name = p->SUB(i)->SUB(0)->value.s; IDnew(EXTERN, name, p->SUB(i)->value.sub.num); fprintf(out, pfEXTRN, name); } break; case INIT: name = p->SUB(0)->SUB(0)->value.s; IDnew(INIT, name, p->SUB(1)->value.sub.num); fprintf(out, pfDATA); fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfGLOBL, name, pfOBJ); fprintf(out, pfLABEL, name); for(i = 0; i < p->SUB(1)->value.sub.num; i++){ fprintf(out, pfCONST, p->SUB(1)->SUB(i)->value.i); } fprintf(out, pfTEXT); fprintf(out, pfALIGN); /* make sure we are aligned */ break; case CONST: fprintf(out, pfRODATA); fprintf(out, pfALIGN); name = p->SUB(0)->SUB(0)->value.s; IDnew(CONST, name, p->SUB(1)->value.sub.num); fprintf(out, pfLABEL, name); /* name variable location */ for (temp = 0; temp < p->SUB(1)->value.sub.num; temp++) fprintf(out, pfCONST, p->SUB(1)->SUB(temp)->value.i); fprintf(out, pfTEXT); fprintf(out, pfALIGN); break; case LVALUE2: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case LVALUE: name = p->SUB(0)->SUB(0)->value.s; if(p->SUB(0)->SUB(0)->attrib == IDLVALUE) IDnew(INT_NUMBER, name, offset); else if (p->SUB(0)->SUB(0)->attrib == IDARRAY) IDnew(ARRAY, name, offset); else{ name = p->SUB(0)->SUB(0)->SUB(0)->value.s; offset -= 4 * p->SUB(0)->SUB(1)->value.i; IDnew(ARRAYINDEX, name, offset); break; } offset -= 4; break; case VAR: for (i = 0; i < p->value.sub.num; i++){ eval(p->SUB(i)); } break; case ARRAYINDEX: eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfINT, 4); /* push an integer */ fprintf(out, pfMUL); eval(p->SUB(0)); fprintf(out, pfADD); break; case ARRAY: eval(p->SUB(0)); break; case FNNAME: name = p->SUB(0)->SUB(0)->value.s; if(p->value.sub.num == 2) temp = p->SUB(1)->value.sub.num; IDnew(FNNAME, name, temp); IDpush(); IDnew(INT_NUMBER, name, -4); offset = -8; fprintf(out, pfTEXT); fprintf(out, pfALIGN); fprintf(out, pfGLOBL, name, pfFUNC); fprintf(out, pfLABEL, name); fprintf(out, pfENTER, args + 4); break; case FUNCTION: args = count_args(p); for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); fprintf(out, pfLOCAL, -4); fprintf(out, pfLOAD); fprintf(out, pfPOP); fprintf(out, pfLEAVE); fprintf(out, pfRET); IDpop(); break; case INT_NUMBER: fprintf(out, pfINT, p->value.i); /* push an integer */ break; case ID: /* */ name = p->SUB(0)->value.s; switch(p->SUB(0)->attrib){ case IDLVALUE: case IDARRAY: case IDARRAYINDEX: temp = IDfind(name, &attrib); fprintf(out, pfLOCAL, attrib); break; default: fprintf(out, pfADDR, name); break; } break; case DO: fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); IDpush(); eval(p->SUB(0)); IDpop(); fprintf(out, pfLABEL, mklbl(lbl2 = ++lbl)); eval(p->SUB(1)); fprintf(out, pfJNZ, mklbl(lbl1)); if (p->value.sub.num > 2){ /* do else */ IDpush(); eval(p->SUB(2)); IDpop(); } break; case WHILE: fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); eval(p->SUB(0)); fprintf(out, pfJZ, mklbl(lbl2 = ++lbl)); IDpush(); eval(p->SUB(1)); IDpop(); fprintf(out, pfJMP, mklbl(lbl1)); fprintf(out, pfLABEL, mklbl(lbl2)); if (p->value.sub.num > 2){ /* while else */ IDpush(); eval(p->SUB(2)); IDpop(); } break; case CALL: name = p->SUB(0)->value.s; if(p->value.sub.num == 2) { for(i = p->SUB(1)->value.sub.num; i > 0; i--){ eval(p->SUB(i)); /* evaluate argument */ if (p->SUB(i)->attrib != INT_NUMBER) fprintf(out, pfLOAD); } } fprintf(out, pfCALL, name); fprintf(out, pfTRASH, i); /* remove the return value */ fprintf(out, pfPUSH); break; case STR: /* generate the string */ fprintf(out, pfRODATA); /* strings are DATA readonly */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfLABEL, mklbl(lbl1 = ++lbl)); /* give the string a name */ fprintf(out, pfSTR, p->value.s); /* output string characters */ /* make the call */ fprintf(out, pfTEXT); /* return to the TEXT segment */ fprintf(out, pfALIGN); /* make sure we are aligned */ fprintf(out, pfADDR, mklbl(lbl1)); break; case PRINTSTUFF: eval(p->SUB(0)); if(p->SUB(0)->attrib == ID){ fprintf(out, pfLOAD); fprintf(out, pfCALL, "printi"); /* call the print function */ } else if(p->SUB(0)->attrib == STR){ fprintf(out, pfCALL, "prints"); /* call the print function */ } else if(p->SUB(0)->attrib == INT_NUMBER){ fprintf(out, pfCALL, "printi"); /* call the print function */ } print = 0; break; case '!': print = 1; eval(p->SUB(0)); /* determine the value */ fprintf(out, pfTRASH, 4); /* delete the printed value */ break; case OUT: print = 1; eval(p->SUB(0)); /* determine the value */ fprintf(out, pfCALL, "println"); /* print a newline */ fprintf(out, pfTRASH, 4); /* delete the printed value */ break; case IF: eval(p->SUB(0)); if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfJZ, mklbl(lbl1 = ++lbl)); IDpush(); eval(p->SUB(1)); IDpop(); if (p->value.sub.num > 2){ /* if else */ fprintf(out, pfJMP, mklbl(lbl2 = ++lbl)); fprintf(out, pfLABEL, mklbl(lbl1)); IDpush(); eval(p->SUB(2)); IDpop(); lbl1 = lbl2; } fprintf(out, pfLABEL, mklbl(lbl1)); break; case BONUS: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case COMPOUND_STAT: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case CONST_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case DECL_VAR_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case EXPRESSION_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case EXTRA_STAT_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case NUM_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case PROGRAM: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case STATEMENT: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case STATEMENT_LIST: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case ULTRA: for (i = 0; i < p->value.sub.num; i++) eval(p->SUB(i)); break; case AND_OP: eval(p->SUB(0)); /* evaluate first argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfDUP); fprintf(out, pfJZ, mklbl(lbl1 = ++lbl)); fprintf(out, pfTRASH, 4); eval(p->SUB(1)); /* evaluate second argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfLABEL, mklbl(lbl1)); break; case OR_OP: eval(p->SUB(0)); /* evaluate first argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfDUP); fprintf(out, pfJNZ, mklbl(lbl1 = ++lbl)); fprintf(out, pfTRASH, 4); eval(p->SUB(1)); /* evaluate second argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfLABEL, mklbl(lbl1)); break; case NOT: eval(p->SUB(0)); /* evaluate argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfINT, 0); fprintf(out, pfEQ); break; case '?': fprintf(out, pfCALL, "readi"); fprintf(out, pfPUSH); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case '=': eval(p->SUB(1)); /* determine the new value */ if(p->SUB(1)->attrib == '='){ eval(p->SUB(1)->SUB(0)); fprintf(out, pfLOAD); } eval(p->SUB(0)); /* determine the new address */ fprintf(out, pfSTORE); /* store the value at address */ break; case '@': eval(p->SUB(0)); /* evaluate argument */ break; case SIMETRIC: eval(p->SUB(0)); /* evaluate argument */ if (p->SUB(0)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfNEG); /* make the 2-compliment */ break; case INC: eval(p->SUB(0)); /* evaluate argument */ fprintf(out, pfINCR, 1); break; case DEC: eval(p->SUB(0)); /* evaluate argument */ fprintf(out, pfDECR, 1); break; case ADDEDATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfADD); eval(p->SUB(0)); /* determine the new address */ fprintf(out, pfSTORE); /* store the value at address */ break; /* case MINUSATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfSUB); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case MULATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfMUL); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case DIVATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfDIV); fprintf(out, pfADD); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case MODATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); fprintf(out, pfMOD); eval(p->SUB(0)); fprintf(out, pfSTORE); break; case EXPATTRIB: eval(p->SUB(0)); fprintf(out, pfLOAD); eval(p->SUB(1)); if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); pow_flag = 1; fprintf(out, pfCALL, "power"); fprintf(out, pfTRASH, 8); fprintf(out, pfPUSH); eval(p->SUB(0)); fprintf(out, pfSTORE); break; */ default: if(print){ if(p->attrib == '+'){ for (i = 0; i < p->value.sub.num; i++){ eval(p->SUB(i)); if(p->SUB(i)->attrib == ID){ fprintf(out, pfLOAD); fprintf(out, pfCALL, "printi"); /* call the print function */ } else if(p->SUB(i)->attrib == INT_NUMBER){ fprintf(out, pfCALL, "printi"); /* call the print function */ } else if (p->SUB(i)->attrib == STR){ fprintf(out, pfCALL, "prints"); /* call the print function */ } else if(p->SUB(i)->attrib == '*'){ eval(p->SUB(i)->SUB(1)); /* determine the value */ if (p->SUB(i)->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); eval(p->SUB(i)->SUB(0)); /* determine the value */ printer_flag = 1; fprintf(out, pfCALL, "printer"); /* print a newline */ fprintf(out, pfTRASH, 4); /* remove the return value */ } } } else{ eval(p->SUB(1)); /* determine the value */ if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); eval(p->SUB(0)); /* determine the value */ printer_flag = 1; fprintf(out, pfCALL, "printer"); /* print a newline */ fprintf(out, pfTRASH, 4); /* remove the return value */ } } else{ eval(p->SUB(1)); /* evaluate first argument */ if (p->SUB(1)->attrib != INT_NUMBER) fprintf(out, pfLOAD); switch(p->attrib){ /* make the operation ... */ case '+': eval(p->SUB(0)); /* determine the new value */ if (verif(p->SUB(0))) fprintf(out, pfLOAD); fprintf(out, pfADD); break; case '-': eval(p->SUB(0)); /* determine the new value */ if (p->SUB(0)->attrib != INT_NUMBER && p->SUB(0)->attrib != '-') fprintf(out, pfLOAD); fprintf(out, pfSUB); break; case '*': eval(p->SUB(0)); /* determine the new value */ if (p->SUB(0)->attrib != INT_NUMBER && p->SUB(0)->attrib != '*') fprintf(out, pfLOAD); fprintf(out, pfMUL); break; case '/': eval(p->SUB(0)); /* determine the new value */ if (p->SUB(0)->attrib != INT_NUMBER && p->SUB(0)->attrib != '/') fprintf(out, pfLOAD); fprintf(out, pfDIV); break; case '%': eval(p->SUB(0)); /* determine the new value */ if (p->SUB(0)->attrib != INT_NUMBER && p->SUB(0)->attrib != '%') fprintf(out, pfLOAD); fprintf(out, pfMOD); break; case EXP: eval(p->SUB(0)); /* determine the new value */ if (p->SUB(0)->attrib != INT_NUMBER && p->SUB(0)->attrib != EXP) fprintf(out, pfLOAD); pow_flag = 1; fprintf(out, pfCALL, "power"); fprintf(out, pfTRASH, 8); fprintf(out, pfPUSH); break; case '<': fprintf(out, pfLT); break; case '>': fprintf(out, pfGT); break; case GE_OP: fprintf(out, pfGE); break; case LE_OP: fprintf(out, pfLE); break; case NE_OP: fprintf(out, pfNE); break; case EQ_OP: fprintf(out, pfEQ); break; case IMPLICA: eval(p->SUB(0)); fprintf(out, pfNOT); eval(p->SUB(1)); fprintf(out, pfOR); break; default: printf("WTF? Unknown %d ('%c') !\n", p->attrib, p->attrib); } } } }