Expr* parse(std::vector<std::pair<calc::tType,char>> &vTok) { auto i = vTok.begin(); std::stack<tType> operStack; std::stack<Expr> ExprStack; while(i!=vTok.end()) { switch (i->first) { case LPAREN: operStack.push(i->first); break; case NUM: ExprStack.push(calc::Num((int)i->second)); break; case PLUS: while(precedence(operStack.top())>=precedence(PLUS)) { auto o = operStack.top(); operStack.pop(); Expr r = ExprStack.top(); ExprStack.pop(); Expr l = ExprStack.top(); ExprStack.pop(); ExprStack.push(pushType(o,&l,&r)); } operStack.push(i->first); break; case RPAREN: while(operStack.top() != LPAREN) { auto o = operStack.top(); operStack.pop(); Expr r = ExprStack.top(); ExprStack.pop(); Expr l = ExprStack.top(); ExprStack.pop(); ExprStack.push(pushType(o,&l,&r)); } operStack.push(i->first); break; default: break; } i++; } return &ExprStack.top(); }
void BytecodeTranslatorVisitor::visitLoadNode(LoadNode* node) { onVisitNode(node); EMIT_LOAD(node->var()); pushType(node->var()->type()); }
void BytecodeTranslatorVisitor::visitForNode(ForNode* node) { onVisitNode(node); const AstVar* i = node->var(); if (i->type() != VT_INT) ERROR("Non-iterable type in for loop"); const BinaryOpNode* expr = node->inExpr()->asBinaryOpNode(); if (expr == NULL || expr->kind() != tRANGE) ERROR("Invalid range in for loop"); CONTEXT(function(), locals(), node->body()->scope(), typeStack()); beforeProcessBlock(); bool needTempVar = !expr->right()->isIntLiteralNode(); AstVar* temp = NULL; if (needTempVar) { if (!scope()->declareVariable("<tempForEnd>", VT_INT)) ERROR("internal error: temp name is unavailable"); temp = scope()->lookupVariable("<tempForEnd>", false); } Label L_Begin(bytecode()); Label L_End(bytecode()); VISIT(expr->left()); EMIT_STORE(i); if (needTempVar) { VISIT(expr->right()); EMIT_STORE(temp); popType(VT_INT); } popType(VT_INT); EMIT_BIND(L_Begin); if (needTempVar) EMIT_LOAD(temp); else VISIT(expr->right()); EMIT_LOAD(i); EMIT_BRANCH(BC_IFICMPG, L_End); processBlockNode(node->body()); afterProcessBlock(); /* i += 1 */ EMIT_LOAD(i); EMIT(BC_ILOAD1); EMIT(BC_IADD); EMIT_STORE(i); EMIT_BRANCH(BC_JA, L_Begin); EMIT_BIND(L_End); pushType(VT_VOID); }
void BytecodeTranslatorVisitor::castTopsToCommonType() { VarType hi = popType(); VarType lo = popType(); if (hi != lo) { if (hi == VT_DOUBLE) { EMIT(BC_SWAP); EMIT(BC_I2D); EMIT(BC_SWAP); } else { EMIT(BC_I2D); } hi = VT_DOUBLE; } pushType(hi); pushType(hi); }
void BytecodeTranslatorVisitor::visitBlockNode(BlockNode* node) { onVisitNode(node); CONTEXT(function(), locals(), node->scope(), typeStack()); beforeProcessBlock(); processBlockNode(node); afterProcessBlock(); pushType(VT_VOID); }
void BytecodeTranslatorVisitor::visitStringLiteralNode(StringLiteralNode * node) { onVisitNode(node); if (node->literal().empty()) EMIT(BC_SLOAD0); else { EMIT(BC_SLOAD); EMIT_ID(code()->makeStringConstant(node->literal())); } pushType(VT_STRING); }
void BytecodeTranslatorVisitor::visitReturnNode(ReturnNode* node) { onVisitNode(node); if (node->returnExpr() != NULL) visitTyped(node->returnExpr(), function()->returnType()); else if (function()->returnType() != VT_VOID) ERROR("Missing return statement"); EMIT(BC_RETURN); ensureTypeStackEmpty(); pushType(function()->returnType()); }
void BytecodeTranslatorVisitor::visitStoreNode(StoreNode* node) { onVisitNode(node); visitTyped(node->value(), node->var()->type()); pushType(node->var()->type()); if (node->op() == tINCRSET || node->op() == tDECRSET) { ensureTopIsNumeric(); EMIT_LOAD(node->var()); if (node->op() == tINCRSET) EMIT(TYPED(ADD)); else EMIT(TYPED(SUB)); } else if (node->op() != tASSIGN) ERROR("Invalid store operation"); EMIT_STORE(node->var()); popType(); pushType(VT_VOID); /* a = b = c is forbidden */ }
void BytecodeTranslatorVisitor::visitIntLiteralNode(IntLiteralNode* node) { onVisitNode(node); switch (node->literal()) { case -1: EMIT(BC_ILOADM1); break; case 0: EMIT(BC_ILOAD0); break; case 1: EMIT(BC_ILOAD1); break; default: EMIT(BC_ILOAD); EMIT_INT(node->literal()); break; } pushType(VT_INT); }
void BytecodeTranslatorVisitor::visitDoubleLiteralNode(DoubleLiteralNode* node) { onVisitNode(node); const double value = node->literal(); if (doubleEquals(value, -1.0)) EMIT(BC_DLOADM1); else if (doubleEquals(value, 0.0)) EMIT(BC_DLOAD0); else if (doubleEquals(value, 1.0)) EMIT(BC_DLOAD1); else { EMIT(BC_DLOAD); EMIT_DOUBLE(value); } pushType(VT_DOUBLE); }
void BytecodeTranslatorVisitor::visitPrintNode(PrintNode * node) { onVisitNode(node); for (uint32_t i = 0; i < node->operands(); ++i) { VISIT(node->operandAt(i)); switch (topType()) { case VT_INT: EMIT(BC_IPRINT); break; case VT_DOUBLE: EMIT(BC_DPRINT); break; case VT_STRING: EMIT(BC_SPRINT); break; default: ERROR("Unprintable parameter"); } popType(); } pushType(VT_VOID); }
void BytecodeTranslatorVisitor::tryCast(VarType to) { static Instruction castTable[VAR_TYPES_NUMBER][VAR_TYPES_NUMBER] = {BC_INVALID}; castTable[VT_INT][VT_DOUBLE] = BC_I2D; castTable[VT_DOUBLE][VT_INT] = BC_D2I; VarType from = topType(); if (from == to) return; Instruction cast = castTable[from][to]; if (!cast) ERROR(string("Cast error from ") + typeToName(from) + " to " + typeToName(to)); warningIf(cast == BC_D2I, "Casting double to int. I warned you!"); EMIT(cast); popType(); pushType(to); }
void BytecodeTranslatorVisitor::visitCallNode(CallNode* node) { onVisitNode(node); AstFunction* f = scope()->lookupFunction(node->name()); if (!f) ERROR("Unknown function " + f->name()); checkSignature(node, f); for (uint16_t i = 0; i < node->parametersNumber(); i++) visitTyped(node->parameterAt(i), f->parameterType(i)); if (isNative(f)) EMIT(BC_CALLNATIVE); else EMIT(BC_CALL); EMIT_ID(getFunctionId(f)); pushType(f->returnType()); }
void BytecodeTranslatorVisitor::processComparison(TokenKind kind) { castTopsToCommonType(); Instruction cmp = TYPED(CMP); int hack = topType() == VT_INT ? 3 : 0; popType(); popType(); pushType(VT_INT); if (kind == tNEQ) { EMIT(cmp); return; } if (!hack) { EMIT(cmp); EMIT(BC_ILOAD0); } Label L_Fail(bytecode()); Label L_End(bytecode()); switch (kind) { case tEQ: EMIT_BRANCH(BC_IFICMPE, L_Fail); break; case tGT: EMIT_BRANCH(BC_IFICMPG, L_Fail); break; case tGE: EMIT_BRANCH(BC_IFICMPGE, L_Fail); break; case tLT: EMIT_BRANCH(BC_IFICMPL, L_Fail); break; default : EMIT_BRANCH(BC_IFICMPLE, L_Fail); break; } EMIT(BC_ILOAD1 - hack); EMIT_BRANCH(BC_JA, L_End); EMIT_BIND(L_Fail); EMIT(BC_ILOAD0 + hack); EMIT_BIND(L_End); }
/* * The generic solution to the multiplex operators is to translate * them to a MAL loop. * The call optimizer.multiplex(MOD,FCN,A1,...An) introduces the following code * structure: * * resB:= bat.new(A1); * barrier (h,t1):= iterator.new(A1); * t2:= algebra.fetch(A2,h) * ... * cr:= MOD.FCN(t1,...,tn); * bat.append(resB,cr); * redo (h,t):= iterator.next(A1); * end h; * * The algorithm consists of two phases: phase one deals with * collecting the relevant information, phase two is the actual * code construction. */ static str OPTexpandMultiplex(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i = 2, iter = 0; int hvar, tvar; str mod, fcn; int *alias, *resB; InstrPtr q; int tt; int bat = (getModuleId(pci) == batmalRef) ; //if ( optimizerIsApplied(mb,"multiplex")) //return 0; (void) cntxt; (void) stk; for (i = 0; i < pci->retc; i++) { tt = getBatType(getArgType(mb, pci, i)); if (tt== TYPE_any) throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Target tail type is missing"); if (isAnyExpression(getArgType(mb, pci, i))) throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Target type is missing"); } mod = VALget(&getVar(mb, getArg(pci, pci->retc))->value); mod = putName(mod); fcn = VALget(&getVar(mb, getArg(pci, pci->retc+1))->value); fcn = putName(fcn); if(mod == NULL || fcn == NULL) throw(MAL, "optimizer.multiplex", SQLSTATE(HY001) MAL_MALLOC_FAIL); #ifndef NDEBUG fprintf(stderr,"#WARNING To speedup %s.%s a bulk operator implementation is needed\n#", mod,fcn); fprintInstruction(stderr, mb, stk, pci, LIST_MAL_DEBUG); #endif /* search the iterator bat */ for (i = pci->retc+2; i < pci->argc; i++) if (isaBatType(getArgType(mb, pci, i))) { iter = getArg(pci, i); break; } if( i == pci->argc) throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Iterator BAT type is missing"); #ifdef DEBUG_OPT_MULTIPLEX { char *tpenme; fprintf(stderr,"#calling the optimize multiplex script routine\n"); fprintFunction(stderr,mb, 0, LIST_MAL_ALL ); tpenme = getTypeName(getVarType(mb,iter)); fprintf(stderr,"#multiplex against operator %d %s\n",iter, tpenme); GDKfree(tpenme); fprintInstruction(stderr,mb, 0, pci,LIST_MAL_ALL); } #endif /* * Beware, the operator constant (arg=1) is passed along as well, * because in the end we issue a recursive function call that should * find the actual arguments at the proper place of the callee. */ alias= (int*) GDKmalloc(sizeof(int) * pci->maxarg); resB = (int*) GDKmalloc(sizeof(int) * pci->retc); if (alias == NULL || resB == NULL) { GDKfree(alias); GDKfree(resB); return NULL; } /* resB := new(refBat) */ for (i = 0; i < pci->retc; i++) { q = newFcnCall(mb, batRef, newRef); resB[i] = getArg(q, 0); tt = getBatType(getArgType(mb, pci, i)); setVarType(mb, getArg(q, 0), newBatType(tt)); q = pushType(mb, q, tt); } /* barrier (h,r) := iterator.new(refBat); */ q = newFcnCall(mb, iteratorRef, newRef); q->barrier = BARRIERsymbol; hvar = newTmpVariable(mb, TYPE_any); getArg(q,0) = hvar; tvar = newTmpVariable(mb, TYPE_any); q= pushReturn(mb, q, tvar); (void) pushArgument(mb,q,iter); /* $1:= algebra.fetch(Ai,h) or constant */ for (i = pci->retc+2; i < pci->argc; i++) { if (getArg(pci, i) != iter && isaBatType(getArgType(mb, pci, i))) { q = newFcnCall(mb, algebraRef, "fetch"); alias[i] = newTmpVariable(mb, getBatType(getArgType(mb, pci, i))); getArg(q, 0) = alias[i]; q= pushArgument(mb, q, getArg(pci, i)); (void) pushArgument(mb, q, hvar); } } /* cr:= mod.CMD($1,...,$n); */ q = newFcnCall(mb, mod, fcn); for (i = 0; i < pci->retc; i++) { int nvar = 0; if (bat) { tt = getBatType(getArgType(mb, pci, i)); nvar = newTmpVariable(mb, newBatType(tt)); } else { nvar = newTmpVariable(mb, TYPE_any); } if (i) q = pushReturn(mb, q, nvar); else getArg(q, 0) = nvar; } for (i = pci->retc+2; i < pci->argc; i++) { if (getArg(pci, i) == iter) { q = pushArgument(mb, q, tvar); } else if (isaBatType(getArgType(mb, pci, i))) { q = pushArgument(mb, q, alias[i]); } else { q = pushArgument(mb, q, getArg(pci, i)); } } for (i = 0; i < pci->retc; i++) { InstrPtr a = newFcnCall(mb, batRef, appendRef); a = pushArgument(mb, a, resB[i]); (void) pushArgument(mb, a, getArg(q,i)); } /* redo (h,r):= iterator.next(refBat); */ q = newFcnCall(mb, iteratorRef, nextRef); q->barrier = REDOsymbol; getArg(q,0) = hvar; q= pushReturn(mb, q, tvar); (void) pushArgument(mb,q,iter); q = newAssignment(mb); q->barrier = EXITsymbol; getArg(q,0) = hvar; (void) pushReturn(mb, q, tvar); for (i = 0; i < pci->retc; i++) { q = newAssignment(mb); getArg(q, 0) = getArg(pci, i); (void) pushArgument(mb, q, resB[i]); } GDKfree(alias); GDKfree(resB); return MAL_SUCCEED; }
bool run(ASTNode* mainNode, RuntimeError* error, ExternalFunctions externals, char** libsToLoad, int libsCount) { assert(mainNode->nodeType == AST_MAIN); getValueFunc = getGetValueFuncPtr(); MemoryStack stack = makeMemoryStack(MEGABYTE(16)); Array<HINSTANCE> libraries = makeArray<HINSTANCE>(KILOBYTE(1)); Scope scalarTypesScope = makeScope(nullptr); Scope globalScope = makeScope(&scalarTypesScope); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("f64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("f32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s16"), {}, 2 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u16"), {}, 2 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s8"), {}, 1 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u8"), {}, 1 }); ExternalArgumentDefinition binarys32Args[] = { { "a", "s32" }, { "b", "s32" } }; ExternalArgumentDefinition binaryf32Args[] = { { "a", "f32" }, { "b", "f32" } }; ExternalDefinition buildInExternals[] = { { &scalarS32FuncsHandler, "opAdd", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opSub", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEqualsOrLess", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEqualsOrsGreater", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opLess", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opGreater", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEquals", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opNot", "s32", binarys32Args, ArrayCount(binarys32Args) }, }; loadExternals(&scalarTypesScope, &stack, ExternalFunctions{ buildInExternals, ArrayCount(buildInExternals) }); loadExternals(&scalarTypesScope, &stack, externals); loadLibrariries(&libraries, &scalarTypesScope, &stack, libsToLoad, libsCount); bool stillWorking = true; // load all global function and type definitions ListIterator<ASTNode> iterator = makeIterator(&mainNode->main.statements); while (stillWorking && hasNext(&iterator)) { ASTNode* statement = getNext(&iterator); if (statement->nodeType == AST_STATEMENT_FUNCTION_DEFINITION || statement->nodeType == AST_STATEMENT_TYPE_DEFINITION) stillWorking = runStatement(statement, &stack, &globalScope, error); else { // TODO: illigal statement exception? Or do this on parsing stage? } } if (stillWorking) { FunctionIdentifier mainIdentifier = {}; mainIdentifier.name = makeSlice("main"); Function* func = getFunction(&globalScope, mainIdentifier); if (func != nullptr) stillWorking = runStatement(func->body, &stack, &globalScope, error); else { stillWorking = false; *error = RuntimeError{ RET_UNDEFINED_FUNCTION, mainIdentifier.name, 0 }; } } scopeFreeMemory(&globalScope, &stack); scopeFreeMemory(&scalarTypesScope, &stack); freeAllLibraries(&libraries); freeArray(&libraries); freeMemoryStack(&stack); return stillWorking; }
/* * The trace operation collects the events in the BATs * and creates a secondary result set upon termination * of the query. */ static void SQLsetTrace(backend *be, Client cntxt, bit onoff) { InstrPtr q, resultset; InstrPtr tbls, cols, types, clen, scale; MalBlkPtr mb = cntxt->curprg->def; int k; (void) be; if (onoff) { (void) newStmt(mb, "profiler", "start"); initTrace(); } else { (void) newStmt(mb, "profiler", "stop"); /* cook a new resultSet instruction */ resultset = newInstruction(mb,ASSIGNsymbol); setModuleId(resultset, sqlRef); setFunctionId(resultset, resultSetRef); getArg(resultset,0)= newTmpVariable(mb,TYPE_int); /* build table defs */ tbls = newStmt(mb,batRef, newRef); setVarType(mb, getArg(tbls,0), newBatType(TYPE_oid, TYPE_str)); tbls = pushType(mb, tbls, TYPE_oid); tbls = pushType(mb, tbls, TYPE_str); resultset= pushArgument(mb,resultset, getArg(tbls,0)); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q,getArg(tbls,0)); q= pushStr(mb,q,".trace"); k= getArg(q,0); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q,k); q= pushStr(mb,q,".trace"); /* build colum defs */ cols = newStmt(mb,batRef, newRef); setVarType(mb, getArg(cols,0), newBatType(TYPE_oid, TYPE_str)); cols = pushType(mb, cols, TYPE_oid); cols = pushType(mb, cols, TYPE_str); resultset= pushArgument(mb,resultset, getArg(cols,0)); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q,getArg(cols,0)); q= pushStr(mb,q,"usec"); k= getArg(q,0); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, getArg(cols,0)); q= pushStr(mb,q,"statement"); /* build type defs */ types = newStmt(mb,batRef, newRef); setVarType(mb, getArg(types,0), newBatType(TYPE_oid, TYPE_str)); types = pushType(mb, types, TYPE_oid); types = pushType(mb, types, TYPE_str); resultset= pushArgument(mb,resultset, getArg(types,0)); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, getArg(types,0)); q= pushStr(mb,q,"bigint"); k= getArg(q,0); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, k); q= pushStr(mb,q,"clob"); /* build scale defs */ clen = newStmt(mb,batRef, newRef); setVarType(mb, getArg(clen,0), newBatType(TYPE_oid, TYPE_int)); clen = pushType(mb, clen, TYPE_oid); clen = pushType(mb, clen, TYPE_int); resultset= pushArgument(mb,resultset, getArg(clen,0)); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, getArg(clen,0)); q= pushInt(mb,q,64); k= getArg(q,0); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, k); q= pushInt(mb,q,0); /* build scale defs */ scale = newStmt(mb,batRef, newRef); setVarType(mb, getArg(scale,0), newBatType(TYPE_oid, TYPE_int)); scale = pushType(mb, scale, TYPE_oid); scale = pushType(mb, scale, TYPE_int); resultset= pushArgument(mb,resultset, getArg(scale,0)); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb,q, getArg(scale,0)); q= pushInt(mb,q,0); k= getArg(q,0); q= newStmt(mb,batRef,appendRef); q= pushArgument(mb, q, k); q= pushInt(mb,q,0); /* add the ticks column */ q = newStmt(mb, profilerRef, "getTrace"); q = pushStr(mb, q, putName("usec",4)); resultset= pushArgument(mb,resultset, getArg(q,0)); /* add the stmt column */ q = newStmt(mb, profilerRef, "getTrace"); q = pushStr(mb, q, putName("stmt",4)); resultset= pushArgument(mb,resultset, getArg(q,0)); pushInstruction(mb,resultset); } }
/* * The generic solution to the multiplex operators is to translate * them to a MAL loop. * The call optimizer.multiplex(MOD,FCN,A1,...An) introduces the following code * structure: * * @verbatim * A1rev:=bat.reverse(A1); * resB:= bat.new(A1); * barrier (h,t):= iterator.new(A1); * $1:= algebra.fetch(A1,h); * $2:= A2; # in case of constant? * ... * cr:= MOD.FCN($1,...,$n); * y:=algebra.fetch(A1rev,h); * bat.insert(resB,y,cr); * redo (h,t):= iterator.next(A1); * end h; * @end verbatim * * The algorithm consists of two phases: phase one deals with * collecting the relevant information, phase two is the actual * code construction. */ static str OPTexpandMultiplex(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i = 2, resB, iter = 0, cr; int hvar, tvar; int x, y; str mod, fcn; int *alias; InstrPtr q; int ht, tt; (void) cntxt; (void) stk; ht = getHeadType(getArgType(mb, pci, 0)); if (ht != TYPE_oid) throw(MAL, "optimizer.multiplex", "Target head type is missing"); tt = getTailType(getArgType(mb, pci, 0)); if (tt== TYPE_any) throw(MAL, "optimizer.multiplex", "Target tail type is missing"); if (isAnyExpression(getArgType(mb, pci, 0))) throw(MAL, "optimizer.multiplex", "Target type is missing"); mod = VALget(&getVar(mb, getArg(pci, 1))->value); mod = putName(mod,strlen(mod)); fcn = VALget(&getVar(mb, getArg(pci, 2))->value); fcn = putName(fcn,strlen(fcn)); /* search the iterator bat */ for (i = 3; i < pci->argc; i++) if (isaBatType(getArgType(mb, pci, i))) { iter = getArg(pci, i); if (getHeadType(getVarType(mb,iter)) != TYPE_oid) throw(MAL, "optimizer.multiplex", "Iterator BAT is not OID-headed"); break; } if( i == pci->argc) throw(MAL, "optimizer.multiplex", "Iterator BAT type is missing"); OPTDEBUGmultiplex { mnstr_printf(cntxt->fdout,"#calling the optimize multiplex script routine\n"); printFunction(cntxt->fdout,mb, 0, LIST_MAL_ALL ); mnstr_printf(cntxt->fdout,"#multiplex against operator %d %s\n",iter, getTypeName(getVarType(mb,iter))); printInstruction(cntxt->fdout,mb, 0, pci,LIST_MAL_ALL); } /* * Beware, the operator constant (arg=1) is passed along as well, * because in the end we issue a recursive function call that should * find the actual arguments at the proper place of the callee. */ alias= (int*) GDKmalloc(sizeof(int) * pci->maxarg); if (alias == NULL) return NULL; /* x := bat.reverse(A1); */ x = newTmpVariable(mb, newBatType(getTailType(getVarType(mb,iter)), getHeadType(getVarType(mb,iter)))); q = newFcnCall(mb, batRef, reverseRef); getArg(q, 0) = x; q = pushArgument(mb, q, iter); /* resB := new(refBat) */ q = newFcnCall(mb, batRef, newRef); resB = getArg(q, 0); setVarType(mb, getArg(q, 0), newBatType(ht, tt)); q = pushType(mb, q, ht); q = pushType(mb, q, tt); /* barrier (h,r) := iterator.new(refBat); */ q = newFcnCall(mb, iteratorRef, newRef); q->barrier = BARRIERsymbol; hvar = newTmpVariable(mb, TYPE_any); getArg(q,0) = hvar; tvar = newTmpVariable(mb, TYPE_any); q= pushReturn(mb, q, tvar); (void) pushArgument(mb,q,iter); /* $1:= algebra.fetch(Ai,h) or constant */ alias[i] = tvar; for (i++; i < pci->argc; i++) if (isaBatType(getArgType(mb, pci, i))) { q = newFcnCall(mb, algebraRef, "fetch"); alias[i] = newTmpVariable(mb, getTailType(getArgType(mb, pci, i))); getArg(q, 0) = alias[i]; q= pushArgument(mb, q, getArg(pci, i)); (void) pushArgument(mb, q, hvar); } /* cr:= mod.CMD($1,...,$n); */ q = newFcnCall(mb, mod, fcn); cr = getArg(q, 0) = newTmpVariable(mb, TYPE_any); for (i = 3; i < pci->argc; i++) if (isaBatType(getArgType(mb, pci, i))) { q= pushArgument(mb, q, alias[i]); } else { q = pushArgument(mb, q, getArg(pci, i)); } /* y := algebra.fetch(x,h); */ y = newTmpVariable(mb, getHeadType(getVarType(mb,iter))); q = newFcnCall(mb, algebraRef, "fetch"); getArg(q, 0) = y; q = pushArgument(mb, q, x); q = pushArgument(mb, q, hvar); /* insert(resB,h,cr); not append(resB, cr); the head type (oid) may dynamically change */ q = newFcnCall(mb, batRef, insertRef); q= pushArgument(mb, q, resB); q= pushArgument(mb, q, y); (void) pushArgument(mb, q, cr); /* redo (h,r):= iterator.next(refBat); */ q = newFcnCall(mb, iteratorRef, nextRef); q->barrier = REDOsymbol; getArg(q,0) = hvar; q= pushReturn(mb, q, tvar); (void) pushArgument(mb,q,iter); q = newAssignment(mb); q->barrier = EXITsymbol; getArg(q,0) = hvar; (void) pushReturn(mb, q, tvar); q = newAssignment(mb); getArg(q, 0) = getArg(pci, 0); (void) pushArgument(mb, q, resB); GDKfree(alias); return MAL_SUCCEED; }
int pushDisk(lua_State* luaSt, const Disk* p) { return pushType(luaSt, DISK_TYPE, sizeof(Disk), (void*) p); }
int pushNBodyCtx(lua_State* luaSt, const NBodyCtx* p) { return pushType(luaSt, NBODYCTX_TYPE, sizeof(NBodyCtx), (void*) p); }
int pushSpherical(lua_State* luaSt, const Spherical* p) { return pushType(luaSt, SPHERICAL_TYPE, sizeof(Spherical), (void*) p); }