diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 8fcc681c1cc..d9accc6e09f 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -3432,8 +3432,7 @@ def __init__(self): self.asp_problem = [] def fact(self, atom: AspFunction) -> None: - symbol = atom.symbol() if hasattr(atom, "symbol") else atom - self.asp_problem.append(f"{str(symbol)}.\n") + self.asp_problem.append(f"{atom}.\n") def append(self, rule: str) -> None: self.asp_problem.append(rule) diff --git a/lib/spack/spack/solver/core.py b/lib/spack/spack/solver/core.py index a38ad27848c..b710c5745e4 100644 --- a/lib/spack/spack/solver/core.py +++ b/lib/spack/spack/solver/core.py @@ -31,16 +31,19 @@ class AspObject: """Object representing a piece of ASP code.""" -def _id(thing: Any) -> Union[str, AspObject]: +def _id(thing: Any) -> Union[str, int, AspObject]: """Quote string if needed for it to be a valid identifier.""" - if isinstance(thing, AspObject): + if isinstance(thing, bool): + return f'"{thing}"' + elif isinstance(thing, (AspObject, int)): return thing - elif isinstance(thing, bool): - return f'"{str(thing)}"' - elif isinstance(thing, int): - return str(thing) else: - return f'"{str(thing)}"' + if isinstance(thing, str): + # escape characters that cannot be in clingo strings + thing = thing.replace("\\", r"\\") + thing = thing.replace("\n", r"\n") + thing = thing.replace('"', r"\"") + return f'"{thing}"' class AspVar(AspObject): @@ -90,26 +93,9 @@ def __call__(self, *args: Any) -> "AspFunction": """ return AspFunction(self.name, self.args + args) - def _argify(self, arg: Any) -> Any: - """Turn the argument into an appropriate clingo symbol""" - if isinstance(arg, bool): - return clingo().String(str(arg)) - elif isinstance(arg, int): - return clingo().Number(arg) - elif isinstance(arg, AspFunction): - return clingo().Function(arg.name, [self._argify(x) for x in arg.args], positive=True) - elif isinstance(arg, AspVar): - return clingo().Variable(arg.name) - return clingo().String(str(arg)) - - def symbol(self): - """Return a clingo symbol for this function""" - return clingo().Function( - self.name, [self._argify(arg) for arg in self.args], positive=True - ) - def __str__(self) -> str: - return f"{self.name}({', '.join(str(_id(arg)) for arg in self.args)})" + args = f"({','.join(str(_id(arg)) for arg in self.args)})" + return f"{self.name}{args}" def __repr__(self) -> str: return str(self)