/*************************************************************** NAME : GenerateSlotComparisonTest DESCRIPTION : Generates pattern and join network expressions for comparing object pattern variables INPUTS : 1) A flag indicating if this is a pattern or join network test 2) For a join test, a flag indicating if it is a nand join 3) The intermediate parse node for the first variable 4) The intermediate parse node for the second variable RETURNS : An expression for comparing the variables SIDE EFFECTS : Expression and bitmaps generated NOTES : The following tests are generated for the following scenarios: SF slot w/ SF slot: PN_1 or JN_1 Example: (foo ?x) with (bar ?xy) SF slot w/ SF reference in MF slot: PN_2 or JN_2 Example: (foo ?x) (bar ? ?x ? ?) SF reference w/ SF reference: PN_3 or JN_3 Example: (foo ? ?x ?) and (bar ? ? ? ?x) All other cases: EQ/NEQ general test Example: (foo $? ?x $?) and (bar ?x) ***************************************************************/ static EXPRESSION *GenerateSlotComparisonTest( void *theEnv, int joinTest, int isNand, struct lhsParseNode *selfNode, struct lhsParseNode *referringNode) { EXPRESSION *theExp; struct ObjectCmpPNSingleSlotVars1 phack1; struct ObjectCmpPNSingleSlotVars2 phack2; struct ObjectCmpPNSingleSlotVars3 phack3; struct ObjectCmpJoinSingleSlotVars1 jhack1; struct ObjectCmpJoinSingleSlotVars2 jhack2; struct ObjectCmpJoinSingleSlotVars3 jhack3; struct lhsParseNode *firstNode; if (isNand) { firstNode = referringNode; } else { firstNode = selfNode; } /* ========================================================= If we are comparing two single-field slot variables that don't require multifield markers for lookup, use a quick comparison. Otherwise, use a general eq/neq with the pattern variable access routines ========================================================= */ if (IsSimpleSlotVariable(firstNode) && IsSimpleSlotVariable(referringNode)) { /* ============================== Compare two single-field slots ============================== */ if ((firstNode->withinMultifieldSlot == FALSE) && (referringNode->withinMultifieldSlot == FALSE)) { ClearBitString((void *) &phack1,(int) sizeof(struct ObjectCmpPNSingleSlotVars1)); ClearBitString((void *) &jhack1,(int) sizeof(struct ObjectCmpJoinSingleSlotVars1)); if (selfNode->negated) phack1.fail = jhack1.fail = 1; else phack1.pass = jhack1.pass = 1; phack1.firstSlot = jhack1.firstSlot = (unsigned short) firstNode->slotNumber; phack1.secondSlot = jhack1.secondSlot = (unsigned short) referringNode->slotNumber; if (joinTest) { if (isNand) { jhack1.firstPattern = (unsigned short) referringNode->joinDepth; } else { jhack1.firstPattern = 0; } jhack1.firstPatternRHS = TRUE; jhack1.secondPatternLHS = TRUE; jhack1.secondPattern = (unsigned short) referringNode->joinDepth; theExp = GenConstant(theEnv,OBJ_JN_CMP1,EnvAddBitMap(theEnv,(void *) &jhack1, (int) sizeof(struct ObjectCmpJoinSingleSlotVars1))); } else theExp = GenConstant(theEnv,OBJ_PN_CMP1,EnvAddBitMap(theEnv,(void *) &phack1, (int) sizeof(struct ObjectCmpPNSingleSlotVars1))); } /* ============================================ Compare a single-field slot with a single-field in a multifield slot (make sure the multifield slot reference is first ============================================ */ else if ((firstNode->withinMultifieldSlot == FALSE) || (referringNode->withinMultifieldSlot == FALSE)) { ClearBitString((void *) &phack2,(int) sizeof(struct ObjectCmpPNSingleSlotVars2)); ClearBitString((void *) &jhack2,(int) sizeof(struct ObjectCmpJoinSingleSlotVars2)); if (selfNode->negated) phack2.fail = jhack2.fail = 1; else phack2.pass = jhack2.pass = 1; if (firstNode->withinMultifieldSlot == TRUE) { phack2.firstSlot = jhack2.firstSlot = (unsigned short) firstNode->slotNumber; phack2.secondSlot = jhack2.secondSlot = (unsigned short) referringNode->slotNumber; if (joinTest) { if (isNand) { jhack2.firstPattern = (unsigned short) referringNode->joinDepth; } else { jhack2.firstPattern = 0; } jhack2.firstPatternRHS = TRUE; jhack2.secondPatternLHS = TRUE; jhack2.secondPattern = (unsigned short) referringNode->joinDepth; } if (firstNode->multiFieldsBefore == 0) { phack2.fromBeginning = jhack2.fromBeginning = 1; phack2.offset = jhack2.offset = firstNode->singleFieldsBefore; } else phack2.offset = jhack2.offset = firstNode->singleFieldsAfter; } else { phack2.firstSlot = jhack2.firstSlot = (unsigned short) referringNode->slotNumber; phack2.secondSlot = jhack2.secondSlot = (unsigned short) firstNode->slotNumber; if (joinTest) { if (isNand) { jhack2.secondPattern = (unsigned short) firstNode->joinDepth; } else { jhack2.secondPattern = 0; } jhack2.secondPatternRHS = TRUE; jhack2.firstPatternLHS = TRUE; jhack2.firstPattern = (unsigned short) referringNode->joinDepth; } if (referringNode->multiFieldsBefore == 0) { phack2.fromBeginning = jhack2.fromBeginning = 1; phack2.offset = jhack2.offset = referringNode->singleFieldsBefore; } else phack2.offset = jhack2.offset = referringNode->singleFieldsAfter; } if (joinTest) theExp = GenConstant(theEnv,OBJ_JN_CMP2,EnvAddBitMap(theEnv,(void *) &jhack2, (int) sizeof(struct ObjectCmpJoinSingleSlotVars2))); else theExp = GenConstant(theEnv,OBJ_PN_CMP2,EnvAddBitMap(theEnv,(void *) &phack2, (int) sizeof(struct ObjectCmpPNSingleSlotVars2))); } /* =================================== Compare two single-field references within multifield slots =================================== */ else { ClearBitString((void *) &phack3,(int) sizeof(struct ObjectCmpPNSingleSlotVars3)); ClearBitString((void *) &jhack3,(int) sizeof(struct ObjectCmpJoinSingleSlotVars3)); if (selfNode->negated) phack3.fail = jhack3.fail = 1; else phack3.pass = jhack3.pass = 1; phack3.firstSlot = jhack3.firstSlot = (unsigned short) firstNode->slotNumber; phack3.secondSlot = jhack3.secondSlot = (unsigned short) referringNode->slotNumber; if (firstNode->multiFieldsBefore == 0) { phack3.firstFromBeginning = jhack3.firstFromBeginning = 1; phack3.firstOffset = jhack3.firstOffset = firstNode->singleFieldsBefore; } else phack3.firstOffset = jhack3.firstOffset = firstNode->singleFieldsAfter; if (referringNode->multiFieldsBefore == 0) { phack3.secondFromBeginning = jhack3.secondFromBeginning = 1; phack3.secondOffset = jhack3.secondOffset = referringNode->singleFieldsBefore; } else phack3.secondOffset = jhack3.secondOffset = referringNode->singleFieldsAfter; if (joinTest) { if (isNand) { jhack3.firstPattern = (unsigned short) referringNode->joinDepth; } else { jhack3.firstPattern = 0; } jhack3.firstPatternRHS = TRUE; jhack3.secondPatternLHS = TRUE; jhack3.secondPattern = (unsigned short) referringNode->joinDepth; theExp = GenConstant(theEnv,OBJ_JN_CMP3,EnvAddBitMap(theEnv,(void *) &jhack3, (int) sizeof(struct ObjectCmpJoinSingleSlotVars3))); } else theExp = GenConstant(theEnv,OBJ_PN_CMP3,EnvAddBitMap(theEnv,(void *) &phack3, (int) sizeof(struct ObjectCmpPNSingleSlotVars3))); } } /* ================================================== General comparison for multifield slot references, references which require multifield markers, and object addresses ================================================== */ else { theExp = GenConstant(theEnv,FCALL,selfNode->negated ? ExpressionData(theEnv)->PTR_NEQ : ExpressionData(theEnv)->PTR_EQ); theExp->argList = GenConstant(theEnv,0,NULL); if (isNand) { GenObjectGetVar(theEnv,joinTest,theExp->argList,selfNode,NESTED_RHS); } else { GenObjectGetVar(theEnv,joinTest,theExp->argList,selfNode,RHS); } theExp->argList->nextArg = GenConstant(theEnv,0,NULL); GenObjectGetVar(theEnv,joinTest,theExp->argList->nextArg,referringNode,LHS); } return(theExp); }
/*************************************************************** NAME : GenerateSlotComparisonTest DESCRIPTION : Generates pattern and join network expressions for comparing object pattern variables INPUTS : 1) A flag indicating if this is a pattern or join network test 2) The intermediate parse node for the first variable 3) The intermediate parse node for the second variable RETURNS : An expression for comparing the variables SIDE EFFECTS : Expression and bitmaps generated NOTES : The following tests are generated for the following scenarios: SF slot w/ SF slot: PN_1 or JN_1 Example: (foo ?x) with (bar ?xy) SF slot w/ SF reference in MF slot: PN_2 or JN_2 Example: (foo ?x) (bar ? ?x ? ?) SF reference w/ SF reference: PN_3 or JN_3 Example: (foo ? ?x ?) and (bar ? ? ? ?x) All other cases: EQ/NEQ general test Example: (foo $? ?x $?) and (bar ?x) ***************************************************************/ static EXPRESSION *GenerateSlotComparisonTest( int joinTest, struct lhsParseNode *selfNode, struct lhsParseNode *referringNode) { EXPRESSION *exp; struct ObjectCmpPNSingleSlotVars1 phack1; struct ObjectCmpPNSingleSlotVars2 phack2; struct ObjectCmpPNSingleSlotVars3 phack3; struct ObjectCmpJoinSingleSlotVars1 jhack1; struct ObjectCmpJoinSingleSlotVars2 jhack2; struct ObjectCmpJoinSingleSlotVars3 jhack3; /* ========================================================= If we are comparing two single-field slot variables that don't require multifield markers for lookup, use a quick comparison. Otherwise, use a general eq/neq with the pattern variable access routines ========================================================= */ if (IsSimpleSlotVariable(selfNode) && IsSimpleSlotVariable(referringNode)) { /* ============================== Compare two single-field slots ============================== */ if ((selfNode->withinMultifieldSlot == FALSE) && (referringNode->withinMultifieldSlot == FALSE)) { ClearBitString((void *) &phack1,(int) sizeof(struct ObjectCmpPNSingleSlotVars1)); ClearBitString((void *) &jhack1,(int) sizeof(struct ObjectCmpJoinSingleSlotVars1)); if (selfNode->negated) phack1.fail = jhack1.fail = 1; else phack1.pass = jhack1.pass = 1; phack1.firstSlot = jhack1.firstSlot = (unsigned) selfNode->slotNumber; phack1.secondSlot = jhack1.secondSlot = (unsigned) referringNode->slotNumber; if (joinTest) { jhack1.firstPattern = (unsigned) selfNode->pattern; jhack1.secondPattern = (unsigned) referringNode->pattern; exp = GenConstant(OBJ_JN_CMP1,AddBitMap((void *) &jhack1, (int) sizeof(struct ObjectCmpJoinSingleSlotVars1))); } else exp = GenConstant(OBJ_PN_CMP1,AddBitMap((void *) &phack1, (int) sizeof(struct ObjectCmpPNSingleSlotVars1))); } /* ============================================ Compare a single-field slot with a single-field in a multifield slot (make sure the multifield slot reference is first ============================================ */ else if ((selfNode->withinMultifieldSlot == FALSE) || (referringNode->withinMultifieldSlot == FALSE)) { ClearBitString((void *) &phack2,(int) sizeof(struct ObjectCmpPNSingleSlotVars2)); ClearBitString((void *) &jhack2,(int) sizeof(struct ObjectCmpJoinSingleSlotVars2)); if (selfNode->negated) phack2.fail = jhack2.fail = 1; else phack2.pass = jhack2.pass = 1; if (selfNode->withinMultifieldSlot == TRUE) { phack2.firstSlot = jhack2.firstSlot = (unsigned) selfNode->slotNumber; phack2.secondSlot = jhack2.secondSlot = (unsigned) referringNode->slotNumber; if (joinTest) { jhack2.firstPattern = (unsigned) selfNode->pattern; jhack2.secondPattern = (unsigned) referringNode->pattern; } if (selfNode->multiFieldsBefore == 0) { phack2.fromBeginning = jhack2.fromBeginning = 1; phack2.offset = jhack2.offset = selfNode->singleFieldsBefore; } else phack2.offset = jhack2.offset = selfNode->singleFieldsAfter; } else { phack2.firstSlot = jhack2.firstSlot = (unsigned) referringNode->slotNumber; phack2.secondSlot = jhack2.secondSlot = (unsigned) selfNode->slotNumber; if (joinTest) { jhack2.firstPattern = (unsigned) referringNode->pattern; jhack2.secondPattern = (unsigned) selfNode->pattern; } if (referringNode->multiFieldsBefore == 0) { phack2.fromBeginning = jhack2.fromBeginning = 1; phack2.offset = jhack2.offset = referringNode->singleFieldsBefore; } else phack2.offset = jhack2.offset = referringNode->singleFieldsAfter; } if (joinTest) exp = GenConstant(OBJ_JN_CMP2,AddBitMap((void *) &jhack2, (int) sizeof(struct ObjectCmpJoinSingleSlotVars2))); else exp = GenConstant(OBJ_PN_CMP2,AddBitMap((void *) &phack2, (int) sizeof(struct ObjectCmpPNSingleSlotVars2))); } /* =================================== Compare two single-field references within multifield slots =================================== */ else { ClearBitString((void *) &phack3,(int) sizeof(struct ObjectCmpPNSingleSlotVars3)); ClearBitString((void *) &jhack3,(int) sizeof(struct ObjectCmpJoinSingleSlotVars3)); if (selfNode->negated) phack3.fail = jhack3.fail = 1; else phack3.pass = jhack3.pass = 1; phack3.firstSlot = jhack3.firstSlot = (unsigned) selfNode->slotNumber; phack3.secondSlot = jhack3.secondSlot = (unsigned) referringNode->slotNumber; if (selfNode->multiFieldsBefore == 0) { phack3.firstFromBeginning = jhack3.firstFromBeginning = 1; phack3.firstOffset = jhack3.firstOffset = selfNode->singleFieldsBefore; } else phack3.firstOffset = jhack3.firstOffset = selfNode->singleFieldsAfter; if (referringNode->multiFieldsBefore == 0) { phack3.secondFromBeginning = jhack3.secondFromBeginning = 1; phack3.secondOffset = jhack3.secondOffset = referringNode->singleFieldsBefore; } else phack3.secondOffset = jhack3.secondOffset = referringNode->singleFieldsAfter; if (joinTest) { jhack3.firstPattern = (unsigned) selfNode->pattern; jhack3.secondPattern = (unsigned) referringNode->pattern; exp = GenConstant(OBJ_JN_CMP3,AddBitMap((void *) &jhack3, (int) sizeof(struct ObjectCmpJoinSingleSlotVars3))); } else exp = GenConstant(OBJ_PN_CMP3,AddBitMap((void *) &phack3, (int) sizeof(struct ObjectCmpPNSingleSlotVars3))); } } /* ================================================== General comparison for multifield slot references, references which require multifield markers, and object addresses ================================================== */ else { exp = GenConstant(FCALL,selfNode->negated ? PTR_NEQ : PTR_EQ); exp->argList = GenConstant(0,NULL); GenObjectGetVar(joinTest,exp->argList,selfNode); exp->argList->nextArg = GenConstant(0,NULL); GenObjectGetVar(joinTest,exp->argList->nextArg,referringNode); } return(exp); }