int OGRGeomFieldDefn::IsSame( OGRGeomFieldDefn * poOtherFieldDefn ) { if( !(strcmp(GetNameRef(), poOtherFieldDefn->GetNameRef()) == 0 && GetType() == poOtherFieldDefn->GetType() && IsNullable() == poOtherFieldDefn->IsNullable()) ) return FALSE; OGRSpatialReference* poMySRS = GetSpatialRef(); OGRSpatialReference* poOtherSRS = poOtherFieldDefn->GetSpatialRef(); return ((poMySRS == poOtherSRS) || (poMySRS != NULL && poOtherSRS != NULL && poMySRS->IsSame(poOtherSRS))); }
// Load a given column for the row with the given TID codegen::Value TileGroup::LoadColumn( CodeGen &codegen, llvm::Value *tid, const TileGroup::ColumnLayout &layout) const { // We're calculating: col[tid] = col_start + (tid * col_stride) llvm::Value *col_address = codegen->CreateInBoundsGEP(codegen.ByteType(), layout.col_start_ptr, codegen->CreateMul(tid, layout.col_stride)); // The value, length and is_null check llvm::Value *val = nullptr, *length = nullptr, *is_null = nullptr; // Column metadata bool is_nullable = schema_.AllowNull(layout.col_id); const auto &column = schema_.GetColumn(layout.col_id); const auto &sql_type = type::SqlType::LookupType(column.GetType()); // Check if it's a string or numeric value if (sql_type.IsVariableLength()) { auto *varlen_type = VarlenProxy::GetType(codegen); auto *varlen_ptr_ptr = codegen->CreateBitCast( col_address, varlen_type->getPointerTo()->getPointerTo()); if (is_nullable) { codegen::Varlen::GetPtrAndLength( codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length, is_null); } else { codegen::Varlen::SafeGetPtrAndLength( codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length); } PL_ASSERT(val != nullptr && length != nullptr); } else { // Get the LLVM type of the column llvm::Type *col_type = nullptr, *col_len_type = nullptr; sql_type.GetTypeForMaterialization(codegen, col_type, col_len_type); PL_ASSERT(col_type != nullptr && col_len_type == nullptr); // val = *(col_type*)col_address; val = codegen->CreateLoad( col_type, codegen->CreateBitCast(col_address, col_type->getPointerTo())); if (is_nullable) { // To check for NULL, we need to perform a comparison between the value we // just read from the table with the NULL value for the column's type. We // need to be careful that the runtime type of both values is not NULL to // bypass the type system's NULL checking logic. if (sql_type.TypeId() == peloton::type::TypeId::BOOLEAN) { is_null = type::Boolean::Instance().CheckNull(codegen, col_address); } else { auto val_tmp = codegen::Value{sql_type, val}; auto null_val = codegen::Value{sql_type, sql_type.GetNullValue(codegen).GetValue()}; auto val_is_null = val_tmp.CompareEq(codegen, null_val); PL_ASSERT(!val_is_null.IsNullable()); is_null = val_is_null.GetValue(); } } } // Names val->setName(column.GetName()); if (length != nullptr) length->setName(column.GetName() + ".len"); if (is_null != nullptr) is_null->setName(column.GetName() + ".null"); // Return the value auto type = type::Type{column.GetType(), is_nullable}; return codegen::Value{type, val, length, is_null}; }
codegen::type::Type AbstractExpression::ResultType() const { return codegen::type::Type{GetValueType(), IsNullable()}; }
/* function closure(I): begin repeat for each item [A -> a*ZB, a] in I, each production Z -> y in G', and each terminal b in FIRST(Ba) such that [Z -> *y, b] is not in I do add [Z -> *y, b] to I; until no more items can be added to I; return I end; */ LR_ITEM_SET* Closure(LR_ITEM_SET* I, GRAMMAR_TABLE* G) { // J := I; LR_ITEM_SET* J = CopyItemSet(I); // repeat int stillAdding; do { stillAdding = 0; // for each item [A -> a*ZB, a] in J, LR_ITEM_SET* itr; for (itr = J; itr; itr = itr->next) { LR_ITEM item = itr->item; RULE rule = G->rules[item.production]; if (item.dot < rule.rhsLength) { int Z = rule.rhs[item.dot]; // each production Z -> y in G', int i; for (i = 0; i < G->numRules; i++) { if (G->rules[i].lhs == Z) { // and each terminal b in FIRST(Ba) int B = (item.dot + 1 < rule.rhsLength) ? rule.rhs[item.dot + 1] : 0; int b; for (b = 0; b < G->numTokens; b++) { int terminal = (b + 1) | K_TOKEN; if ((B && GetFirstTable(B, terminal, G) == 1) || ((!B || IsNullable(B)) && GetFirstTable(item.lookahead, terminal, G) == 1)) { // such that [Z -> *y, b] is not in J do LR_ITEM add; add.production = i; add.dot = 0; add.lookahead = terminal; LR_ITEM_SET* find; for (find = J; find; find = find->next) { if (CompareItems(find->item, add) == 0) break; } if (find == NULL) { // add [Z -> *y, b] to J; find = malloc(sizeof(LR_ITEM_SET)); find->item = add; find->next = J; J = find; stillAdding = 1; } } } } } } } // until no more items can be added to J; } while (stillAdding); // return J return Sort(J); }
// construct FOLLOW sets void BuildFollowSets(GRAMMAR_TABLE* G) { RULE rule; int finished; int i, j, p, r; FOLLOW_SETS = malloc(sizeof(int) * G->numTokens * G->numSymbols); // clear follow map for (i = 0; i < G->numTokens * G->numSymbols; i++) FOLLOW_SETS[i] = 0; // add goal SetFollowTable(gSymbolGoal, gSymbolEOF, 1, G); // go through productions and construct follow sets for the rhs int changing; do { changing = 0; for (p = 0; p < G->numRules; p++) { rule = G->rules[p]; int left = rule.lhs; // compute follow for all of the rhs terms for (r = 0; r < rule.rhsLength; r++) { int symbol = rule.rhs[r]; if (symbol & K_SYMBOL) { for (j = r+1; j < rule.rhsLength; j++) { // add following tokens to the follow set if (rule.rhs[j] & K_TOKEN) { if (SetFollowTable(symbol, rule.rhs[j], 1, G)) changing = 1; break; } // for following symbols, add the first set for (i = 1; i <= G->numTokens; i++) { if (GetFirstTable(rule.rhs[j], i | K_TOKEN, G) == 1 && SetFollowTable(symbol, i | K_TOKEN, 1, G)) { changing = 1; } } // continue while nullable if (!IsNullable(rule.rhs[j])) break; } // add all from the follow set of the lhs if (j == rule.rhsLength) { for (i = 1; i <= G->numTokens; i++) { if (GetFollowTable(left, i | K_TOKEN, G) == 1 && SetFollowTable(symbol, i | K_TOKEN, 1, G)) { changing = 1; } } } } } } } while (changing); }
// construct FIRST sets void BuildFirstSets(GRAMMAR_TABLE* G) { int finished; int symbol, i, p, r; RULE rule; FIRST_SETS = malloc(sizeof(int) * G->numTokens * G->numSymbols); // clear first map for (i = 0; i < G->numTokens * G->numSymbols; i++) FIRST_SETS[i] = 0; // map nullable nonterminals to epsilon for (symbol = 0; symbol < G->numSymbols; symbol++) { if (IsNullable(symbol)) { SetFirstTable(symbol, gSymbolEpsilon, 1, G); } } // join first sets from production rules while they continue to change int changing; do { changing = 0; for (p = 0; p < G->numRules; p++) { RULE rule = G->rules[p]; int left = rule.lhs; for (r = 0; r < rule.rhsLength; r++) { // terminal if (rule.rhs[r] & K_TOKEN) { if (SetFirstTable(left, rule.rhs[r], 1, G)) changing = 1; break; } // add symbols from table for (i = 1; i <= G->numSymbols; i++) { if (GetFirstTable(rule.rhs[r], i | K_SYMBOL, G) == 1 && SetFirstTable(left, i | K_SYMBOL, 1, G)) { changing = 1; } } // add tokens from table for (i = 1; i <= G->numTokens; i++) { if (GetFirstTable(rule.rhs[r], i | K_TOKEN, G) == 1 && SetFirstTable(left, i | K_TOKEN, 1, G)) { changing = 1; } } // continue only if it's nullable if (!IsNullable(rule.rhs[r])) break; } } } while (changing); }