Skip to content

Commit 1e8ff49

Browse files
committed
Transform many package related facts to use a nested function
Each fact that is deduced from package rules, and start with a bare package atom, is transformed into a "facts" atom containing a nested function. For instance we transformed version_declared(Package, ...) -> facts(Package, version_declared(...)) This allows us to clearly mark facts that represent a rule on the package, and will be of help later when we'll have to distinguish the cases where the atom "Package" is being used referred to package rules and not to a node in the DAG.
1 parent d1bc4c4 commit 1e8ff49

File tree

3 files changed

+141
-112
lines changed

3 files changed

+141
-112
lines changed

lib/spack/spack/solver/asp.py

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ def argify(arg):
303303
return clingo.String(str(arg))
304304
elif isinstance(arg, int):
305305
return clingo.Number(arg)
306+
elif isinstance(arg, AspFunction):
307+
return clingo.Function(arg.name, [argify(x) for x in arg.args], positive=positive)
306308
else:
307309
return clingo.String(str(arg))
308310

@@ -919,16 +921,20 @@ def key_fn(version):
919921
)
920922

921923
for weight, declared_version in enumerate(most_to_least_preferred):
924+
# TODO: self.package_fact(pkg.name).version_declared(declared_version, weight=weight)
922925
self.gen.fact(
923-
fn.version_declared(
924-
pkg.name, declared_version.version, weight, str(declared_version.origin)
926+
fn.facts(
927+
pkg.name,
928+
fn.version_declared(
929+
declared_version.version, weight, str(declared_version.origin)
930+
),
925931
)
926932
)
927933

928934
# Declare deprecated versions for this package, if any
929935
deprecated = self.deprecated_versions[pkg.name]
930936
for v in sorted(deprecated):
931-
self.gen.fact(fn.deprecated_version(pkg.name, v))
937+
self.gen.fact(fn.facts(pkg.name, fn.deprecated_version(v)))
932938

933939
def spec_versions(self, spec):
934940
"""Return list of clauses expressing spec's version constraints."""
@@ -971,7 +977,9 @@ def conflict_rules(self, pkg):
971977
conflict_msg = default_msg.format(pkg.name, trigger, constraint)
972978
constraint_msg = "conflict constraint %s" % str(constraint)
973979
constraint_id = self.condition(constraint, name=pkg.name, msg=constraint_msg)
974-
self.gen.fact(fn.conflict(pkg.name, trigger_id, constraint_id, conflict_msg))
980+
self.gen.fact(
981+
fn.facts(pkg.name, fn.conflict(trigger_id, constraint_id, conflict_msg))
982+
)
975983
self.gen.newline()
976984

977985
def compiler_facts(self):
@@ -1024,8 +1032,11 @@ def package_compiler_defaults(self, pkg):
10241032

10251033
for i, compiler in enumerate(reversed(matches)):
10261034
self.gen.fact(
1027-
fn.node_compiler_preference(
1028-
pkg.name, compiler.spec.name, compiler.spec.version, -i * 100
1035+
fn.facts(
1036+
pkg.name,
1037+
fn.node_compiler_preference(
1038+
compiler.spec.name, compiler.spec.version, -i * 100
1039+
),
10291040
)
10301041
)
10311042

@@ -1120,7 +1131,7 @@ def pkg_rules(self, pkg, tests):
11201131

11211132
if spack.spec.Spec() in when:
11221133
# unconditional variant
1123-
self.gen.fact(fn.variant(pkg.name, name))
1134+
self.gen.fact(fn.facts(pkg.name, fn.variant(name)))
11241135
else:
11251136
# conditional variant
11261137
for w in when:
@@ -1129,19 +1140,23 @@ def pkg_rules(self, pkg, tests):
11291140
msg += " when %s" % w
11301141

11311142
cond_id = self.condition(w, name=pkg.name, msg=msg)
1132-
self.gen.fact(fn.variant_condition(cond_id, pkg.name, name))
1143+
self.gen.fact(fn.facts(pkg.name, fn.conditional_variant(cond_id, name)))
11331144

11341145
single_value = not variant.multi
11351146
if single_value:
1136-
self.gen.fact(fn.variant_single_value(pkg.name, name))
1147+
self.gen.fact(fn.facts(pkg.name, fn.variant_single_value(name)))
11371148
self.gen.fact(
1138-
fn.variant_default_value_from_package_py(pkg.name, name, variant.default)
1149+
fn.facts(
1150+
pkg.name, fn.variant_default_value_from_package_py(name, variant.default)
1151+
)
11391152
)
11401153
else:
11411154
spec_variant = variant.make_default()
11421155
defaults = spec_variant.value
11431156
for val in sorted(defaults):
1144-
self.gen.fact(fn.variant_default_value_from_package_py(pkg.name, name, val))
1157+
self.gen.fact(
1158+
fn.facts(pkg.name, fn.variant_default_value_from_package_py(name, val))
1159+
)
11451160

11461161
values = variant.values
11471162
if values is None:
@@ -1152,7 +1167,9 @@ def pkg_rules(self, pkg, tests):
11521167
for sid, s in enumerate(values.sets):
11531168
for value in s:
11541169
self.gen.fact(
1155-
fn.variant_value_from_disjoint_sets(pkg.name, name, value, sid)
1170+
fn.facts(
1171+
pkg.name, fn.variant_value_from_disjoint_sets(name, value, sid)
1172+
)
11561173
)
11571174
union.update(s)
11581175
values = union
@@ -1179,7 +1196,9 @@ def pkg_rules(self, pkg, tests):
11791196
msg="empty (total) conflict constraint",
11801197
)
11811198
msg = "variant {0}={1} is conditionally disabled".format(name, value)
1182-
self.gen.fact(fn.conflict(pkg.name, trigger_id, constraint_id, msg))
1199+
self.gen.fact(
1200+
fn.facts(pkg.name, fn.conflict(trigger_id, constraint_id, msg))
1201+
)
11831202
else:
11841203
imposed = spack.spec.Spec(value.when)
11851204
imposed.name = pkg.name
@@ -1190,10 +1209,10 @@ def pkg_rules(self, pkg, tests):
11901209
name=pkg.name,
11911210
msg="%s variant %s value %s when %s" % (pkg.name, name, value, when),
11921211
)
1193-
self.gen.fact(fn.variant_possible_value(pkg.name, name, value))
1212+
self.gen.fact(fn.facts(pkg.name, fn.variant_possible_value(name, value)))
11941213

