void CSharpGotoCodeGen::emitSingleSwitch( RedStateAp *state ) { /* Load up the singles. */ int numSingles = state->outSingle.length(); RedTransEl *data = state->outSingle.data; if ( numSingles == 1 ) { /* If there is a single single key then write it out as an if. */ out << L"\tif ( " << GET_WIDE_KEY(state) << L" == " << KEY(data[0].lowKey) << L" )\n\t\t"; /* Virtual function for writing the target of the transition. */ TRANS_GOTO(data[0].value, 0) << L"\n"; } else if ( numSingles > 1 ) { /* Write out single keys in a switch if there is more than one. */ out << L"\tswitch( " << GET_WIDE_KEY(state) << L" ) {\n"; /* Write out the single indicies. */ for ( int j = 0; j < numSingles; j++ ) { out << L"\t\tcase " << ALPHA_KEY(data[j].lowKey) << L": "; TRANS_GOTO(data[j].value, 0) << L"\n"; } /* Emits a default case for D code. */ SWITCH_DEFAULT(); /* Close off the transition switch. */ out << L"\t}\n"; } }
void CSharpFlatCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n"; out << " _keys = " << vCS() << "<<1;\n" " _conds = " << CO() << "[" << vCS() << "];\n" // " _keys = " << ARR_OFF( CK(), "(" + vCS() + "<<1)" ) << ";\n" // " _conds = " << ARR_OFF( C(), CO() + "[" + vCS() + "]" ) << ";\n" "\n" " _slen = " << CSP() << "[" << vCS() << "];\n" " if (_slen > 0 && " << CK() << "[_keys] <=" << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1])\n" " _cond = " << C() << "[_conds+" << GET_WIDE_KEY() << " - " << CK() << "[_keys]];\n" " else\n" " _cond = 0;" "\n"; /* XXX This version of the code doesn't work because Mono is weird. Works * fine in Microsoft's csc, even though the bug report filed claimed it * didn't. " _slen = " << CSP() << "[" << vCS() << "];\n" " _cond = _slen > 0 && " << CK() << "[_keys] <=" << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1] ?\n" " " << C() << "[_conds+" << GET_WIDE_KEY() << " - " << CK() << "[_keys]] : 0;\n" "\n"; */ out << " switch ( _cond ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId + 1 << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " }\n"; out << " break;\n"; } SWITCH_DEFAULT(); out << " }\n"; }
void CSharpTabCodeGen::LOCATE_TRANS() { out << " _keys = " << KO() + "[" + vCS() + "]" << ";\n" " _trans = " << CAST(transType) << IO() << "[" << vCS() << "];\n" "\n" " _klen = " << SL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + _klen - 1);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + ((_upper-_lower) >> 1));\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 1);\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 1);\n" " else {\n" " _trans += " << CAST(transType) << " (_mid - _keys);\n" " goto _match;\n" " }\n" " }\n" " _keys += " << CAST(keysType) << " _klen;\n" " _trans += " << CAST(transType) << " _klen;\n" " }\n" "\n" " _klen = " << RL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + (_klen<<1) - 2);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + (((_upper-_lower) >> 1) & ~1));\n" " if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n" " else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n" " else {\n" " _trans += " << CAST(transType) << "((_mid - _keys)>>1);\n" " goto _match;\n" " }\n" " }\n" " _trans += " << CAST(transType) << " _klen;\n" " }\n" "\n"; }
void CSharpTabCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n" " _klen = " << CL() << "[" << vCS() << "];\n" " _keys = " << CAST(keysType) << " ("<< CO() << "[" << vCS() << "]*2);\n" " if ( _klen > 0 ) {\n" " " << signedKeysType << " _lower = _keys;\n" " " << signedKeysType << " _mid;\n" " " << signedKeysType << " _upper = " << CAST(signedKeysType) << " (_keys + (_klen<<1) - 2);\n" " while (true) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = " << CAST(signedKeysType) << " (_lower + (((_upper-_lower) >> 1) & ~1));\n" " if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n" " _upper = " << CAST(signedKeysType) << " (_mid - 2);\n" " else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n" " _lower = " << CAST(signedKeysType) << " (_mid + 2);\n" " else {\n" " switch ( " << C() << "[" << CO() << "[" << vCS() << "]" " + ((_mid - _keys)>>1)] ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " break;\n" " }\n"; } SWITCH_DEFAULT(); out << " }\n" " break;\n" " }\n" " }\n" " }\n" "\n"; }
void FlatCodeGen::LOCATE_TRANS() { out << " _keys = " << ARR_OFF( K(), "(" + vCS() + "<<1)" ) << ";\n" " _inds = " << ARR_OFF( I(), IO() + "[" + vCS() + "]" ) << ";\n" "\n" " _slen = " << SP() << "[" << vCS() << "];\n" " _trans = _inds[ _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= _keys[1] ?\n" " " << GET_WIDE_KEY() << " - _keys[0] : _slen ];\n" "\n"; }
void TabCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n" " _klen = " << CL() << "[" << vCS() << "];\n" " _keys = " << ARR_OFF( CK(), "(" + CO() + "[" + vCS() + "]*2)" ) << ";\n" " if ( _klen > 0 ) {\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + (_klen<<1) - 2;\n" " while (1) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n" " if ( " << GET_WIDE_KEY() << " < _mid[0] )\n" " _upper = _mid - 2;\n" " else if ( " << GET_WIDE_KEY() << " > _mid[1] )\n" " _lower = _mid + 2;\n" " else {\n" " switch ( " << C() << "[" << CO() << "[" << vCS() << "]" " + ((_mid - _keys)>>1)] ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " break;\n" " }\n"; } SWITCH_DEFAULT(); out << " }\n" " break;\n" " }\n" " }\n" " }\n" "\n"; }
void TabCodeGen::LOCATE_TRANS() { out << " _keys = " << ARR_OFF( K(), KO() + "[" + vCS() + "]" ) << ";\n" " _trans = " << IO() << "[" << vCS() << "];\n" "\n" " _klen = " << SL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + _klen - 1;\n" " while (1) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + ((_upper-_lower) >> 1);\n" " if ( " << GET_WIDE_KEY() << " < *_mid )\n" " _upper = _mid - 1;\n" " else if ( " << GET_WIDE_KEY() << " > *_mid )\n" " _lower = _mid + 1;\n" " else {\n" " _trans += " << CAST(UINT()) << "(_mid - _keys);\n" " goto _match;\n" " }\n" " }\n" " _keys += _klen;\n" " _trans += _klen;\n" " }\n" "\n" " _klen = " << RL() << "[" << vCS() << "];\n" " if ( _klen > 0 ) {\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_lower = _keys;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_mid;\n" " " << PTR_CONST() << WIDE_ALPH_TYPE() << PTR_CONST_END() << POINTER() << "_upper = _keys + (_klen<<1) - 2;\n" " while (1) {\n" " if ( _upper < _lower )\n" " break;\n" "\n" " _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n" " if ( " << GET_WIDE_KEY() << " < _mid[0] )\n" " _upper = _mid - 2;\n" " else if ( " << GET_WIDE_KEY() << " > _mid[1] )\n" " _lower = _mid + 2;\n" " else {\n" " _trans += " << CAST(UINT()) << "((_mid - _keys)>>1);\n" " goto _match;\n" " }\n" " }\n" " _trans += _klen;\n" " }\n" "\n"; }
void CSharpFlatCodeGen::LOCATE_TRANS() { out << " _keys = " << vCS() << "<<1;\n" " _inds = " << IO() << "[" << vCS() << "];\n" "\n" " _slen = " << SP() << "[" << vCS() << "];\n" " _trans = " << I() << "[_inds + (\n" " _slen > 0 && " << K() << "[_keys] <=" << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= " << K() <<"[_keys+1] ?\n" " " << GET_WIDE_KEY() << " - " << K() << "[_keys] : _slen ) ];\n" "\n"; }
void OCamlTabCodeGen::LOCATE_TRANS() { out << " state.keys <- " << AT( KO(), vCS() ) << ";\n" " state.trans <- " << CAST(transType) << AT( IO(), vCS() ) << ";\n" "\n" " let klen = " << AT( SL(), vCS() ) << " in\n" " if klen > 0 then begin\n" " let lower : " << signedKeysType << " ref = ref state.keys in\n" " let upper : " << signedKeysType << " ref = ref " << CAST(signedKeysType) << "(state.keys + klen - 1) in\n" " while !upper >= !lower do\n" " let mid = " << CAST(signedKeysType) << " (!lower + ((!upper - !lower) / 2)) in\n" " if " << GET_WIDE_KEY() << " < " << AT( K(), "mid" ) << " then\n" " upper := " << CAST(signedKeysType) << " (mid - 1)\n" " else if " << GET_WIDE_KEY() << " > " << AT( K(), "mid" ) << " then\n" " lower := " << CAST(signedKeysType) << " (mid + 1)\n" " else begin\n" " state.trans <- state.trans + " << CAST(transType) << " (mid - state.keys);\n" " raise Goto_match;\n" " end\n" " done;\n" " state.keys <- state.keys + " << CAST(keysType) << " klen;\n" " state.trans <- state.trans + " << CAST(transType) << " klen;\n" " end;\n" "\n" " let klen = " << AT( RL(), vCS() ) << " in\n" " if klen > 0 then begin\n" " let lower : " << signedKeysType << " ref = ref state.keys in\n" " let upper : " << signedKeysType << " ref = ref " << CAST(signedKeysType) << "(state.keys + (klen * 2) - 2) in\n" " while !upper >= !lower do\n" " let mid = " << CAST(signedKeysType) << " (!lower + (((!upper - !lower) / 2) land (lnot 1))) in\n" " if " << GET_WIDE_KEY() << " < " << AT( K() , "mid" ) << " then\n" " upper := " << CAST(signedKeysType) << " (mid - 2)\n" " else if " << GET_WIDE_KEY() << " > " << AT( K(), "mid+1" ) << " then\n" " lower := " << CAST(signedKeysType) << " (mid + 2)\n" " else begin\n" " state.trans <- state.trans + " << CAST(transType) << "((mid - state.keys) / 2);\n" " raise Goto_match;\n" " end\n" " done;\n" " state.trans <- state.trans + " << CAST(transType) << " klen;\n" " end;\n" "\n"; }
void FlatCodeGen::COND_TRANSLATE() { out << " _widec = " << GET_KEY() << ";\n"; out << " _keys = " << ARR_OFF( CK(), "(" + vCS() + "<<1)" ) << ";\n" " _conds = " << ARR_OFF( C(), CO() + "[" + vCS() + "]" ) << ";\n" "\n" " _slen = " << CSP() << "[" << vCS() << "];\n" " _cond = _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n" " " << GET_WIDE_KEY() << " <= _keys[1] ?\n" " _conds[" << GET_WIDE_KEY() << " - _keys[0]] : 0;\n" "\n"; out << " switch ( _cond ) {\n"; for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) { GenCondSpace *condSpace = csi; out << " case " << condSpace->condSpaceId + 1 << ": {\n"; out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" << KEY(condSpace->baseKey) << " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << "));\n"; for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) { out << TABS(2) << "if ( "; CONDITION( out, *csi ); Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize()); out << " ) _widec += " << condValOffset << ";\n"; } out << " }\n"; out << " break;\n"; } SWITCH_DEFAULT(); out << " }\n"; }
void CSharpGotoCodeGen::emitRangeBSearch( RedStateAp *state, int level, int low, int high ) { /* Get the mid position, staying on the lower end of the range. */ int mid = (low + high) >> 1; RedTransEl *data = state->outRange.data; /* Determine if we need to look higher or lower. */ bool anyLower = mid > low; bool anyHigher = mid < high; /* Determine if the keys at mid are the limits of the alphabet. */ bool limitLow = data[mid].lowKey == keyOps->minKey; bool limitHigh = data[mid].highKey == keyOps->maxKey; if ( anyLower && anyHigher ) { /* Can go lower and higher than mid. */ out << TABS(level) << L"if ( " << GET_WIDE_KEY(state) << L" < " << KEY(data[mid].lowKey) << L" ) {\n"; emitRangeBSearch( state, level+1, low, mid-1 ); out << TABS(level) << L"} else if ( " << GET_WIDE_KEY(state) << L" > " << KEY(data[mid].highKey) << L" ) {\n"; emitRangeBSearch( state, level+1, mid+1, high ); out << TABS(level) << L"} else\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else if ( anyLower && !anyHigher ) { /* Can go lower than mid but not higher. */ out << TABS(level) << L"if ( " << GET_WIDE_KEY(state) << L" < " << KEY(data[mid].lowKey) << L" ) {\n"; emitRangeBSearch( state, level+1, low, mid-1 ); /* if the higher is the highest in the alphabet then there is no * sense testing it. */ if ( limitHigh ) { out << TABS(level) << L"} else\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else { out << TABS(level) << L"} else if ( " << GET_WIDE_KEY(state) << L" <= " << KEY(data[mid].highKey) << L" )\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } } else if ( !anyLower && anyHigher ) { /* Can go higher than mid but not lower. */ out << TABS(level) << L"if ( " << GET_WIDE_KEY(state) << L" > " << KEY(data[mid].highKey) << L" ) {\n"; emitRangeBSearch( state, level+1, mid+1, high ); /* If the lower end is the lowest in the alphabet then there is no * sense testing it. */ if ( limitLow ) { out << TABS(level) << L"} else\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else { out << TABS(level) << L"} else if ( " << GET_WIDE_KEY(state) << L" >= " << KEY(data[mid].lowKey) << L" )\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } } else { /* Cannot go higher or lower than mid. It's mid or bust. What * tests to do depends on limits of alphabet. */ if ( !limitLow && !limitHigh ) { out << TABS(level) << L"if ( " << KEY(data[mid].lowKey) << L" <= " << GET_WIDE_KEY(state) << L" && " << GET_WIDE_KEY(state) << L" <= " << KEY(data[mid].highKey) << L" )\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else if ( limitLow && !limitHigh ) { out << TABS(level) << L"if ( " << GET_WIDE_KEY(state) << L" <= " << KEY(data[mid].highKey) << L" )\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else if ( !limitLow && limitHigh ) { out << TABS(level) << L"if ( " << KEY(data[mid].lowKey) << L" <= " << GET_WIDE_KEY(state) << L" )\n"; TRANS_GOTO(data[mid].value, level+1) << L"\n"; } else { /* Both high and low are at the limit. No tests to do. */ TRANS_GOTO(data[mid].value, level+1) << L"\n"; } } }