bool PruningVisitor::VisitImpNode(ASTNode **nodePtr) { ASTNode *node = *nodePtr; ASTNode **leftNodePtr, **rightNodePtr; leftNodePtr = &(node->Nodes[0]); rightNodePtr = &(node->Nodes[1]); bool leftNodeKnown = VisitNode(leftNodePtr), rightNodeKnown = VisitNode(rightNodePtr); ASTNode *leftNode = *leftNodePtr, *rightNode = *rightNodePtr; //P->Q === !P||Q ASTNode *newNode = new ASTNode(Token(TOKENTYPE_OPOR, "||")); ASTNode *newSubNode = new ASTNode(Token(TOKENTYPE_OPNOT, "!")); newSubNode->Nodes.push_back(leftNode); newNode->Nodes.push_back(newSubNode); newNode->Nodes.push_back(rightNode); bool newKnown = VisitNode(&newNode); CopyTo(newNode, nodePtr); return newKnown; }
bool PruningVisitor::VisitBitorNode(ASTNode **nodePtr) { ASTNode *node = *nodePtr; ASTNode **leftNodePtr, **rightNodePtr; leftNodePtr = &(node->Nodes[0]); rightNodePtr = &(node->Nodes[1]); bool leftNodeKnown = VisitNode(leftNodePtr), rightNodeKnown = VisitNode(rightNodePtr); ASTNode *leftNode = *leftNodePtr, *rightNode = *rightNodePtr; if ((leftNodeKnown && leftNode->Value == 0xFFFFFFFF) || (rightNodeKnown && rightNode->Value == 0xFFFFFFFF)) { delete leftNode; delete rightNode; node->Nodes.clear(); SetKnown(node, 0xFFFFFFFF); return true; } else if (leftNodeKnown && leftNode->Value == 0) { delete leftNode; CopyTo(rightNode, nodePtr); return false; } else if (rightNodeKnown && rightNode->Value == 0) { delete rightNode; CopyTo(leftNode, nodePtr); return false; } return false; }
static kbool_t FuelVM_VisitIfNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk) { kNode *expr = kNode_getFirstNode(kctx, stmt); Block *ThenBB = CreateBlock(BLD(builder)); Block *ElseBB = CreateBlock(BLD(builder)); Block *MergeBB = CreateBlock(BLD(builder)); /* if */ SUGAR VisitNode(kctx, builder, expr, thunk); CreateBranch(BLD(builder), FuelVM_getExpression(builder), ThenBB, ElseBB); { /* then */ IRBuilder_setBlock(BLD(builder), ThenBB); SUGAR VisitNode(kctx, builder, kNode_getFirstBlock(kctx, stmt), thunk); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { IRBuilder_JumpTo(BLD(builder), MergeBB); } } { /* else */ IRBuilder_setBlock(BLD(builder), ElseBB); SUGAR VisitNode(kctx, builder, kNode_getElseBlock(kctx, stmt), thunk); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { IRBuilder_JumpTo(BLD(builder), MergeBB); } } /* endif */ IRBuilder_setBlock(BLD(builder), MergeBB); return true; }
bool PruningVisitor::VisitModNode(ASTNode **nodePtr) { ASTNode *node = *nodePtr; ASTNode **leftNodePtr, **rightNodePtr; leftNodePtr = &(node->Nodes[0]); rightNodePtr = &(node->Nodes[1]); bool leftNodeKnown = VisitNode(leftNodePtr), rightNodeKnown = VisitNode(rightNodePtr); ASTNode *leftNode = *leftNodePtr, *rightNode = *rightNodePtr; if (leftNodeKnown && rightNodeKnown) { int value = leftNode->Value % rightNode->Value; delete leftNode; *leftNodePtr = leftNode = NULL; delete rightNode; *rightNodePtr = rightNode = NULL; node->Nodes.clear(); SetKnown(node, value); return true; } return false; }
static kbool_t CollectLocalVar_VisitIfNode(KVISITOR_PARAM) { KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); KLIB VisitNode(kctx, builder, kUntypedNode_getElseBlock(kctx, node), thunk); return true; }
static kbool_t MiniVM_VisitDoWhileNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { bblock_t HeadBB = new_BasicBlockLABEL(kctx); bblock_t BodyBB = new_BasicBlockLABEL(kctx); bblock_t MergeBB = new_BasicBlockLABEL(kctx); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), HeadBB); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"), MergeBB); MiniVMBuilder_JumpTo(kctx, builder, BodyBB); { /* Head */ MiniVMBuilder_setBlock(kctx, builder, HeadBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); CreateBranch(kctx, builder, MiniVM_getExpression(builder), MergeBB, BodyBB, true); } { /* Body */ MiniVMBuilder_setBlock(kctx, builder, BodyBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } MiniVMBuilder_setBlock(kctx, builder, MergeBB); return true; }
bool PruningVisitor::VisitDivNode(ASTNode **nodePtr) { ASTNode *node = *nodePtr; ASTNode **leftNodePtr, **rightNodePtr; leftNodePtr = &(node->Nodes[0]); rightNodePtr = &(node->Nodes[1]); bool leftNodeKnown = VisitNode(leftNodePtr), rightNodeKnown = VisitNode(rightNodePtr); ASTNode *leftNode = *leftNodePtr, *rightNode = *rightNodePtr; if (leftNodeKnown && rightNodeKnown) { if (rightNode->Value == 0) { throw RuntimeError("Divided by zero."); } int value = leftNode->Value / rightNode->Value; delete leftNode; *leftNodePtr = leftNode = NULL; delete rightNode; *rightNodePtr = rightNode = NULL; node->Nodes.clear(); SetKnown(node, value); return true; } return false; }
bool PruningVisitor::VisitBitxorNode(ASTNode **nodePtr) { ASTNode *node = *nodePtr; ASTNode **leftNodePtr, **rightNodePtr; leftNodePtr = &(node->Nodes[0]); rightNodePtr = &(node->Nodes[1]); bool leftNodeKnown = VisitNode(leftNodePtr), rightNodeKnown = VisitNode(rightNodePtr); ASTNode *leftNode = *leftNodePtr, *rightNode = *rightNodePtr; if ((leftNodeKnown && leftNode->Value == 0xFFFFFFFF)) //1^x === ~x { delete leftNode; *leftNodePtr = leftNode = NULL; ASTNode *newNode = new ASTNode(Token(TOKENTYPE_OPBITNOT, "~")); newNode->Nodes.push_back(rightNode); bool newKnown = VisitNode(&newNode); CopyTo(newNode, nodePtr); return newKnown; } else if (leftNodeKnown && leftNode->Value == 0) //0^x === x { delete leftNode; *leftNodePtr = leftNode = NULL; CopyTo(rightNode, nodePtr); return rightNodeKnown; } else if (rightNodeKnown && rightNode->Value == 0xFFFFFFFF) //x^1 === ~x { delete rightNode; *rightNodePtr = rightNode = NULL; ASTNode *newNode = new ASTNode(Token(TOKENTYPE_OPBITNOT, "~")); newNode->Nodes.push_back(leftNode); bool newKnown = VisitNode(&newNode); CopyTo(newNode, nodePtr); return newKnown; } else if (rightNodeKnown && rightNode->Value == 0) //x^0 === x { delete rightNode; *rightNodePtr = rightNode = NULL; CopyTo(leftNode, nodePtr); return leftNodeKnown; } return false; }
static kbool_t FuelVM_VisitAssignNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { /* * [LetExpr] := lhs = rhs * expr->NodeList = [NULL, lhs, rhs] **/ kNode *left = kNode_At(expr, 1); kNode *right = kNode_At(expr, 2); INode *Node; FuelIRBuilder *flbuilder = BLD(builder); if(left->node == KNode_Local) { enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId); if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, left->index)) == 0) { Node = CreateLocal(flbuilder, type); IField_setHash((IField *) Node, left->index); } SUGAR VisitNode(kctx, builder, right, thunk); INode *RHS = FuelVM_getExpression(builder); //if(RHS->Type != Node->Type) { // INode_setType(Node, RHS->Type); //} CreateUpdate(flbuilder, Node, RHS); } //else if(left->node == TEXPR_STACKTOP) { // enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId); // uintptr_t Hash = (uintptr_t) left; // if((Node = IRBuilder_FindLocalVarByHash(flbuilder, type, Hash)) == 0) { // Node = CreateLocal(flbuilder, type); // IField_setHash((IField *) Node, Hash); // ARRAY_add(INodePtr, &BLD(builder)->Stack, Node); // } // SUGAR VisitNode(kctx, builder, right, thunk); // INode *RHS = FuelVM_getExpression(builder); // if(RHS->Type != Node->Type) // INode_setType(Node, RHS->Type); // CreateUpdate(BLD(builder), Node, RHS); //} else{ assert(left->node == KNode_Field); SUGAR VisitNode(kctx, builder, right, thunk); kshort_t index = (kshort_t)left->index; kshort_t xindex = (kshort_t)(left->index >> (sizeof(kshort_t)*8)); INode *Left; if((Left = IRBuilder_FindLocalVarByHash(BLD(builder), TYPE_Object, index)) == 0) { Left = CreateLocal(BLD(builder), TYPE_Object); IField_setHash((IField *) Left, index); } enum TypeId type = ConvertToTypeId(kctx, left->attrTypeId); Node = CreateField(BLD(builder), FieldScope, type, Left, xindex); SUGAR VisitNode(kctx, builder, right, thunk); CreateUpdate(BLD(builder), Node, FuelVM_getExpression(builder)); } builder->Value = Node; return true; }
static kbool_t CollectLocalVar_VisitWhileNode(KVISITOR_PARAM) { kUntypedNode *ItrBlock; KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); ItrBlock = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_("Iterator"), NULL); if(ItrBlock != NULL) { KLIB VisitNode(kctx, builder, ItrBlock, thunk); } return true; }
static kbool_t CollectLocalVar_VisitAssignNode(KVISITOR_PARAM) { kUntypedNode *left = kUntypedNode_At(node, 1); kUntypedNode *right = kUntypedNode_At(node, 2); if(kUntypedNode_node(left) == KNode_Local) { LOCAL(left->typeAttr, left->index); KLIB VisitNode(kctx, builder, right, thunk); } else{ LOCAL(KType_Object, (khalfword_t)left->index); KLIB VisitNode(kctx, builder, right, thunk); } return true; }
static struct KVirtualCode *MiniVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kUntypedNode *block, int option) { KVirtualCode *vcode; KBuffer wb; KBuilder builderbuf = {{0}}, *builder = &builderbuf; kNameSpace *ns = kUntypedNode_ns(block); INIT_GCSTACK(); KLIB KBuffer_Init(&(kctx->stack->cwb), &wb); builder->common.api = ns->builderApi; builder->constPools = ns->NameSpaceConstList; builder->bbBeginId = new_BasicBlockLABEL(kctx); builder->bbReturnId = new_BasicBlockLABEL(kctx); builder->bbMainId = builder->bbBeginId; builder->currentMtd = mtd; builder->Value = 0; builder->stackbase = 0; builder->InstructionSize = 0; builder->common.api = &CollectLocalVar_BuilderAPI; KLIB VisitNode(kctx, builder, block, NULL); builder->stackbase += builder->localVarSize + 1/* == this object */; builder->common.api = ns->builderApi; KLIB KArray_Init(kctx, &builder->localVar, sizeof(LocalVarInfo) * builder->stackbase); ASM(THCODE, 0, _THCODE); ASM(CHKSTACK, 0); KLIB VisitNode(kctx, builder, block, NULL); if(!Block_HasTerminatorInst(kctx, builder->bbMainId)) { MiniVMBuilder_JumpTo(kctx, builder, builder->bbReturnId); } MiniVMBuilder_setBlock(kctx, builder, builder->bbReturnId); if(mtd->mn == MN_new) { // FIXME: Type 'This' must be resolved ASM(NMOV, OC_(K_RTNIDX), OC_(0), KClass_(mtd->typeId)); } ASM(RET); vcode = CompileVirtualCode(kctx, builder, builder->bbBeginId, builder->bbReturnId); KLIB KArray_Free(kctx, &builder->localVar); RESET_GCSTACK(); KLIB KBuffer_Free(&wb); return vcode; }
bool AStar::Step(sf::RectangleShape board[]) { Node* pCurrentNode; if (!qOpenList.empty()) { pCurrentNode = VisitNode(); } else { std::cout << "Can't find a path" << std::endl; return true; } UpdateBoardGraphic(board); if (pCurrentNode == tRoot[iEndNode]) { PrintPath(pCurrentNode, board); return true; } board[pCurrentNode->X()*yMax + pCurrentNode->Y()].setFillColor(sf::Color::Red); return false; }
void Visit(SyntaxApi::IOperations::IUnaryOp* operation_node) { std::vector<TSOperation*> param_expressions; TSOperation *left; left = VisitNode(operation_node->GetLeft()); param_expressions.push_back(left); std::vector<TExpressionResult> param; param.resize(1); param[0] = left->GetFormalParameter(); SemanticApi::ISMethod *unary_operator = nullptr; if (param[0].GetClass() == nullptr) syntax_node->Error("К данному операнду нельзя применить унарный оператор (нужен тип отличающийся от void)!"); std::vector<SemanticApi::ISMethod*> operators; param[0].GetClass()->GetOperators(operators, operation_node->GetOp()); unary_operator = FindMethod(syntax_node, operators, param); if (unary_operator != nullptr) { ValidateAccess(syntax_node, owner, unary_operator); TSExpression_TMethodCall* method_call = new TSExpression_TMethodCall(SemanticApi::TMethodCallType::Operator); method_call->Build(param_expressions, dynamic_cast<TSMethod*>(unary_operator)); Return(method_call); } else syntax_node->Error("Унарного оператора для данного типа не существует!"); }
DWORD CQHState::OnVisitHierarchy( DWORD size, void *params ) { VISITHIERARCHYDATA *vhd = static_cast<VISITHIERARCHYDATA *>( params ); VERIFY_MESSAGE_SIZE( size, sizeof( *vhd ) ); VisitNode( vhd->visitor ); return MSG_HANDLED_STOP; }
bool PruningVisitor::VisitNotNode(ASTNode **nodePtr) { auto node = *nodePtr; ASTNode **subnodePtr = &(node->Nodes[0]); bool subKnown = VisitNode(subnodePtr); ASTNode *subNode = *subnodePtr; if (subKnown) { int value = !subNode->Value; delete subNode; node->Nodes.clear(); SetKnown(node, value); return true; } else if (subNode->token.Type == TOKENTYPE_OPNOT) //!!x === x { ASTNode *subSubNode = subNode->Nodes[0]; subNode->Nodes.clear(); delete subNode; *subnodePtr = subNode = NULL; CopyTo(subSubNode, nodePtr); return subSubNode->Known; } return false; }
static kbool_t KBuilder_VisitMethodCallNode(KonohaContext *kctx, KBuilder *builder, kNode *expr, void *thunk) { kshort_t a = AssignStack(thunk), espidx = expr->stackbase, thisidx = espidx + K_CALLDELTA; DBG_ASSERT(a <= espidx); kMethod *mtd = CallNode_getMethod(expr); DBG_ASSERT(IS_Method(mtd)); int i, s = kMethod_Is(Static, mtd) ? 2 : 1; int argc = CallNode_getArgCount(expr); for (i = s; i < argc + 2; i++) { intptr_t a = thisidx + i - 1; kNode *paramNode = kNode_At(expr, i); if(!kNode_IsValue(paramNode) && paramNode->stackbase != a) { DBG_P("a=%d, stackbase=%d", a, paramNode->stackbase); DBG_ASSERT(paramNode->stackbase == a); } SUGAR VisitNode(kctx, builder, paramNode, &a); } if(kMethod_Is(Final, mtd) || !kMethod_Is(Virtual, mtd)) { ASM(NSET, NC_(thisidx-1), (intptr_t)mtd, KClass_Method); if(kMethod_Is(Virtual, mtd)) { // set namespace to enable method lookups ASM(NSET, OC_(thisidx-2), (intptr_t)kNode_ns(expr), KClass_NameSpace); } } else { ASM(NSET, OC_(thisidx-2), (intptr_t)kNode_ns(expr), KClass_NameSpace); ASM(LOOKUP, SFP_(thisidx), kNode_ns(expr), mtd); } int esp_ = SFP_(espidx + argc + K_CALLDELTA + 1); ASM(CALL, builder->common.uline, SFP_(thisidx), esp_, KLIB Knull(kctx, KClass_(expr->attrTypeId))); ReAssignNonValueNode(kctx, builder, a, expr); return true; }
static struct KVirtualCode *FuelVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kNode *block, int option) { if(unlikely(AbstractMethodPtr == 0)) { AbstractMethodPtr = mtd->invokeKMethodFunc; } kNameSpace *ns = kNode_ns(block); KBuilder builderbuf = {}, *builder = &builderbuf; FuelIRBuilder Builder = {}; INIT_GCSTACK(); IRBuilder_Init(&Builder, kctx, ns); builder->builder = &Builder; builder->common.api = ns->builderApi; Block *EntryBlock = CreateBlock(BLD(builder)); IRBuilder_setBlock(BLD(builder), EntryBlock); INode *Self = SetUpArguments(kctx, &Builder, mtd); SUGAR VisitNode(kctx, builder, block, NULL); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { if(mtd->mn == MN_new) { INode *Ret = CreateReturn(BLD(builder), Self); INode_setType(Ret, ConvertToTypeId(kctx, mtd->typeId)); } else { ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; if(retTy == KType_void) { CreateReturn(BLD(builder), 0); } else { enum TypeId Type = ConvertToTypeId(kctx, retTy); INode *Ret; if(KType_Is(UnboxType, retTy)) { SValue V; V.bits = 0; Ret = CreateConstant(BLD(builder), Type, V); } else { kObject *obj = KLIB Knull(kctx, KClass_(retTy)); Ret = CreateObject(BLD(builder), Type, (void *)obj); } Ret = CreateReturn(BLD(builder), Ret); INode_setType(Ret, Type); CreateReturn(BLD(builder), 0); } } } RESET_GCSTACK(); IMethod Mtd = {kctx, mtd, EntryBlock, ns}; BLD(builder)->Method = &Mtd; bool JITCompiled = false; union ByteCode *code = IRBuilder_Compile(BLD(builder), &Mtd, option, &JITCompiled); if(mtd->invokeKMethodFunc == FuelVM_RunVirtualMachine) { mtd->virtualCodeApi_plus1[-1]->FreeVirtualCode(kctx, mtd->vcode_start); } KLIB kMethod_SetFunc(kctx, mtd, 0); if(JITCompiled) { KLIB kMethod_SetFunc(kctx, mtd, (KMethodFunc) code); } KFieldSet(mtd, ((kMethodVar *)mtd)->CompiledNode, block); IRBuilder_Exit(&Builder); return (struct KVirtualCode *) code; }
static kbool_t CollectLocalVar_VisitReturnNode(KVISITOR_PARAM) { kUntypedNode *expr = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_ExprPattern, NULL); if(expr != NULL && IS_Node(expr) && expr->typeAttr != KType_void) { KLIB VisitNode(kctx, builder, expr, thunk); } return false; }
int Dijkstra(NodeStruct *Map,int MapSize,int Start,int Finish) { //Start Dijkstra algorithm VisitNode(Map, MapSize, Start, Finish); //Trace found route of Dijkstra algorithm return TraceRoute(Map, Finish); }
static INode *FetchINode(KonohaContext *kctx, KBuilder *builder, kNode *expr, unsigned idx, ktypeattr_t reqTy, void *thunk) { kNode *exprN = kNode_At(expr, idx); SUGAR VisitNode(kctx, builder, exprN, thunk); INode *Node = FuelVM_getExpression(builder); assert(Node->Type != TYPE_void); return Node; }
static kbool_t MiniVM_VisitForNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kUntypedNode *initNode = kUntypedNode_GetNode(kctx, node, KSymbol_("init")); if(initNode != NULL) { KLIB VisitNode(kctx, builder, initNode, thunk); } return MiniVM_VisitLoopNode(kctx, builder, node, thunk, ForLoop); }
static void CreateCond(KonohaContext *kctx, KBuilder *builder, kNode *expr, enum ConditionalOp Op, void *thunk) { kNode *LHS = kNode_At(expr, 1); kNode *RHS = kNode_At(expr, 2); Block *HeadBB = CreateBlock(BLD(builder)); Block *ThenBB = CreateBlock(BLD(builder)); Block *MergeBB = CreateBlock(BLD(builder)); /* [CondExpr] * LogicalAnd case * | goto Head * Head | let bval = LHS * | if(bval) { goto Then } else { goto Merge } * Then | bval = RHS * | goto Merge * Merge | ... */ INode *Node; IRBuilder_JumpTo(BLD(builder), HeadBB); { /* Head */ IRBuilder_setBlock(BLD(builder), HeadBB); Node = CreateLocal(BLD(builder), TYPE_boolean); SUGAR VisitNode(kctx, builder, LHS, thunk); INode *Left = FuelVM_getExpression(builder); CreateUpdate(BLD(builder), Node, Left); if(Op == LogicalAnd) { CreateBranch(BLD(builder), Left, ThenBB, MergeBB); } else { CreateBranch(BLD(builder), Left, MergeBB, ThenBB); } } { /* Then */ IRBuilder_setBlock(BLD(builder), ThenBB); SUGAR VisitNode(kctx, builder, RHS, thunk); INode *Right = FuelVM_getExpression(builder); CreateUpdate(BLD(builder), Node, Right); IRBuilder_JumpTo(BLD(builder), MergeBB); } IRBuilder_setBlock(BLD(builder), MergeBB); builder->Value = Node; }
static kbool_t CollectLocalVar_VisitFunctionNode(KVISITOR_PARAM) { size_t i, ParamSize = kArray_size(node->NodeList)-2; for(i = 0; i < ParamSize; i++) { kUntypedNode *expr = kUntypedNode_At(node, i+2); KLIB VisitNode(kctx, builder, expr, thunk); } return true; }
static kbool_t CollectLocalVar_VisitForNode(KVISITOR_PARAM) { kUntypedNode *initNode = kUntypedNode_GetNode(kctx, node, KSymbol_("init")); if(initNode != NULL) { KLIB VisitNode(kctx, builder, initNode, thunk); } CollectLocalVar_VisitWhileNode(kctx, builder, node, thunk); return true; }
static void CreateCond(KonohaContext *kctx, KBuilder *builder, kUntypedNode *expr, enum ConditionalOp Op, void *thunk) { intptr_t cond; kUntypedNode *LHS = kUntypedNode_At(expr, 1); kUntypedNode *RHS = kUntypedNode_At(expr, 2); bblock_t HeadBB = new_BasicBlockLABEL(kctx); bblock_t ThenBB = new_BasicBlockLABEL(kctx); bblock_t MergeBB = new_BasicBlockLABEL(kctx); /* [CondExpr] * LogicalAnd case * | goto Head * Head | let bval = LHS * | if(bval) { goto Then } else { goto Merge } * Then | bval = RHS * | goto Merge * Merge | ... */ MiniVMBuilder_JumpTo(kctx, builder, HeadBB); cond = builder->stackbase; builder->stackbase += 1; { /* Head */ MiniVMBuilder_setBlock(kctx, builder, HeadBB); KLIB VisitNode(kctx, builder, LHS, thunk); CreateUpdate(kctx, builder, KType_Boolean, cond, MiniVM_getExpression(builder)); if(Op == LogicalAnd) CreateBranch(kctx, builder, cond, ThenBB, MergeBB, false); else { CreateBranch(kctx, builder, cond, ThenBB, MergeBB, true); } } { /* Then */ MiniVMBuilder_setBlock(kctx, builder, ThenBB); KLIB VisitNode(kctx, builder, RHS, thunk); CreateUpdate(kctx, builder, KType_Boolean, cond, MiniVM_getExpression(builder)); MiniVMBuilder_JumpTo(kctx, builder, MergeBB); } MiniVMBuilder_setBlock(kctx, builder, MergeBB); builder->stackbase -= 1; builder->Value = builder->stackbase; }
static kbool_t MiniVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk, enum LoopType Loop) { kUntypedNode *ItrBlock; bblock_t HeadBB = new_BasicBlockLABEL(kctx); bblock_t BodyBB = new_BasicBlockLABEL(kctx); bblock_t ItrBB = new_BasicBlockLABEL(kctx); bblock_t MergeBB = new_BasicBlockLABEL(kctx); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), ItrBB); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"), MergeBB); ItrBlock = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_("Iterator"), NULL); if(ItrBlock != NULL) { assert(Loop == ForLoop); MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } else if(Loop == WhileLoop) { MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } else { MiniVMBuilder_JumpTo(kctx, builder, BodyBB); } { /* Head */ MiniVMBuilder_setBlock(kctx, builder, HeadBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); CreateBranch(kctx, builder, MiniVM_getExpression(builder), BodyBB, MergeBB, false); } { /* Body */ MiniVMBuilder_setBlock(kctx, builder, BodyBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); MiniVMBuilder_JumpTo(kctx, builder, ItrBB); /* Itr */ MiniVMBuilder_setBlock(kctx, builder, ItrBB); if(ItrBlock != NULL) { KLIB VisitNode(kctx, builder, ItrBlock, thunk); } MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } MiniVMBuilder_setBlock(kctx, builder, MergeBB); return true; }
static kbool_t MiniVM_VisitReturnNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kUntypedNode *expr = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_ExprPattern, NULL); if(expr != NULL && IS_Node(expr) && expr->typeAttr != KType_void) { KLIB VisitNode(kctx, builder, expr, thunk); ASM_NMOV(kctx, builder, KClass_(expr->typeAttr), K_RTNIDX, MiniVM_getExpression(builder)); } MiniVMBuilder_JumpTo(kctx, builder, builder->bbReturnId); return false; }
static kbool_t MiniVM_VisitBoxNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { /* * [box] := box(this) **/ KLIB VisitNode(kctx, builder, node->NodeToPush, thunk); ASM(BOX, OC_(builder->stackbase), NC_(MiniVM_getExpression(builder)), KClass_(node->typeAttr)); builder->Value = builder->stackbase; return true; }
static kbool_t CollectLocalVar_VisitBlockNode(KVISITOR_PARAM) { unsigned i; for(i = 0; i < kUntypedNode_GetNodeListSize(kctx, node); i++) { kUntypedNode *stmt = node->NodeList->NodeItems[i]; if(!KLIB VisitNode(kctx, builder, stmt, thunk)) break; } return true; }