11951214
if variant.sticky:
1196-
self.gen.fact(fn.variant_sticky(pkg.name, name))
1215+
self.gen.fact(fn.facts(pkg.name, fn.variant_sticky(name)))
11971216

11981217
self.gen.newline()
11991218

@@ -1211,7 +1230,8 @@ def pkg_rules(self, pkg, tests):
12111230

12121231
# virtual preferences
12131232
self.virtual_preferences(
1214-
pkg.name, lambda v, p, i: self.gen.fact(fn.pkg_provider_preference(pkg.name, v, p, i))
1233+
pkg.name,
1234+
lambda v, p, i: self.gen.fact(fn.facts(pkg.name, fn.provider_preference(v, p, i))),
12151235
)
12161236

12171237
self.package_requirement_rules(pkg)
@@ -1233,15 +1253,16 @@ def condition(self, required_spec, imposed_spec=None, name=None, msg=None, node=
12331253
"""
12341254
named_cond = required_spec.copy()
12351255
named_cond.name = named_cond.name or name
1236-
assert named_cond.name, "must provide name for anonymous condtions!"
1256+
assert named_cond.name, "must provide name for anonymous conditions!"
12371257

12381258
# Check if we can emit the requirements before updating the condition ID counter.
12391259
# In this way, if a condition can't be emitted but the exception is handled in the caller,
12401260
# we won't emit partial facts.
12411261
requirements = self.spec_clauses(named_cond, body=True, required_from=name)
12421262

12431263
condition_id = next(self._condition_id_counter)
1244-
self.gen.fact(fn.condition(condition_id, msg))
1264+
self.gen.fact(fn.facts(named_cond.name, fn.condition(condition_id)))
1265+
self.gen.fact(fn.condition_reason(condition_id, msg))
12451266
for pred in requirements:
12461267
self.gen.fact(fn.condition_requirement(condition_id, *pred.args))
12471268

@@ -1260,13 +1281,15 @@ def impose(self, condition_id, imposed_spec, node=True, name=None, body=False):
12601281

12611282
def package_provider_rules(self, pkg):
12621283
for provider_name in sorted(set(s.name for s in pkg.provided.keys())):
1263-
self.gen.fact(fn.possible_provider(pkg.name, provider_name))
1284+
self.gen.fact(fn.facts(pkg.name, fn.possible_provider(provider_name)))
12641285

12651286
for provided, whens in pkg.provided.items():
12661287
for when in whens:
12671288
msg = "%s provides %s when %s" % (pkg.name, provided, when)
12681289
condition_id = self.condition(when, provided, pkg.name, msg)
1269-
self.gen.fact(fn.provider_condition(condition_id, when.name, provided.name))
1290+
self.gen.fact(
1291+
fn.facts(when.name, fn.provider_condition(condition_id, provided.name))
1292+
)
12701293
self.gen.newline()
12711294

12721295
def package_dependencies_rules(self, pkg):
@@ -1292,7 +1315,9 @@ def package_dependencies_rules(self, pkg):
12921315
msg += " when %s" % cond
12931316

12941317
condition_id = self.condition(cond, dep.spec, pkg.name, msg)
1295-
self.gen.fact(fn.dependency_condition(condition_id, pkg.name, dep.spec.name))
1318+
self.gen.fact(
1319+
fn.facts(pkg.name, fn.dependency_condition(condition_id, dep.spec.name))
1320+
)
12961321

12971322
for t in sorted(deptypes):
12981323
# there is a declared dependency of type t
@@ -1450,7 +1475,7 @@ def external_packages(self):
14501475
for local_idx, spec in enumerate(external_specs):
14511476
msg = "%s available as external when satisfying %s" % (spec.name, spec)
14521477
condition_id = self.condition(spec, msg=msg)
1453-
self.gen.fact(fn.possible_external(condition_id, pkg_name, local_idx))
1478+
self.gen.fact(fn.facts(pkg_name, fn.possible_external(condition_id, local_idx)))
14541479
self.possible_versions[spec.name].add(spec.version)
14551480
self.gen.newline()
14561481

@@ -1496,7 +1521,9 @@ def target_preferences(self, pkg_name):
14961521
if str(preferred.architecture.target) == best_default and i != 0:
14971522
offset = 100
14981523
self.gen.fact(
1499-
fn.target_weight(pkg_name, str(preferred.architecture.target), i + offset)
1524+
fn.facts(
1525+
pkg_name, fn.target_weight(str(preferred.architecture.target), i + offset)
1526+
)
15001527
)
15011528

15021529
def spec_clauses(self, *args, **kwargs):
@@ -2042,11 +2069,11 @@ def define_version_constraints(self):
20422069
# generate facts for each package constraint and the version
20432070
# that satisfies it
20442071
for v in sorted(v for v in self.possible_versions[pkg_name] if v.satisfies(versions)):
2045-
self.gen.fact(fn.version_satisfies(pkg_name, versions, v))
2072+
self.gen.fact(fn.facts(pkg_name, fn.version_satisfies(versions, v)))
20462073

20472074
self.gen.newline()
20482075

2049-
def define_virtual_constraints(self):
2076+
def collect_virtual_constraints(self):
20502077
"""Define versions for constraints on virtuals.
20512078
20522079
Must be called before define_version_constraints().
@@ -2132,7 +2159,7 @@ def define_variant_values(self):
21322159
# spec_clauses(). We might want to order these facts by pkg and name
21332160
# if we are debugging.
21342161
for pkg, variant, value in self.variant_values_from_specs:
2135-
self.gen.fact(fn.variant_possible_value(pkg, variant, value))
2162+
self.gen.fact(fn.facts(pkg, fn.variant_possible_value(variant, value)))
21362163

21372164
def _facts_from_concrete_spec(self, spec, possible):
21382165
# tell the solver about any installed packages that could
@@ -2281,10 +2308,8 @@ def setup(self, driver, specs, reuse=None):
22812308
self.gen.h1("Variant Values defined in specs")
22822309
self.define_variant_values()
22832310

2284-
self.gen.h1("Virtual Constraints")
2285-
self.define_virtual_constraints()
2286-
22872311
self.gen.h1("Version Constraints")
2312+
self.collect_virtual_constraints()
22882313
self.define_version_constraints()
22892314

22902315
self.gen.h1("Compiler Version Constraints")

0 commit comments

Comments
 (0)