generator: Unify handling of argument and member parsing
This completes the handling of "length" for structure members which were
missing const* structures defaulting to being of length one.
Also renames "record" to json_data to more precisely describe what it
is.
BUG=dawn:4
Change-Id: Ia53e4fcec15ebc9f9dae58ddba5b460d1f2eeebd
Reviewed-on: https://dawn-review.googlesource.com/c/2881
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/main.py b/generator/main.py
index e58daac..017a941 100644
--- a/generator/main.py
+++ b/generator/main.py
@@ -48,37 +48,39 @@
return '_'.join(self.chunks)
class Type:
- def __init__(self, name, record, native=False):
- self.record = record
+ def __init__(self, name, json_data, native=False):
+ self.json_data = json_data
self.dict_name = name
self.name = Name(name, native=native)
- self.category = record['category']
+ self.category = json_data['category']
self.is_builder = self.name.canonical_case().endswith(" builder")
EnumValue = namedtuple('EnumValue', ['name', 'value'])
class EnumType(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record)
- self.values = [EnumValue(Name(m['name']), m['value']) for m in self.record['values']]
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data)
+ self.values = [EnumValue(Name(m['name']), m['value']) for m in self.json_data['values']]
BitmaskValue = namedtuple('BitmaskValue', ['name', 'value'])
class BitmaskType(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record)
- self.values = [BitmaskValue(Name(m['name']), m['value']) for m in self.record['values']]
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data)
+ self.values = [BitmaskValue(Name(m['name']), m['value']) for m in self.json_data['values']]
self.full_mask = 0
for value in self.values:
self.full_mask = self.full_mask | value.value
class NativeType(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record, native=True)
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data, native=True)
class NativelyDefined(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record)
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data)
-class MethodArgument:
+# Methods and structures are both "records", so record members correspond to
+# method arguments or structure members.
+class RecordMember:
def __init__(self, name, typ, annotation, optional):
self.name = name
self.type = typ
@@ -88,24 +90,16 @@
Method = namedtuple('Method', ['name', 'return_type', 'arguments'])
class ObjectType(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record)
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data)
self.methods = []
self.native_methods = []
self.built_type = None
-class StructureMember:
- def __init__(self, name, typ, annotation, optional):
- self.name = name
- self.type = typ
- self.annotation = annotation
- self.length = None
- self.optional = optional
-
class StructureType(Type):
- def __init__(self, name, record):
- Type.__init__(self, name, record)
- self.extensible = record.get("extensible", False)
+ def __init__(self, name, json_data):
+ Type.__init__(self, name, json_data)
+ self.extensible = json_data.get("extensible", False)
self.members = []
############################################################
@@ -117,32 +111,37 @@
return method.return_type.category == "natively defined" or \
any([arg.type.category == "natively defined" for arg in method.arguments])
-def link_object(obj, types):
- def make_method(record):
- arguments = []
- arguments_by_name = {}
- for a in record.get('args', []):
- arg = MethodArgument(Name(a['name']), types[a['type']],
- a.get('annotation', 'value'), a.get('optional', False))
- arguments.append(arg)
- arguments_by_name[arg.name.canonical_case()] = arg
+def linked_record_members(json_data, types):
+ members = []
+ members_by_name = {}
+ for m in json_data:
+ member = RecordMember(Name(m['name']), types[m['type']],
+ m.get('annotation', 'value'), m.get('optional', False))
+ members.append(member)
+ members_by_name[member.name.canonical_case()] = member
- for (arg, a) in zip(arguments, record.get('args', [])):
- if arg.annotation != 'value':
- if not 'length' in a:
- if arg.type.category == 'structure':
- arg.length = "constant"
- arg.constant_length = 1
- else:
- assert(False)
- elif a['length'] == 'strlen':
- arg.length = 'strlen'
+ for (member, m) in zip(members, json_data):
+ if member.annotation != 'value':
+ if not 'length' in m:
+ if member.type.category == 'structure':
+ member.length = "constant"
+ member.constant_length = 1
else:
- arg.length = arguments_by_name[a['length']]
+ assert(False)
+ elif m['length'] == 'strlen':
+ member.length = 'strlen'
+ else:
+ member.length = members_by_name[m['length']]
- return Method(Name(record['name']), types[record.get('returns', 'void')], arguments)
+ return members
- methods = [make_method(m) for m in obj.record.get('methods', [])]
+
+def link_object(obj, types):
+ def make_method(json_data):
+ arguments = linked_record_members(json_data.get('args', []), types)
+ return Method(Name(json_data['name']), types[json_data.get('returns', 'void')], arguments)
+
+ methods = [make_method(m) for m in obj.json_data.get('methods', [])]
obj.methods = [method for method in methods if not is_native_method(method)]
obj.native_methods = [method for method in methods if is_native_method(method)]
@@ -155,25 +154,7 @@
assert(obj.built_type != None)
def link_structure(struct, types):
- def make_member(m):
- return StructureMember(Name(m['name']), types[m['type']],
- m.get('annotation', 'value'), m.get('optional', False))
-
- members = []
- members_by_name = {}
- for m in struct.record['members']:
- member = make_member(m)
- members.append(member)
- members_by_name[member.name.canonical_case()] = member
- struct.members = members
-
- for (member, m) in zip(members, struct.record['members']):
- # TODO(kainino@chromium.org): More robust pointer/length handling?
- if 'length' in m:
- if m['length'] == 'strlen':
- member.length = 'strlen'
- else:
- member.length = members_by_name[m['length']]
+ struct.members = linked_record_members(struct.json_data['members'], types)
# Sort structures so that if struct A has struct B as a member, then B is listed before A
# This is a form of topological sort where we try to keep the order reasonably similar to the
@@ -193,7 +174,7 @@
max_dependent_depth = 0
for member in struct.members:
- if member.type.category == 'structure' and member.annotation == 'value':
+ if member.type.category == 'structure':
max_dependent_depth = max(max_dependent_depth, compute_depth(member.type) + 1)
struct.subdag_depth = max_dependent_depth
@@ -227,11 +208,11 @@
for name in category_to_parser.keys():
by_category[name] = []
- for (name, record) in json.items():
+ for (name, json_data) in json.items():
if name[0] == '_':
continue
- category = record['category']
- parsed = category_to_parser[category](name, record)
+ category = json_data['category']
+ parsed = category_to_parser[category](name, json_data)
by_category[category].append(parsed)
types[name] = parsed
@@ -363,8 +344,6 @@
def decorate(name, typ, arg):
if arg.annotation == 'value':
return typ + ' ' + name
- elif arg.annotation == '*':
- return typ + '* ' + name
elif arg.annotation == 'const*':
return typ + ' const * ' + name
else:
@@ -414,9 +393,9 @@
if typ.is_builder:
methods.append(Method(Name('set error callback'), types['void'], [
- MethodArgument(Name('callback'), types['builder error callback'], 'value', False),
- MethodArgument(Name('userdata1'), types['callback userdata'], 'value', False),
- MethodArgument(Name('userdata2'), types['callback userdata'], 'value', False),
+ RecordMember(Name('callback'), types['builder error callback'], 'value', False),
+ RecordMember(Name('userdata1'), types['callback userdata'], 'value', False),
+ RecordMember(Name('userdata2'), types['callback userdata'], 'value', False),
]))
return methods