void OverlapConstruct::generateCode(XStr& decls, XStr& defs, Entry* entry) { sprintf(nameStr,"%s%s", CParsedFile::className->charstar(),label->charstar()); generateClosureSignature(decls, defs, entry, false, "void", label, false, encapState); #if CMK_BIGSIM_CHARM generateBeginTime(defs); generateEventBracket(defs, SOVERLAP); #endif defs << " "; generateCall(defs, encapStateChild, encapStateChild, constructs->front()->label); endMethod(defs); // trace sprintf(nameStr,"%s%s", CParsedFile::className->charstar(),label->charstar()); strcat(nameStr,"_end"); generateClosureSignature(decls, defs, entry, false, "void", label, true, encapStateChild); #if CMK_BIGSIM_CHARM generateBeginTime(defs); generateEventBracket(defs, SOVERLAP_END); #endif defs << " "; generateCall(defs, encapState, encapState, next->label, nextBeginOrEnd ? 0 : "_end"); endMethod(defs); generateChildrenCode(decls, defs, entry); }
Expression *TypeCompiler::visit(CallExpression *call) { MethodBase *methodBase = call->methodBase; call->function->visitExpression(this); // check whether we're calling a methodbase if (methodBase) { lmAssert(methodBase->isMethod(), "Non-method called"); MethodInfo *method = (MethodInfo *)methodBase; generateCall(&call->function->e, call->arguments, method); call->e = call->function->e; } else { lmAssert(call->function->type, "Untyped call"); // if we're calling a delegate we need to load up the call method if (call->function->type->isDelegate()) { MethodInfo *method = (MethodInfo *)call->function->type->findMember("call"); lmAssert(method, "delegate with no call method"); ExpDesc right; BC::initExpDesc(&right, VKNUM, 0); right.u.nval = method->getOrdinal(); BC::expToNextReg(cs->fs, &call->function->e); BC::expToNextReg(cs->fs, &right); BC::expToVal(cs->fs, &right); BC::indexed(cs->fs, &call->function->e, &right); generateCall(&call->function->e, call->arguments, NULL); call->e = call->function->e; } else { // we're directly calling a local, instance (bound), or static method of type Function generateCall(&call->function->e, call->arguments, NULL); call->e = call->function->e; } } return call; }
Expression *TypeCompiler::visit(SuperExpression *expression) { lmAssert(currentMethod, "super outside of method"); Type *type = currentMethod->getDeclaringType(); Type *baseType = type->getBaseType(); //FIXME: issue a warning if (!baseType) { return expression; } FuncState *fs = cs->fs; if (currentMethod->isConstructor()) { ConstructorInfo *base = baseType->getConstructor(); //FIXME: warn if no base constructor if (!base) { return expression; } // load up base class ExpDesc eclass; BC::singleVar(cs, &eclass, baseType->getFullName().c_str()); // index with the __ls_constructor BC::expToNextReg(fs, &eclass); ExpDesc fname; BC::expString(cs, &fname, "__ls_constructor"); BC::expToNextReg(fs, &fname); BC::expToVal(fs, &fname); BC::indexed(fs, &eclass, &fname); // call the LSMethod generateCall(&eclass, &expression->arguments); } else { utString name = currentMethod->getName(); if (expression->method) { name = expression->method->string; } MemberInfo *mi = baseType->findMember(name.c_str()); //FIXME: warn if (!mi) { return expression; } lmAssert(mi->isMethod(), "Non-method in super call"); MethodInfo *methodInfo = (MethodInfo *)mi; // load up declaring class ExpDesc eclass; BC::singleVar(cs, &eclass, methodInfo->getDeclaringType()->getFullName().c_str()); BC::expToNextReg(fs, &eclass); ExpDesc fname; BC::expString(cs, &fname, name.c_str()); BC::expToNextReg(fs, &fname); BC::expToVal(fs, &fname); BC::indexed(fs, &eclass, &fname); // call the LSMethod generateCall(&eclass, &expression->arguments); expression->e = eclass; } return expression; }
// TODO: Unify this with the JIT bc generator binary expressions // https://theengineco.atlassian.net/browse/LOOM-640 // https://theengineco.atlassian.net/browse/LOOM-641 Expression *TypeCompiler::visit(BinaryOperatorExpression *expression) { Tokens *tok = Tokens::getSingletonPtr(); Expression *eleft = expression->leftExpression; Expression *eright = expression->rightExpression; // operator overloads lmAssert(eleft->type && eright->type, "Untyped binary expression"); const char *opmethod = tok->getOperatorMethodName(expression->op); if (opmethod) { MemberInfo *mi = eleft->type->findMember(opmethod); if (mi) { lmAssert(mi->isMethod(), "Non-method operator"); MethodInfo *method = (MethodInfo *)mi; lmAssert(method->isOperator(), "Non-operator method"); utArray<Expression *> args; args.push_back(eleft); args.push_back(eright); ExpDesc opcall; ExpDesc emethod; BC::singleVar(cs, &opcall, eleft->type->getName()); BC::expString(cs, &emethod, method->getName()); BC::expToNextReg(cs->fs, &opcall); BC::expToNextReg(cs->fs, &emethod); BC::expToVal(cs->fs, &emethod); BC::indexed(cs->fs, &opcall, &emethod); generateCall(&opcall, &args, method); expression->e = opcall; return expression; } } // dynamic cast if ((expression->op == &tok->KEYWORD_IS) || (expression->op == &tok->KEYWORD_INSTANCEOF) || (expression->op == &tok->KEYWORD_AS)) { lmAssert(eleft->type && eright->type, "Untype expression"); FuncState *fs = cs->fs; ExpDesc object; BC::singleVar(cs, &object, "Object"); ExpDesc method; if (expression->op == &tok->KEYWORD_IS) { BC::expString(cs, &method, "_is"); } else if (expression->op == &tok->KEYWORD_AS) { BC::expString(cs, &method, "_as"); } else { BC::expString(cs, &method, "_instanceof"); } BC::expToNextReg(fs, &object); BC::expToNextReg(fs, &method); BC::expToVal(fs, &method); BC::indexed(fs, &object, &method); utArray<Expression *> args; args.push_back(eleft); args.push_back(new StringLiteral(eright->type->getAssembly()->getName().c_str())); args.push_back(new NumberLiteral(eright->type->getTypeID())); generateCall(&object, &args); expression->e = object; return expression; } BinOpr op = getbinopr(expression->op); if (op == OPR_LOOM_ADD) { lmAssert(eleft->type && eright->type, "Untyped add operaton %i", lineNumber); int ncheck = 0; if (eleft->type->isEnum() || (eleft->type->getFullName() == "system.Number")) { ncheck++; } if (eright->type->isEnum() || (eright->type->getFullName() == "system.Number")) { ncheck++; } if (ncheck != 2) { op = OPR_CONCAT; } } // If we're concat'ing arbitrary types with a string, we need to coerce them // to strings with Object._toString otherwise the Lua VM will error when // it can't concat (which has strict rules, for instance cannot concat nil) if ((op == OPR_CONCAT) && ((eleft->type->getFullName() == "system.String") || (eright->type->getFullName() == "system.String"))) { // coerce left to string, must be done even for string types as they may be null coerceToString(eleft); BC::infix(cs->fs, op, &eleft->e); // coerce right to string, must be done even for string types as they may be null coerceToString(eright); // and the binary op BC::posFix(cs->fs, op, &eleft->e, &eright->e); // save off expression and return expression->e = eleft->e; return expression; } eleft->visitExpression(this); BC::infix(cs->fs, op, &eleft->e); eright->visitExpression(this); BC::posFix(cs->fs, op, &eleft->e, &eright->e); expression->e = eleft->e; // promote to register BC::expToNextReg(cs->fs, &expression->e); return expression; }
Expression *TypeCompiler::visit(AssignmentOperatorExpression *expression) { Tokens *tok = Tokens::getSingletonPtr(); BinOpr op = getassignmentopr(expression->type); lmAssert(op != OPR_NOBINOPR, "Unknown bin op on AssignentOperatorExpression"); Expression *eleft = expression->leftExpression; Expression *eright = expression->rightExpression; lmAssert(eleft->type, "Untyped error on left expression"); const char *opmethod = tok->getOperatorMethodName(expression->type); if (opmethod) { MemberInfo *mi = eleft->type->findMember(opmethod); if (mi) { lmAssert(mi->isMethod(), "Non-method operator"); MethodInfo *method = (MethodInfo *)mi; lmAssert(method->isOperator(), "Non-operator method"); utArray<Expression *> args; args.push_back(eright); ExpDesc opcall; ExpDesc emethod; eleft->visitExpression(this); opcall = eleft->e; BC::initExpDesc(&emethod, VKNUM, 0); emethod.u.nval = method->getOrdinal(); BC::expToNextReg(cs->fs, &opcall); BC::expToNextReg(cs->fs, &emethod); BC::expToVal(cs->fs, &emethod); BC::indexed(cs->fs, &opcall, &emethod); generateCall(&opcall, &args, method); expression->e = opcall; return expression; } } eleft->assignment = false; eleft->visitExpression(this); BC::infix(cs->fs, op, &eleft->e); eright->visitExpression(this); BC::expToNextReg(cs->fs, &eright->e); BC::posFix(cs->fs, op, &eleft->e, &eright->e); ExpDesc right = eleft->e; BC::expToNextReg(cs->fs, &right); memset(&eleft->e, 0, sizeof(ExpDesc)); eleft->assignment = true; eleft->visitExpression(this); ExpDesc left = eleft->e; if (eleft->memberInfo && eleft->memberInfo->isProperty()) { eright->e = right; generatePropertySet(&eleft->e, eright, false); } else { BC::storeVar(cs->fs, &left, &right); } return expression; }