Commit 3df0b847 authored by Yuki Shiino's avatar Yuki Shiino Committed by Chromium LUCI CQ

bind-gen: Implement IDL union (3 of N)

Implements accessor functions of new IDL unions.  Also implements
constructors and 'Clear' member function.

Bug: 839389
Change-Id: I4d51261e96a23b63c33ac3c43553a779e978053e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2522861Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#832354}
parent e1525192
...@@ -14,6 +14,7 @@ from .code_node_cxx import CxxClassDefNode ...@@ -14,6 +14,7 @@ from .code_node_cxx import CxxClassDefNode
from .code_node_cxx import CxxFuncDeclNode from .code_node_cxx import CxxFuncDeclNode
from .code_node_cxx import CxxFuncDefNode from .code_node_cxx import CxxFuncDefNode
from .code_node_cxx import CxxNamespaceNode from .code_node_cxx import CxxNamespaceNode
from .code_node_cxx import CxxSwitchNode
from .codegen_accumulator import CodeGenAccumulator from .codegen_accumulator import CodeGenAccumulator
from .codegen_context import CodeGenContext from .codegen_context import CodeGenContext
from .codegen_format import format_template as _format from .codegen_format import format_template as _format
...@@ -43,8 +44,8 @@ class _UnionMember(object): ...@@ -43,8 +44,8 @@ class _UnionMember(object):
self._api_pred = "Is{}".format(self._base_name) self._api_pred = "Is{}".format(self._base_name)
self._api_get = "GetAs{}".format(self._base_name) self._api_get = "GetAs{}".format(self._base_name)
self._api_set = "Set" self._api_set = "Set"
self._member_var = name_style.member_var("member", self._base_name) self._var_name = name_style.member_var("member", self._base_name)
self._member_type = None self._type_info = None
self._typedef_aliases = () self._typedef_aliases = ()
@property @property
...@@ -70,12 +71,12 @@ class _UnionMember(object): ...@@ -70,12 +71,12 @@ class _UnionMember(object):
return self._api_set return self._api_set
@property @property
def member_var(self): def var_name(self):
return self._member_var return self._var_name
@property @property
def member_type(self): def type_info(self):
return self._member_type return self._type_info
@property @property
def typedef_aliases(self): def typedef_aliases(self):
...@@ -95,7 +96,7 @@ class _UnionMemberImpl(_UnionMember): ...@@ -95,7 +96,7 @@ class _UnionMemberImpl(_UnionMember):
_UnionMember.__init__(self, base_name=base_name) _UnionMember.__init__(self, base_name=base_name)
self._is_null = idl_type is None self._is_null = idl_type is None
if not self._is_null: if not self._is_null:
self._member_type = blink_type_info(idl_type) self._type_info = blink_type_info(idl_type)
self._typedef_aliases = tuple([ self._typedef_aliases = tuple([
_UnionMemberAlias(impl=self, typedef=typedef) _UnionMemberAlias(impl=self, typedef=typedef)
for typedef in union.typedef_members for typedef in union.typedef_members
...@@ -103,13 +104,43 @@ class _UnionMemberImpl(_UnionMember): ...@@ -103,13 +104,43 @@ class _UnionMemberImpl(_UnionMember):
]) ])
class _UnionMemberSubunion(_UnionMember):
def __init__(self, union, subunion):
assert isinstance(union, web_idl.NewUnion)
assert isinstance(subunion, web_idl.NewUnion)
_UnionMember.__init__(self, base_name=blink_class_name(subunion))
self._type_info = blink_type_info(subunion.idl_types[0],
use_new_union=True)
self._typedef_aliases = tuple(
map(lambda typedef: _UnionMemberAlias(impl=self, typedef=typedef),
subunion.aliasing_typedefs))
self._blink_class_name = blink_class_name(subunion)
@property
def blink_class_name(self):
return self._blink_class_name
class _UnionMemberAlias(_UnionMember): class _UnionMemberAlias(_UnionMember):
def __init__(self, impl, typedef): def __init__(self, impl, typedef):
assert isinstance(impl, _UnionMemberImpl) assert isinstance(impl, (_UnionMemberImpl, _UnionMemberSubunion))
assert isinstance(typedef, web_idl.Typedef) assert isinstance(typedef, web_idl.Typedef)
_UnionMember.__init__(self, base_name=typedef.identifier) _UnionMember.__init__(self, base_name=typedef.identifier)
self._member_var = impl.member_var self._var_name = impl.var_name
self._type_info = impl.type_info
def create_union_members(union):
assert isinstance(union, web_idl.NewUnion)
union_members = map(
lambda member_type: _UnionMemberImpl(union, member_type),
union.flattened_member_types)
if union.does_include_nullable_type:
union_members.append(_UnionMemberImpl(union, idl_type=None))
return tuple(union_members)
def make_content_type_enum_class_def(cg_context): def make_content_type_enum_class_def(cg_context):
...@@ -124,12 +155,223 @@ def make_content_type_enum_class_def(cg_context): ...@@ -124,12 +155,223 @@ def make_content_type_enum_class_def(cg_context):
member.content_type(with_enum_name=False))) member.content_type(with_enum_name=False)))
return ListNode([ return ListNode([
TextNode("// The type of the content value of this IDL union."),
TextNode("enum class ContentType {"), TextNode("enum class ContentType {"),
ListNode(map(TextNode, entries), separator=", "), ListNode(map(TextNode, entries), separator=", "),
TextNode("};"), TextNode("};"),
]) ])
def make_constructors(cg_context):
assert isinstance(cg_context, CodeGenContext)
decls = ListNode()
for member in cg_context.union_members:
if member.is_null:
func_def = CxxFuncDefNode(name=cg_context.class_name,
arg_decls=["std::nullptr_t"],
return_type="",
explicit=True,
member_initializer_list=[
"content_type_({})".format(
member.content_type()),
])
else:
func_def = CxxFuncDefNode(
name=cg_context.class_name,
arg_decls=["{} value".format(member.type_info.member_ref_t)],
return_type="",
explicit=True,
member_initializer_list=[
"content_type_({})".format(member.content_type()),
"{}(value)".format(member.var_name),
])
decls.append(func_def)
return decls, None
def make_accessor_functions(cg_context):
assert isinstance(cg_context, CodeGenContext)
T = TextNode
F = lambda *args, **kwargs: T(_format(*args, **kwargs))
decls = ListNode()
defs = ListNode()
func_def = CxxFuncDefNode(name="GetContentType",
arg_decls=[],
return_type="ContentType",
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.append(T("return content_type_;"))
decls.extend([
T("// Returns the type of the content value."),
func_def,
EmptyNode(),
])
def make_api_pred(member):
func_def = CxxFuncDefNode(name=member.api_pred,
arg_decls=[],
return_type="bool",
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.append(
F("return content_type_ == {};", member.content_type()))
return func_def
def make_api_get(member):
func_def = CxxFuncDefNode(name=member.api_get,
arg_decls=[],
return_type=member.type_info.member_ref_t,
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
F("DCHECK_EQ(content_type_, {});", member.content_type()),
F("return {};", member.var_name),
])
return func_def
def make_api_set(member):
func_def = CxxFuncDefNode(
name=member.api_set,
arg_decls=["{} value".format(member.type_info.member_ref_t)],
return_type="void")
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
T("Clear();"),
F("{} = value;", member.var_name),
F("content_type_ = {};", member.content_type()),
])
return func_def
def make_api_set_null(member):
func_def = CxxFuncDefNode(name=member.api_set,
arg_decls=["std::nullptr_t"],
return_type="void")
func_def.set_base_template_vars(cg_context.template_bindings())
func_def.body.extend([
T("Clear();"),
F("content_type_ = {};", member.content_type()),
])
return func_def
for member in cg_context.union_members:
if member.is_null:
decls.append(make_api_pred(member))
decls.append(make_api_set_null(member))
else:
decls.append(make_api_pred(member))
for alias in member.typedef_aliases:
decls.append(make_api_pred(alias))
decls.append(make_api_get(member))
for alias in member.typedef_aliases:
decls.append(make_api_get(alias))
decls.append(make_api_set(member))
decls.append(EmptyNode())
def make_api_subunion_pred(subunion, subunion_members):
func_def = CxxFuncDefNode(name=subunion.api_pred,
arg_decls=[],
return_type="bool",
const=True)
func_def.set_base_template_vars(cg_context.template_bindings())
expr = " || ".join(
map(
lambda member: "content_type_ == {}".format(
member.content_type()), subunion_members))
func_def.body.append(F("return {};", expr))
return func_def, None
def make_api_subunion_get(subunion, subunion_members):
func_decl = CxxFuncDeclNode(name=subunion.api_get,
arg_decls=[],
return_type=subunion.type_info.value_t,
const=True)
func_def = CxxFuncDefNode(name=subunion.api_get,
arg_decls=[],
return_type=subunion.type_info.value_t,
const=True,
class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
node = CxxSwitchNode(cond="content_type_")
node.append(case=None,
body=[T("NOTREACHED();"),
T("return nullptr;")],
should_add_break=False)
for member in subunion_members:
node.append(case=member.content_type(),
body=F("return MakeGarbageCollected<{}>({}());",
subunion.blink_class_name, member.api_get),
should_add_break=False)
func_def.body.append(node)
return func_decl, func_def
def make_api_subunion_set(subunion, subunion_members):
func_decl = CxxFuncDeclNode(
name=subunion.api_set,
arg_decls=["{} value".format(subunion.type_info.const_ref_t)],
return_type="void")
func_def = CxxFuncDefNode(
name=subunion.api_set,
arg_decls=["{} value".format(subunion.type_info.const_ref_t)],
return_type="void",
class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
node = CxxSwitchNode(cond="value->GetContentType()")
for member in subunion_members:
node.append(case=F("{}::{}", subunion.blink_class_name,
member.content_type()),
body=F("Set(value->{}());", member.api_get))
func_def.body.append(node)
return func_decl, func_def
for subunion in cg_context.union.union_members:
subunion_members = create_union_members(subunion)
subunion = _UnionMemberSubunion(cg_context.union, subunion)
func_decl, func_def = make_api_subunion_pred(subunion,
subunion_members)
decls.append(func_decl)
defs.append(func_def)
defs.append(EmptyNode())
func_decl, func_def = make_api_subunion_get(subunion, subunion_members)
decls.append(func_decl)
defs.append(func_def)
defs.append(EmptyNode())
func_decl, func_def = make_api_subunion_set(subunion, subunion_members)
decls.append(func_decl)
defs.append(func_def)
defs.append(EmptyNode())
decls.append(EmptyNode())
return decls, defs
def make_clear_function(cg_context):
assert isinstance(cg_context, CodeGenContext)
func_decl = CxxFuncDeclNode(name="Clear", arg_decls=[], return_type="void")
func_def = CxxFuncDefNode(name="Clear",
arg_decls=[],
return_type="void",
class_name=cg_context.class_name)
func_def.set_base_template_vars(cg_context.template_bindings())
body = func_def.body
for member in cg_context.union_members:
if member.is_null:
continue
clear_expr = member.type_info.clear_member_var_expr(member.var_name)
if clear_expr:
body.append(TextNode("{};".format(clear_expr)))
return func_decl, func_def
def make_trace_function(cg_context): def make_trace_function(cg_context):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
...@@ -152,7 +394,7 @@ def make_trace_function(cg_context): ...@@ -152,7 +394,7 @@ def make_trace_function(cg_context):
continue continue
body.append( body.append(
TextNode("TraceIfNeeded<{}>::Trace(visitor, {});".format( TextNode("TraceIfNeeded<{}>::Trace(visitor, {});".format(
member.member_type.member_t, member.member_var))) member.type_info.member_t, member.var_name)))
body.append(TextNode("${base_class_name}::Trace(visitor);")) body.append(TextNode("${base_class_name}::Trace(visitor);"))
return func_decl, func_def return func_decl, func_def
...@@ -161,11 +403,19 @@ def make_trace_function(cg_context): ...@@ -161,11 +403,19 @@ def make_trace_function(cg_context):
def make_member_vars_def(cg_context): def make_member_vars_def(cg_context):
assert isinstance(cg_context, CodeGenContext) assert isinstance(cg_context, CodeGenContext)
member_vars_def = ListNode()
member_vars_def.extend([
TextNode("ContentType content_type_;"),
EmptyNode(),
])
entries = [ entries = [
"{} {};".format(member.member_type.member_t, member.member_var) "{} {};".format(member.type_info.member_t, member.var_name)
for member in cg_context.union_members if not member.is_null for member in cg_context.union_members if not member.is_null
] ]
return ListNode(map(TextNode, entries)) member_vars_def.extend(map(TextNode, entries))
return member_vars_def
def generate_union(union_identifier): def generate_union(union_identifier):
...@@ -182,13 +432,8 @@ def generate_union(union_identifier): ...@@ -182,13 +432,8 @@ def generate_union(union_identifier):
# Class names # Class names
class_name = blink_class_name(union) class_name = blink_class_name(union)
union_members = map(
lambda member_type: _UnionMemberImpl(union=union, idl_type=member_type
), union.flattened_member_types)
if union.does_include_nullable_type:
union_members.append(_UnionMemberImpl(union=union, idl_type=None))
cg_context = CodeGenContext(union=union, cg_context = CodeGenContext(union=union,
union_members=tuple(union_members), union_members=create_union_members(union),
class_name=class_name, class_name=class_name,
base_class_name="bindings::UnionBase") base_class_name="bindings::UnionBase")
...@@ -218,7 +463,10 @@ def generate_union(union_identifier): ...@@ -218,7 +463,10 @@ def generate_union(union_identifier):
# Implementation parts # Implementation parts
content_type_enum_class_def = make_content_type_enum_class_def(cg_context) content_type_enum_class_def = make_content_type_enum_class_def(cg_context)
trace_decls, trace_defs = make_trace_function(cg_context) ctor_decls, ctor_defs = make_constructors(cg_context)
accessor_decls, accessor_defs = make_accessor_functions(cg_context)
clear_func_decls, clear_func_defs = make_clear_function(cg_context)
trace_func_decls, trace_func_defs = make_trace_function(cg_context)
member_vars_def = make_member_vars_def(cg_context) member_vars_def = make_member_vars_def(cg_context)
# Header part (copyright, include directives, and forward declarations) # Header part (copyright, include directives, and forward declarations)
...@@ -255,6 +503,11 @@ def generate_union(union_identifier): ...@@ -255,6 +503,11 @@ def generate_union(union_identifier):
component_export_header(api_component, for_testing), component_export_header(api_component, for_testing),
"third_party/blink/renderer/platform/bindings/union_base.h", "third_party/blink/renderer/platform/bindings/union_base.h",
]) ])
header_node.accumulator.add_class_decls(
map(blink_class_name, union.union_members))
source_node.accumulator.add_include_headers(
map(lambda subunion: PathManager(subunion).api_path(ext="h"),
union.union_members))
(header_forward_decls, header_include_headers, source_forward_decls, (header_forward_decls, header_include_headers, source_forward_decls,
source_include_headers) = collect_forward_decls_and_include_headers( source_include_headers) = collect_forward_decls_and_include_headers(
union.flattened_member_types) union.flattened_member_types)
...@@ -266,16 +519,28 @@ def generate_union(union_identifier): ...@@ -266,16 +519,28 @@ def generate_union(union_identifier):
header_blink_ns.body.append(class_def) header_blink_ns.body.append(class_def)
header_blink_ns.body.append(EmptyNode()) header_blink_ns.body.append(EmptyNode())
class_def.public_section.extend([ class_def.public_section.append(content_type_enum_class_def)
content_type_enum_class_def, class_def.public_section.append(EmptyNode())
EmptyNode(),
trace_decls, class_def.public_section.append(ctor_decls)
EmptyNode(), class_def.public_section.append(EmptyNode())
]) source_blink_ns.body.append(ctor_defs)
source_blink_ns.body.extend([ source_blink_ns.body.append(EmptyNode())
trace_defs,
EmptyNode(), class_def.public_section.append(accessor_decls)
]) class_def.public_section.append(EmptyNode())
source_blink_ns.body.append(accessor_defs)
source_blink_ns.body.append(EmptyNode())
class_def.public_section.append(clear_func_decls)
class_def.public_section.append(EmptyNode())
source_blink_ns.body.append(clear_func_defs)
source_blink_ns.body.append(EmptyNode())
class_def.public_section.append(trace_func_decls)
class_def.public_section.append(EmptyNode())
source_blink_ns.body.append(trace_func_defs)
source_blink_ns.body.append(EmptyNode())
class_def.private_section.append(member_vars_def) class_def.private_section.append(member_vars_def)
class_def.private_section.append(EmptyNode()) class_def.private_section.append(EmptyNode())
......
...@@ -140,7 +140,7 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent, ...@@ -140,7 +140,7 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
idl_type.type_name_with_extended_attribute_key_values) idl_type.type_name_with_extended_attribute_key_values)
sort_key_identifier = lambda x: x.identifier sort_key_identifier = lambda x: x.identifier
self._union_types = tuple(ir.union_types) self._idl_types = tuple(ir.union_types)
self._flattened_member_types = tuple( self._flattened_member_types = tuple(
sorted(flattened_member_types, key=sort_key_typename)) sorted(flattened_member_types, key=sort_key_typename))
self._does_include_nullable_type = does_include_nullable_type self._does_include_nullable_type = does_include_nullable_type
...@@ -153,9 +153,14 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent, ...@@ -153,9 +153,14 @@ class NewUnion(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
sorted(ir.typedefs, key=sort_key_identifier)) sorted(ir.typedefs, key=sort_key_identifier))
ir.public_object = self ir.public_object = self
# TODO(yukishiino): Replace BackwardCompatibleUnion with NewUnion
# for union_type in self._union_types: for idl_type in self._idl_types:
# union_type.set_union_definition_object(self) idl_type.set_new_union_definition_object(self)
@property
def idl_types(self):
"""Returns a list of IdlTypes which this object represents."""
return self._idl_types
@property @property
def flattened_member_types(self): def flattened_member_types(self):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment