mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-23 06:53:32 +00:00
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>
This commit is contained in:
parent
7b3ea34b6b
commit
e2f948469c
@ -48,37 +48,39 @@ class Name:
|
|||||||
return '_'.join(self.chunks)
|
return '_'.join(self.chunks)
|
||||||
|
|
||||||
class Type:
|
class Type:
|
||||||
def __init__(self, name, record, native=False):
|
def __init__(self, name, json_data, native=False):
|
||||||
self.record = record
|
self.json_data = json_data
|
||||||
self.dict_name = name
|
self.dict_name = name
|
||||||
self.name = Name(name, native=native)
|
self.name = Name(name, native=native)
|
||||||
self.category = record['category']
|
self.category = json_data['category']
|
||||||
self.is_builder = self.name.canonical_case().endswith(" builder")
|
self.is_builder = self.name.canonical_case().endswith(" builder")
|
||||||
|
|
||||||
EnumValue = namedtuple('EnumValue', ['name', 'value'])
|
EnumValue = namedtuple('EnumValue', ['name', 'value'])
|
||||||
class EnumType(Type):
|
class EnumType(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record)
|
Type.__init__(self, name, json_data)
|
||||||
self.values = [EnumValue(Name(m['name']), m['value']) for m in self.record['values']]
|
self.values = [EnumValue(Name(m['name']), m['value']) for m in self.json_data['values']]
|
||||||
|
|
||||||
BitmaskValue = namedtuple('BitmaskValue', ['name', 'value'])
|
BitmaskValue = namedtuple('BitmaskValue', ['name', 'value'])
|
||||||
class BitmaskType(Type):
|
class BitmaskType(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record)
|
Type.__init__(self, name, json_data)
|
||||||
self.values = [BitmaskValue(Name(m['name']), m['value']) for m in self.record['values']]
|
self.values = [BitmaskValue(Name(m['name']), m['value']) for m in self.json_data['values']]
|
||||||
self.full_mask = 0
|
self.full_mask = 0
|
||||||
for value in self.values:
|
for value in self.values:
|
||||||
self.full_mask = self.full_mask | value.value
|
self.full_mask = self.full_mask | value.value
|
||||||
|
|
||||||
class NativeType(Type):
|
class NativeType(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record, native=True)
|
Type.__init__(self, name, json_data, native=True)
|
||||||
|
|
||||||
class NativelyDefined(Type):
|
class NativelyDefined(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record)
|
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):
|
def __init__(self, name, typ, annotation, optional):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = typ
|
self.type = typ
|
||||||
@ -88,24 +90,16 @@ class MethodArgument:
|
|||||||
|
|
||||||
Method = namedtuple('Method', ['name', 'return_type', 'arguments'])
|
Method = namedtuple('Method', ['name', 'return_type', 'arguments'])
|
||||||
class ObjectType(Type):
|
class ObjectType(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record)
|
Type.__init__(self, name, json_data)
|
||||||
self.methods = []
|
self.methods = []
|
||||||
self.native_methods = []
|
self.native_methods = []
|
||||||
self.built_type = None
|
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):
|
class StructureType(Type):
|
||||||
def __init__(self, name, record):
|
def __init__(self, name, json_data):
|
||||||
Type.__init__(self, name, record)
|
Type.__init__(self, name, json_data)
|
||||||
self.extensible = record.get("extensible", False)
|
self.extensible = json_data.get("extensible", False)
|
||||||
self.members = []
|
self.members = []
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
@ -117,32 +111,37 @@ def is_native_method(method):
|
|||||||
return method.return_type.category == "natively defined" or \
|
return method.return_type.category == "natively defined" or \
|
||||||
any([arg.type.category == "natively defined" for arg in method.arguments])
|
any([arg.type.category == "natively defined" for arg in method.arguments])
|
||||||
|
|
||||||
def link_object(obj, types):
|
def linked_record_members(json_data, types):
|
||||||
def make_method(record):
|
members = []
|
||||||
arguments = []
|
members_by_name = {}
|
||||||
arguments_by_name = {}
|
for m in json_data:
|
||||||
for a in record.get('args', []):
|
member = RecordMember(Name(m['name']), types[m['type']],
|
||||||
arg = MethodArgument(Name(a['name']), types[a['type']],
|
m.get('annotation', 'value'), m.get('optional', False))
|
||||||
a.get('annotation', 'value'), a.get('optional', False))
|
members.append(member)
|
||||||
arguments.append(arg)
|
members_by_name[member.name.canonical_case()] = member
|
||||||
arguments_by_name[arg.name.canonical_case()] = arg
|
|
||||||
|
|
||||||
for (arg, a) in zip(arguments, record.get('args', [])):
|
for (member, m) in zip(members, json_data):
|
||||||
if arg.annotation != 'value':
|
if member.annotation != 'value':
|
||||||
if not 'length' in a:
|
if not 'length' in m:
|
||||||
if arg.type.category == 'structure':
|
if member.type.category == 'structure':
|
||||||
arg.length = "constant"
|
member.length = "constant"
|
||||||
arg.constant_length = 1
|
member.constant_length = 1
|
||||||
else:
|
|
||||||
assert(False)
|
|
||||||
elif a['length'] == 'strlen':
|
|
||||||
arg.length = 'strlen'
|
|
||||||
else:
|
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.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)]
|
obj.native_methods = [method for method in methods if is_native_method(method)]
|
||||||
|
|
||||||
@ -155,25 +154,7 @@ def link_object(obj, types):
|
|||||||
assert(obj.built_type != None)
|
assert(obj.built_type != None)
|
||||||
|
|
||||||
def link_structure(struct, types):
|
def link_structure(struct, types):
|
||||||
def make_member(m):
|
struct.members = linked_record_members(struct.json_data['members'], types)
|
||||||
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']]
|
|
||||||
|
|
||||||
# Sort structures so that if struct A has struct B as a member, then B is listed before A
|
# 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
|
# This is a form of topological sort where we try to keep the order reasonably similar to the
|
||||||
@ -193,7 +174,7 @@ def topo_sort_structure(structs):
|
|||||||
|
|
||||||
max_dependent_depth = 0
|
max_dependent_depth = 0
|
||||||
for member in struct.members:
|
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)
|
max_dependent_depth = max(max_dependent_depth, compute_depth(member.type) + 1)
|
||||||
|
|
||||||
struct.subdag_depth = max_dependent_depth
|
struct.subdag_depth = max_dependent_depth
|
||||||
@ -227,11 +208,11 @@ def parse_json(json):
|
|||||||
for name in category_to_parser.keys():
|
for name in category_to_parser.keys():
|
||||||
by_category[name] = []
|
by_category[name] = []
|
||||||
|
|
||||||
for (name, record) in json.items():
|
for (name, json_data) in json.items():
|
||||||
if name[0] == '_':
|
if name[0] == '_':
|
||||||
continue
|
continue
|
||||||
category = record['category']
|
category = json_data['category']
|
||||||
parsed = category_to_parser[category](name, record)
|
parsed = category_to_parser[category](name, json_data)
|
||||||
by_category[category].append(parsed)
|
by_category[category].append(parsed)
|
||||||
types[name] = parsed
|
types[name] = parsed
|
||||||
|
|
||||||
@ -363,8 +344,6 @@ def as_cppType(name):
|
|||||||
def decorate(name, typ, arg):
|
def decorate(name, typ, arg):
|
||||||
if arg.annotation == 'value':
|
if arg.annotation == 'value':
|
||||||
return typ + ' ' + name
|
return typ + ' ' + name
|
||||||
elif arg.annotation == '*':
|
|
||||||
return typ + '* ' + name
|
|
||||||
elif arg.annotation == 'const*':
|
elif arg.annotation == 'const*':
|
||||||
return typ + ' const * ' + name
|
return typ + ' const * ' + name
|
||||||
else:
|
else:
|
||||||
@ -414,9 +393,9 @@ def cpp_native_methods(types, typ):
|
|||||||
|
|
||||||
if typ.is_builder:
|
if typ.is_builder:
|
||||||
methods.append(Method(Name('set error callback'), types['void'], [
|
methods.append(Method(Name('set error callback'), types['void'], [
|
||||||
MethodArgument(Name('callback'), types['builder error callback'], 'value', False),
|
RecordMember(Name('callback'), types['builder error callback'], 'value', False),
|
||||||
MethodArgument(Name('userdata1'), types['callback userdata'], 'value', False),
|
RecordMember(Name('userdata1'), types['callback userdata'], 'value', False),
|
||||||
MethodArgument(Name('userdata2'), types['callback userdata'], 'value', False),
|
RecordMember(Name('userdata2'), types['callback userdata'], 'value', False),
|
||||||
]))
|
]))
|
||||||
|
|
||||||
return methods
|
return methods
|
||||||
|
Loading…
x
Reference in New Issue
Block a user