Expression *TypeCompiler::visit(ConditionalExpression *conditional) { FuncState *fs = cs->fs; int flist; int escapelist = NO_JUMP; int reg = fs->freereg; Expression *expr = conditional->expression; Expression *trueExpr = conditional->trueExpression; Expression *falseExpr = conditional->falseExpression; expr->visitExpression(this); flist = BC::cond(cs, &expr->e); /*true statement*/ BlockCnt bl; enterBlock(fs, &bl, 0); BC::singleVar(cs, &conditional->e, "__ls_ternary"); trueExpr->visitExpression(this); BC::storeVar(fs, &conditional->e, &trueExpr->e); lmAssert(bl.breaklist == NO_JUMP, "Internal Compiler Error"); leaveBlock(fs); fs->freereg = reg; /* false statement*/ BC::concat(fs, &escapelist, BC::jump(fs)); BC::patchToHere(fs, flist); BlockCnt bl2; enterBlock(fs, &bl2, 0); BC::singleVar(cs, &conditional->e, "__ls_ternary"); falseExpr->visitExpression(this); BC::storeVar(fs, &conditional->e, &falseExpr->e); lmAssert(bl.breaklist == NO_JUMP, "Internal Compiler Error"); leaveBlock(fs); BC::patchToHere(fs, escapelist); fs->freereg = reg; BC::singleVar(cs, &conditional->e, "__ls_ternary"); return conditional; }
void compileFuncDecl(void) { Object* funcObj; Type* returnType; eat(KW_FUNCTION); eat(TK_IDENT); checkFreshIdent(currentToken->string); funcObj = createFunctionObject(currentToken->string); declareObject(funcObj); enterBlock(funcObj->funcAttrs->scope); compileParams(); eat(SB_COLON); returnType = compileBasicType(); funcObj->funcAttrs->returnType = returnType; eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); exitBlock(); }
Statement *TypeCompiler::visit(DoStatement *statement) { FuncState *fs = cs->fs; BlockCnt bl; int whileinit = BC::getLabel(fs); enterBlock(fs, &bl, 1); /* statements*/ statement->statement->visitStatement(this); lua_assert(bl.breaklist == NO_JUMP); statement->expression->visitExpression(this); ExpDesc c = statement->expression->e; int condexit = BC::cond(cs, &c); BC::patchList(fs, BC::jump(fs), whileinit); leaveBlock(fs); BC::patchToHere(fs, condexit); /* false conditions finish the loop */ return statement; }
void compileFuncDecl(void) { Object* funcObj; Type* returnType; eat(KW_FUNCTION); eat(TK_IDENT); // TODO: Check if a function identifier is fresh in the block checkFreshIdent(currentToken->string); // create the function object funcObj = createFunctionObject(currentToken->string); // declare the function object declareObject(funcObj); // enter the function's block enterBlock(funcObj->funcAttrs->scope); // parse the function's parameters compileParams(); eat(SB_COLON); // get the funtion's return type returnType = compileBasicType(); funcObj->funcAttrs->returnType = returnType; eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); // exit the function block exitBlock(); }
void compileProgram(void) { // TODO: create, enter, and exit program block# Object * obj = NULL; eat(KW_PROGRAM); eat(TK_IDENT); obj = createProgramObject(currentToken->string); eat(SB_SEMICOLON); enterBlock(obj->progAttrs->scope); compileBlock(); exitBlock(); eat(SB_PERIOD); }
void initSymTab(void) { Object* param; symtab = (SymTab*) malloc(sizeof(SymTab)); symtab->globalObjectList = NULL; symtab->program = NULL; symtab->currentScope = NULL; readcFunction = createFunctionObject("READC"); declareObject(readcFunction); readcFunction->funcAttrs->returnType = makeCharType(); readiFunction = createFunctionObject("READI"); declareObject(readiFunction); readiFunction->funcAttrs->returnType = makeIntType(); writeiProcedure = createProcedureObject("WRITEI"); declareObject(writeiProcedure); enterBlock(writeiProcedure->procAttrs->scope); param = createParameterObject("i", PARAM_VALUE); param->paramAttrs->type = makeIntType(); declareObject(param); exitBlock(); writecProcedure = createProcedureObject("WRITEC"); declareObject(writecProcedure); enterBlock(writecProcedure->procAttrs->scope); param = createParameterObject("ch", PARAM_VALUE); param->paramAttrs->type = makeCharType(); declareObject(param); exitBlock(); writelnProcedure = createProcedureObject("WRITELN"); declareObject(writelnProcedure); intType = makeIntType(); charType = makeCharType(); }
void TypeCompiler::block(CodeState *cs, Statement *fstat) { FuncState *fs = cs->fs; BlockCnt bl; enterBlock(fs, &bl, 0); // was chunk BC::lineNumber = fstat->lineNumber; fstat->visitStatement(this); lmAssert(bl.breaklist == NO_JUMP, "Internal Compiler Error"); leaveBlock(fs); }
void compileProcDecl(void) { // TODO: create and declare a procedure object// Object* obj=NULL; eat(KW_PROCEDURE); eat(TK_IDENT); obj = createProcedureObject(currentToken->string); enterBlock(obj->procAttrs->scope); compileParams(); eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); exitBlock(); declareObject(obj); }
void compileProgram(void) { Object* program; eat(KW_PROGRAM); eat(TK_IDENT); program = createProgramObject(currentToken->string); enterBlock(program->progAttrs->scope); eat(SB_SEMICOLON); compileBlock(); eat(SB_PERIOD); exitBlock(); }
Statement *TypeCompiler::visit(SwitchStatement *statement) { FuncState *fs = cs->fs; BlockCnt bl; enterBlock(fs, &bl, 1); ExpDesc swv; statement->expression->visitExpression(this); swv = statement->expression->e; ExpDesc swexpr; BC::singleVar(cs, &swexpr, "__ls_swexpr"); BC::expToNextReg(fs, &swv); BC::storeVar(fs, &swexpr, &swv); /* switch case fallthrough */ ExpDesc swft; BC::singleVar(cs, &swft, "__ls_swft"); BC::initExpDesc(&swv, VFALSE, 0); BC::expToNextReg(fs, &swv); BC::storeVar(fs, &swft, &swv); cs->fs->freereg = cs->fs->nactvar; /* free registers */ if (statement->clauses) { for (unsigned int i = 0; i < statement->clauses->size(); i++) { CaseStatement *cst = statement->clauses->at(i); cst->visitStatement(this); } } leaveBlock(fs); return statement; }
void compileProgram(void) { Object* program; eat(KW_PROGRAM); eat(TK_IDENT); program = createProgramObject(currentToken->string); program->progAttrs->codeAddress = getCurrentCodeAddress(); enterBlock(program->progAttrs->scope); eat(SB_SEMICOLON); compileBlock(); eat(SB_PERIOD); // Halt the program genHL(); exitBlock(); }
void compileProcDecl(void) { Object* procObj; eat(KW_PROCEDURE); eat(TK_IDENT); checkFreshIdent(currentToken->string); procObj = createProcedureObject(currentToken->string); declareObject(procObj); enterBlock(procObj->procAttrs->scope); compileParams(); eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); exitBlock(); }
void compileFuncDecl(void) { // TODO: create and declare a function object# Object* obj=NULL; eat(KW_FUNCTION); eat(TK_IDENT); obj = createFunctionObject(currentToken->string); enterBlock(obj->funcAttrs->scope); compileParams(); eat(SB_COLON); obj->funcAttrs->returnType = compileBasicType(); eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); exitBlock(); declareObject(obj); }
void compileProcDecl(void) { Object* procObj; eat(KW_PROCEDURE); eat(TK_IDENT); // TODO: Check if a procedure identifier is fresh in the block checkFreshIdent(currentToken->string); // create a procedure object procObj = createProcedureObject(currentToken->string); // declare the procedure object declareObject(procObj); // enter the procedure's block enterBlock(procObj->procAttrs->scope); // parse the procedure's parameters compileParams(); eat(SB_SEMICOLON); compileBlock(); eat(SB_SEMICOLON); // exit the block exitBlock(); }
Statement *TypeCompiler::visit(WhileStatement *statement) { FuncState *fs = cs->fs; int whileinit; int condexit; BlockCnt bl; whileinit = BC::getLabel(fs); statement->expression->visitExpression(this); condexit = BC::cond(cs, &statement->expression->e); enterBlock(fs, &bl, 1); block(cs, statement->statement); BC::patchToHere(fs, bl.continuelist); BC::patchList(fs, BC::jump(fs), whileinit); leaveBlock(fs); BC::patchToHere(fs, condexit); /* false conditions finish the loop */ return statement; }
Statement *TypeCompiler::visit(ForStatement *statement) { FuncState *fs = cs->fs; int whileinit; int condexit; BlockCnt bl; /* initial */ if (statement->initial) { statement->initial->visitExpression(this); } whileinit = BC::getLabel(fs); /* condition */ if (statement->condition) { statement->condition->visitExpression(this); } else { lmAssert(0, "for statement has no condition"); } condexit = BC::cond(cs, &statement->condition->e); /* wrap as a statement */ /* this is the pc of any continue statement in the block */ ExpressionStatement *es = NULL; if (statement->increment) /*increment*/ { /* FIXME: this should be done at parse time */ es = new ExpressionStatement(statement->increment); } enterBlock(fs, &bl, 1); /* statements*/ statement->statement->visitStatement(this); if (es) { BC::patchToHere(fs, bl.continuelist); es->visitStatement(this); es->expression = NULL; delete es; es = NULL; } lua_assert(bl.breaklist == NO_JUMP); BC::patchList(fs, BC::jump(fs), whileinit); leaveBlock(fs); BC::patchToHere(fs, condexit); /* false conditions finish the loop */ return statement; }
Statement *TypeCompiler::visit(ForInStatement *statement) { FuncState *fs = cs->fs; int nvars = 0; int line; char forIteratorName[256]; // save off the previous iterator const char *prevForInIteratorName = currentForInIteratorName; // initially null, unless we need to use it due to // iterating with a variable external to block currentForInIteratorName = NULL; forIteratorName[0] = 0; const char *vname = NULL; ExpDesc v; ExpDesc fv; if (statement->variable->astType == AST_VARDECL) { VariableDeclaration *vd = (VariableDeclaration *)statement->variable; vname = vd->identifier->string.c_str(); } else if (statement->variable->astType == AST_IDENTIFIER) { vname = ((Identifier *)statement->variable)->string.c_str(); // a little sanity lmAssert(strlen(vname) < 240, "For..In variable name > 240 characters"); // we are using an external variable as the iterator for the loop // this means that we'll have to do a quick store to it when exiting the // loop (also via break) sprintf(forIteratorName, "__ls_%s", vname); currentForInIteratorName = forIteratorName; BC::newLocalVar(cs, forIteratorName, 0); BC::reserveRegs(fs, 1); BC::adjustLocalVars(cs, 1); } else { lmAssert(0, "Unknown variable statement in for..in initializer"); } BlockCnt forbl; enterBlock(fs, &forbl, 1); /* scope for loop and control variables */ int base = fs->freereg; /* create control variables */ BC::newLocalVar(cs, "(for generator)", nvars++); BC::newLocalVar(cs, "(for state)", nvars++); BC::newLocalVar(cs, "(for control)", nvars++); //TODO: It would be nice to have a way to iterate pairs if (statement->foreach) { BC::newLocalVar(cs, "__ls_key", nvars++); } /* create declared variables */ BC::newLocalVar(cs, vname, nvars++); line = lineNumber; bool isVector = false; if (statement->expression->type->getFullName() == "system.Vector") { isVector = true; } ExpDesc pairs; if (isVector) { BC::singleVar(cs, &pairs, "__lua_ipairs"); } else { BC::singleVar(cs, &pairs, "__lua_pairs"); } BC::expToNextReg(fs, &pairs); ExpDesc arg; int cbase = pairs.u.s.info; /* base register for call */ statement->expression->visitExpression(this); arg = statement->expression->e; ExpDesc right; if (isVector) { // we pass the instance itself } else { BC::initExpDesc(&right, VKNUM, 0); right.u.nval = LSINDEXDICTPAIRS; BC::expToNextReg(fs, &arg); BC::expToNextReg(fs, &right); BC::expToVal(fs, &right); BC::indexed(fs, &arg, &right); } BC::setMultRet(fs, &arg); int nparams = 0; if (hasmultret(arg.k)) { nparams = LUA_MULTRET; /* open call */ } else { if (arg.k != VVOID) { BC::expToNextReg(fs, &arg); /* close last argument */ } nparams = fs->freereg - (cbase + 1); } BC::initExpDesc(&pairs, VCALL, BC::codeABC(fs, OP_CALL, cbase, nparams + 1, 2 /* returns 1 values */)); fs->freereg = cbase + 1; /* call remove function and arguments and leaves*/ BC::adjustAssign(cs, 3, 1, &pairs); BC::checkStack(fs, 3); /* extra space to call generator */ /* forbody -> DO block */ BlockCnt bl; int prep, endfor; BC::adjustLocalVars(cs, 3); /* control variables */ prep = BC::jump(fs); enterBlock(fs, &bl, 0); /* scope for declared variables */ BC::adjustLocalVars(cs, nvars - 3); BC::reserveRegs(fs, nvars - 3); block(cs, statement->statement); if (forIteratorName[0]) { // we need to store BC::singleVar(cs, &v, vname); BC::singleVar(cs, &fv, forIteratorName); BC::storeVar(fs, &fv, &v); } leaveBlock(fs); /* end of scope for declared variables */ BC::patchToHere(fs, prep); BC::patchToHere(fs, forbl.continuelist); /* patch in continue list for for .. in/ for .. each */ endfor = BC::codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3); BC::fixLine(fs, line); /* pretend that `OP_FOR' starts the loop */ BC::patchList(fs, BC::jump(fs), prep + 1); leaveBlock(fs); if (forIteratorName[0]) { // we need to store to this block's var BC::singleVar(cs, &v, vname); BC::singleVar(cs, &fv, forIteratorName); BC::storeVar(fs, &v, &fv); } currentForInIteratorName = prevForInIteratorName; return statement; }
Statement *TypeCompiler::visit(CaseStatement *statement) { FuncState *fs = cs->fs; int flist; int escapelist = NO_JUMP; ExpDesc swft; ExpDesc cexpr; if (statement->expression) { /* outer || switch fallthrough */ BinOpr ftop = OPR_OR; BC::singleVar(cs, &swft, "__ls_swft"); BC::infix(fs, ftop, &swft); /* inner caseexpr == swexpr */ BinOpr op = OPR_EQ; statement->expression->visitExpression(this); cexpr = statement->expression->e; BC::infix(fs, op, &cexpr); ExpDesc swexpr; BC::singleVar(cs, &swexpr, "__ls_swexpr"); BC::posFix(cs->fs, op, &cexpr, &swexpr); BC::posFix(cs->fs, ftop, &swft, &cexpr); if (cexpr.k == VNIL) { cexpr.k = VFALSE; /* `falses' are all equal here */ } BC::goIfTrue(fs, &cexpr); flist = cexpr.f; } else { BC::initExpDesc(&cexpr, VTRUE, 0); BC::goIfTrue(fs, &cexpr); flist = cexpr.f; } /*true block*/ ExpDesc swv; BC::singleVar(cs, &swft, "__ls_swft"); BC::initExpDesc(&swv, VTRUE, 0); BC::expToNextReg(fs, &swv); BC::storeVar(fs, &swft, &swv); BlockCnt bl; enterBlock(fs, &bl, 0); chunk(statement->statements); lua_assert(bl.breaklist == NO_JUMP); leaveBlock(fs); BC::concat(fs, &escapelist, flist); BC::patchToHere(fs, escapelist); cs->fs->freereg = cs->fs->nactvar; /* free registers */ return statement; }
int main() { Object* obj; initSymTab(); obj = createProgramObject("PRG"); enterBlock(obj->progAttrs->scope); obj = createConstantObject("c1"); obj->constAttrs->value = makeIntConstant(10); declareObject(obj); obj = createConstantObject("c2"); obj->constAttrs->value = makeCharConstant('a'); declareObject(obj); obj = createTypeObject("t1"); obj->typeAttrs->actualType = makeArrayType(10, makeIntType()); declareObject(obj); obj = createVariableObject("v1"); obj->varAttrs->type = makeIntType(); declareObject(obj); obj = createVariableObject("v2"); obj->varAttrs->type = makeArrayType(10, makeArrayType(10, makeIntType())); declareObject(obj); obj = createFunctionObject("f"); obj->funcAttrs->returnType = makeIntType(); declareObject(obj); enterBlock(obj->funcAttrs->scope); obj = createParameterObject("p1", PARAM_VALUE, symtab->currentScope->owner); obj->paramAttrs->type = makeIntType(); declareObject(obj); obj = createParameterObject("p2", PARAM_REFERENCE, symtab->currentScope->owner); obj->paramAttrs->type = makeCharType(); declareObject(obj); exitBlock(); obj = createProcedureObject("p"); declareObject(obj); enterBlock(obj->procAttrs->scope); obj = createParameterObject("v1", PARAM_VALUE, symtab->currentScope->owner); obj->paramAttrs->type = makeIntType(); declareObject(obj); obj = createConstantObject("c1"); obj->constAttrs->value = makeCharConstant('a'); declareObject(obj); obj = createConstantObject("c3"); obj->constAttrs->value = makeIntConstant(10); declareObject(obj); obj = createTypeObject("t1"); obj->typeAttrs->actualType = makeIntType(); declareObject(obj); obj = createTypeObject("t2"); obj->typeAttrs->actualType = makeArrayType(10, makeIntType()); declareObject(obj); obj = createVariableObject("v2"); obj->varAttrs->type = makeArrayType(10, makeIntType()); declareObject(obj); obj = createVariableObject("v3"); obj->varAttrs->type = makeCharType(); declareObject(obj); exitBlock(); exitBlock(); printObject(symtab->program, 0); cleanSymTab(); return 0; }