build.{dsl,res}: allow platform-dependent attributes using callables.

Fixes #132.
This commit is contained in:
whitequark 2019-07-08 11:15:04 +00:00
parent 0ab0a74ec1
commit 7b4fbf8e01
4 changed files with 24 additions and 8 deletions

View file

@ -91,10 +91,10 @@ def DiffPairsN(*args, **kwargs):
class Attrs(OrderedDict):
def __init__(self, **attrs):
for attr_key, attr_value in attrs.items():
if not (attr_value is None or isinstance(attr_value, str)):
raise TypeError("Attribute value must be None or str, not {!r}"
.format(attr_value))
for key, value in attrs.items():
if not (value is None or isinstance(value, str) or hasattr(value, "__call__")):
raise TypeError("Value of attribute {} must be None, str, or callable, not {!r}"
.format(key, value))
super().__init__(**attrs)
@ -103,6 +103,8 @@ class Attrs(OrderedDict):
for key, value in self.items():
if value is None:
items.append("!" + key)
elif hasattr(value, "__call__"):
items.append(key + "=" + repr(value))
else:
items.append(key + "=" + value)
return "(attrs {})".format(" ".join(items))

View file

@ -103,13 +103,21 @@ class ResourceManager:
return dir, xdr
def resolve(resource, dir, xdr, name, attrs):
for attr_key, attr_value in attrs.items():
if hasattr(attr_value, "__call__"):
attr_value = attr_value(self)
assert attr_value is None or isinstance(attr_value, str)
if attr_value is None:
del attrs[attr_key]
else:
attrs[attr_key] = attr_value
if isinstance(resource.ios[0], Subsignal):
fields = OrderedDict()
for sub in resource.ios:
sub_attrs = {k: v for k, v in {**attrs, **sub.attrs}.items() if v is not None}
fields[sub.name] = resolve(sub, dir[sub.name], xdr[sub.name],
name="{}__{}".format(name, sub.name),
attrs=sub_attrs)
attrs={**attrs, **sub.attrs})
return Record([
(f_name, f.layout) for (f_name, f) in fields.items()
], fields=fields, name=name)