MCPcopy Create free account
hub / github.com/bytedance/bolt / isDeterministic

Function isDeterministic

bolt/expression/fuzzer/ExpressionFuzzer.cpp:361–413  ·  view source on GitHub ↗

Returns if `functionName` with the given `argTypes` is deterministic. Returns true if the function was not found or determinism cannot be established.

Source from the content-addressed store, hash-verified

359/// Returns true if the function was not found or determinism cannot be
360/// established.
361bool isDeterministic(
362 const std::string& functionName,
363 const std::vector<TypePtr>& argTypes) {
364 // We know that the 'cast', 'and', and 'or' special forms are deterministic.
365 // Hard-code them here because they are not real functions and hence cannot
366 // be resolved by the code below.
367 if (functionName == "and" || functionName == "or" ||
368 functionName == "coalesce" || functionName == "if" ||
369 functionName == "switch" || functionName == "cast") {
370 return true;
371 }
372
373 // Check if this is a simple function.
374 if (auto simpleFunctionEntry =
375 exec::simpleFunctions().resolveFunction(functionName, argTypes)) {
376 return simpleFunctionEntry->getMetadata().isDeterministic();
377 }
378
379 // Vector functions are a bit more complicated. We need to fetch the list of
380 // available signatures and check if any of them bind given the current
381 // input arg types. If it binds (if there's a match), we fetch the function
382 // and return the isDeterministic bool.
383 try {
384 if (auto vectorFunctionSignatures =
385 exec::getVectorFunctionSignatures(functionName)) {
386 core::QueryConfig config({});
387 for (const auto& signature : *vectorFunctionSignatures) {
388 if (exec::SignatureBinder(*signature, argTypes).tryBind()) {
389 if (auto vectorFunction =
390 exec::getVectorFunction(functionName, argTypes, {}, config)) {
391 return vectorFunction->isDeterministic();
392 }
393 }
394 }
395 }
396 }
397 // TODO: Some stateful functions can only be built when constant arguments
398 // are passed, making the getVectorFunction() call above to throw. We only
399 // have a few of these functions, so for now we assume they are
400 // deterministic so they are picked for Fuzz testing. Once we make the
401 // isDeterministic() flag static (and hence we won't need to build the
402 // function object in here) we can clean up this code.
403 catch (const std::exception& e) {
404 LOG(WARNING) << "Unable to determine if '" << functionName
405 << "' is deterministic or not. Assuming it is.";
406 return true;
407 }
408
409 // functionName must be a special form.
410 LOG(WARNING) << "Unable to determine if '" << functionName
411 << "' is deterministic or not. Assuming it is.";
412 return true;
413}
414
415std::optional<CallableSignature> processConcreteSignature(
416 const std::string& functionName,

Callers 2

isConstantMethod · 0.85
ExpressionFuzzerMethod · 0.85

Calls 7

SignatureBinderClass · 0.85
getVectorFunctionFunction · 0.85
resolveFunctionMethod · 0.80
getMetadataMethod · 0.80
isDeterministicMethod · 0.45
tryBindMethod · 0.45

Tested by

no test coverage detected