Beispiel #1
0
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();
}
Beispiel #3
0
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();
}
Beispiel #7
0
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();
}
Beispiel #10
0
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;
}
Beispiel #11
0
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();
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
}