
cvc5-cvc5-1.2.0.src.expr.mkmetakind Maven / Gradle / Ivy
The newest version!
#!/usr/bin/env bash
#
# mkmetakind
# Morgan Deters for cvc5
# Copyright (c) 2010-2013 The cvc5 Project
#
# The purpose of this script is to create metakind.h from a template
# and a list of theory kinds.
#
# This is kept distinct from kind.h because kind.h is a public header
# and metakind.h is intended for the expr package only.
#
# Invocation:
#
# mkmetakind template-file theory-kind-files...
#
# Output is to standard out.
#
# Required to disable this option for bash >=5.2 to avoid automatically
# replacing & by the substituted text.
shopt | grep -q '^patsub_replacement\b' && shopt -u patsub_replacement
copyright=2010-2022
cat <&2
exit 1
fi
# this script doesn't care about the theory class information, but
# makes does make sure it's there
seen_theory=true
if [ "$1" = THEORY_BUILTIN ]; then
if $seen_theory_builtin; then
echo "$kf:$lineno: error: \"builtin\" theory redefined" >&2
exit 1
fi
seen_theory_builtin=true
elif [ -z "$1" -o -z "$2" -o -z "$3" ]; then
echo "$kf:$lineno: error: \"theory\" directive missing class or header argument" >&2
exit 1
elif ! expr "$2" : '\(::*\)' >/dev/null; then
echo "$kf:$lineno: warning: theory class \`$1' isn't fully-qualified (e.g., ::cvc5::internal::theory::foo)" >&2
elif ! expr "$2" : '\(::cvc5::internal::theory::*\)' >/dev/null; then
echo "$kf:$lineno: warning: theory class not under ::cvc5::internal::theory namespace" >&2
fi
theory_class=$1
metakind_includes="${metakind_includes}
// #include \"theory/$b/$2\""
}
function alternate {
# alternate ID name T header
lineno=${BASH_LINENO[0]}
if $seen_theory; then
echo "$kf:$lineno: error: multiple theories defined in one file !?" >&2
exit 1
fi
seen_theory=true
seen_endtheory=true
theory_id="$1"
name="$2"
theory_class="$3"
theory_header="$4"
theory_includes="${theory_includes}#include \"$theory_header\"
"
}
function properties {
# properties prop*
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function endtheory {
# endtheory
lineno=${BASH_LINENO[0]}
check_theory_seen
seen_endtheory=true
}
function enumerator {
# enumerator KIND enumerator-class header
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function typechecker {
# typechecker header
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function typerule {
# typerule OPERATOR typechecking-class
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function construle {
# construle OPERATOR isconst-checking-class
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function rewriter {
# rewriter class header
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function sort {
# sort TYPE cardinality [well-founded ground-term header | not-well-founded] ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function cardinality {
# cardinality TYPE cardinality-computer [header]
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function well-founded {
# well-founded TYPE wellfoundedness-computer [header]
lineno=${BASH_LINENO[0]}
check_theory_seen
}
function variable {
# variable K ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
register_metakind VARIABLE "$1" 0
}
function operator {
# operator K #children ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
register_metakind OPERATOR "$1" "$2"
}
function parameterized {
# parameterized K1 K2 #children ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
register_metakind PARAMETERIZED "$1" "$3"
if ! expr "$2" : '\[.*\]' &>/dev/null; then
registerOperatorToKind "$1" "$2"
fi
}
function constant {
# constant K F T Hasher header ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
if ! expr "$4" : '\(::*\)' >/dev/null; then
echo "$kf:$lineno: warning: constant $1 hasher \`$4' isn't fully-qualified (e.g., ::cvc5::internal::RationalHashFunction)" >&2
fi
if [[ "$3" =~ '+'$ ]]; then
# Remove last character
class="${3%?}"
skip_const_map=true
else
class="$3"
skip_const_map=false
fi
if contains "${class}" "${payloads_seen[@]}"; then
payload_seen=true
else
payload_seen=false
payloads_seen=(${payloads_seen[@]} "${class}")
fi
if [[ "$2" != "skip" ]]; then
metakind_fwd_decls="${metakind_fwd_decls}
$2 ${class};"
fi
# Avoid including the same header multiple times
if [ -n "$5" ] && [[ "${metakind_includes}" != *"#include \"$5\""* ]]; then
metakind_includes="${metakind_includes}
#include \"$5\""
fi
register_metakind CONSTANT "$1" 0
if [[ "${payload_seen}" != true ]]; then
metakind_constantMaps="${metakind_constantMaps}
// The reinterpret_cast of d_children to \"${class} const*\"
// flags a \"strict aliasing\" warning; it's okay, because we never access
// the embedded constant as a NodeValue* child, and never access an embedded
// NodeValue* child as a constant.
#pragma GCC diagnostic ignored \"-Wstrict-aliasing\"
template <>
${class} const& NodeValue::getConst< ${class} >() const {
//AssertArgument(getKind() == ::cvc5::internal::Kind::$1, *this,
// \"Improper kind for getConst<${class}>()\");
// To support non-inlined CONSTANT-kinded NodeValues (those that are
// \"constructed\" when initially checking them against the NodeManager
// pool), we must check d_nchildren here.
return d_nchildren == 0
? *reinterpret_cast< ${class} const* >(d_children)
: *reinterpret_cast< ${class} const* >(d_children[0]);
}
// re-enable the warning
#pragma GCC diagnostic warning \"-Wstrict-aliasing\"
"
fi
if [ "${skip_const_map}" != true ]; then
metakind_mkConst="${metakind_mkConst}
template<>
Node NodeManager::mkConst<${class}>(const ${class}& val)
{
return mkConstInternal(::cvc5::internal::Kind::$1, val);
}
"
metakind_mkConst="${metakind_mkConst}
template<>
Node NodeManager::mkConst(Kind k, const ${class}& val)
{
return mkConstInternal(k, val);
}
"
elif [[ "${payload_seen}" != true ]]; then
metakind_mkConstDelete="${metakind_mkConstDelete}
template<>
Node NodeManager::mkConst<${class}>(const ${class}& val) = delete;
"
metakind_mkConst="${metakind_mkConst}
template<>
Node NodeManager::mkConst(Kind k, const ${class}& val)
{
return mkConstInternal(k, val);
}
"
fi
metakind_compares="${metakind_compares}
case Kind::$1:
return NodeValueConstCompare::compare(nv1, nv2);
"
metakind_constHashes="${metakind_constHashes}
case Kind::$1:
return $4()(nv->getConst< ${class} >());
"
metakind_constPrinters="${metakind_constPrinters}
case Kind::$1:
out << nv->getConst< ${class} >();
break;
"
cname=`echo "${class}" | awk 'BEGIN {FS="::"} {print$NF}'`
metakind_constDeleters="${metakind_constDeleters}
case Kind::$1:
std::destroy_at(reinterpret_cast< ${class}* >(nv->d_children));
break;
"
}
function nullaryoperator {
# nullaryoperator K ["comment"]
lineno=${BASH_LINENO[0]}
check_theory_seen
register_metakind NULLARY_OPERATOR "$1" 0
}
function registerOperatorToKind {
operatorKind=$1
applyKind=$2
metakind_operatorKinds="${metakind_operatorKinds}
case Kind::$applyKind: return Kind::$operatorKind;";
}
function register_metakind {
mk=$1
k=$2
nc=$3
metakind_kinds="${metakind_kinds} metakind::$mk, /* $k */
";
# figure out the range given by $nc
if expr "$nc" : '[0-9][0-9]*$' >/dev/null; then
lb=$nc
ub=$nc
elif expr "$nc" : '[0-9][0-9]*:$' >/dev/null; then
let `echo "$nc" | awk 'BEGIN{FS=":"}{print"lb="$1}'`
ub="expr::NodeValue::MAX_CHILDREN"
elif expr "$nc" : '[0-9][0-9]*:[0-9][0-9]*$' >/dev/null; then
let `echo "$nc" | awk 'BEGIN{FS=":"}{print"lb="$1" ub="$2}'`
if [ $ub -lt $lb ]; then
echo "$kf:$lineno: error in range \`$nc': LB < UB (in definition of $k)" >&2
exit 1
fi
else
echo "$kf:$lineno: can't parse range \`$nc' in definition of $k" >&2
exit 1
fi
metakind_lbchildren="${metakind_lbchildren}
$lb, /* $k */"
metakind_ubchildren="${metakind_ubchildren}
$ub, /* $k */"
}
# Returns 0 if arg is a primitive C++ type, or a pointer to same; 1
# otherwise. Really all this does is check whether we should issue a
# "not fully qualified" warning or not.
function primitive_type {
strip=`expr "$1" : ' *\(.*\)\* *'`
if [ -n "$strip" ]; then
primitive_type "$strip" >&2
return $?
fi
case "$1" in
bool|int|size_t|long|void|char|float|double) return 0;;
*) return 1;;
esac
}
function check_theory_seen {
if $seen_endtheory; then
echo "$kf:$lineno: error: command after \"endtheory\" declaration (endtheory has to be last)" >&2
exit 1
fi
if ! $seen_theory; then
echo "$kf:$lineno: error: no \"theory\" declaration found (it has to be first)" >&2
exit 1
fi
}
function check_builtin_theory_seen {
if ! $seen_theory_builtin; then
echo "$me: warning: no declaration for the builtin theory found" >&2
fi
}
while [ $# -gt 0 ]; do
kf=$1
seen_theory=false
seen_endtheory=false
b=$(basename $(dirname "$kf"))
metakind_kinds="${metakind_kinds}
/* from $b */
"
metakind_operatorKinds="${metakind_operatorKinds}
/* from $b */"
source "$kf"
if ! $seen_theory; then
echo "$kf: error: no theory content found in file!" >&2
exit 1
fi
if ! $seen_endtheory; then
echo "$kf:$lineno: error: no \"endtheory\" declaration found (it is required at the end)" >&2
exit 1
fi
shift
done
check_builtin_theory_seen
## output
text=$(cat "$template")
for var in \
metakind_fwd_decls \
metakind_includes \
metakind_kinds \
metakind_constantMaps \
metakind_compares \
metakind_constHashes \
metakind_constPrinters \
metakind_constDeleters \
metakind_ubchildren \
metakind_lbchildren \
metakind_operatorKinds \
metakind_mkConst \
metakind_mkConstDelete \
template \
; do
eval text="\${text//\\\$\\{$var\\}/\${$var}}"
done
error=`expr "$text" : '.*\${\([^}]*\)}.*'`
if [ -n "$error" ]; then
echo "$template:0: error: undefined replacement \${$error}" >&2
exit 1
fi
echo "$text"
© 2015 - 2025 Weber Informatics LLC | Privacy Policy