Mojo: Add support for constants to the IDL compiler.

Only supports POD-types and strings currently.

BUG=320091

Review URL: https://codereview.chromium.org/268363003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269659 0039d316-1c4b-4281-b951-d872f2087c98
parent 6ba165ef
...@@ -8,6 +8,8 @@ import "sample_import2.mojom" ...@@ -8,6 +8,8 @@ import "sample_import2.mojom"
[JavaPackage="org.chromium.mojo.bindings.test"] [JavaPackage="org.chromium.mojo.bindings.test"]
module sample { module sample {
const uint8 kThree = 3;
struct Bar { struct Bar {
enum Type { enum Type {
TYPE_VERTICAL = 1 << 0, TYPE_VERTICAL = 1 << 0,
...@@ -23,7 +25,8 @@ struct Bar { ...@@ -23,7 +25,8 @@ struct Bar {
[RequiredFields=7] [RequiredFields=7]
struct Foo { struct Foo {
string name = "Fooby" @8; const string kFooby = "Fooby";
string name = kFooby @8;
int32 x @0; int32 x @0;
int32 y @1; int32 y @1;
bool a = true @2; bool a = true @2;
...@@ -31,7 +34,7 @@ struct Foo { ...@@ -31,7 +34,7 @@ struct Foo {
bool c @4; bool c @4;
Bar bar @5; Bar bar @5;
Bar[] extra_bars @7; Bar[] extra_bars @7;
uint8[] data = [1,2,3] @6; uint8[] data = [1,2,kThree] @6;
handle<message_pipe> source @9; handle<message_pipe> source @9;
handle<data_pipe_consumer>[] input_streams @10; handle<data_pipe_consumer>[] input_streams @10;
handle<data_pipe_producer>[] output_streams @11; handle<data_pipe_producer>[] output_streams @11;
...@@ -59,6 +62,7 @@ interface Service { ...@@ -59,6 +62,7 @@ interface Service {
BAZ_REGULAR = 0, BAZ_REGULAR = 0,
BAZ_EXTRA BAZ_EXTRA
}; };
const uint8 kFavoriteBaz = 1;
Frobinate@0(Foo foo @0, BazOptions baz @1, Port port @2); Frobinate@0(Foo foo @0, BazOptions baz @1, Port port @2);
}; };
......
...@@ -15,6 +15,11 @@ class {{interface.name}} { ...@@ -15,6 +15,11 @@ class {{interface.name}} {
typedef mojo::NoInterface Client_; typedef mojo::NoInterface Client_;
{% endif %} {% endif %}
{#--- Constants #}
{%- for constant in interface.constants %}
static const {{constant.kind|cpp_pod_type}} {{constant.name}};
{%- endfor %}
{#--- Enums #} {#--- Enums #}
{%- for enum in interface.enums %} {%- for enum in interface.enums %}
{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %} {% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
......
...@@ -59,6 +59,13 @@ params->{{param.name}}() ...@@ -59,6 +59,13 @@ params->{{param.name}}()
builder.Finish(&message); builder.Finish(&message);
{%- endmacro %} {%- endmacro %}
{#--- Begin #}
{#--- Constants #}
{% for constant in interface.constants %}
const {{constant.kind|cpp_pod_type}} {{interface.name}}::{{constant.name}} = {{constant.value|expression_to_text(module)}};
{%- endfor %}
{#--- ForwardToCallback definition #} {#--- ForwardToCallback definition #}
{%- for method in interface.methods -%} {%- for method in interface.methods -%}
{%- if method.response_parameters != None %} {%- if method.response_parameters != None %}
......
...@@ -15,6 +15,12 @@ ...@@ -15,6 +15,12 @@
{%- for namespace in namespaces_as_array %} {%- for namespace in namespaces_as_array %}
namespace {{namespace}} { namespace {{namespace}} {
{%- endfor %} {%- endfor %}
{#--- Constants #}
{% for constant in module.constants %}
const {{constant.kind|cpp_pod_type}} {{constant.name}} = {{constant.value|expression_to_text(module)}};
{%- endfor %}
namespace internal { namespace internal {
namespace { namespace {
...@@ -50,6 +56,13 @@ const uint32_t {{method_name}} = {{method.ordinal}}; ...@@ -50,6 +56,13 @@ const uint32_t {{method_name}} = {{method.ordinal}};
} // namespace internal } // namespace internal
{#--- Struct Constants #}
{%- for struct in structs %}
{% for constant in struct.constants %}
const {{constant.kind|cpp_pod_type}} {{struct.name}}::{{constant.name}} = {{constant.value|expression_to_text(module)}};
{%- endfor %}
{%- endfor %}
{#--- Struct builder definitions #} {#--- Struct builder definitions #}
{%- for struct in structs %} {%- for struct in structs %}
{%- include "struct_builder_definition.tmpl" %} {%- include "struct_builder_definition.tmpl" %}
......
...@@ -22,6 +22,11 @@ ...@@ -22,6 +22,11 @@
namespace {{namespace}} { namespace {{namespace}} {
{%- endfor %} {%- endfor %}
{#--- Constants #}
{% for constant in module.constants %}
extern const {{constant.kind|cpp_pod_type}} {{constant.name}};
{%- endfor %}
{#--- Enums #} {#--- Enums #}
{% for enum in enums %} {% for enum in enums %}
{% include "enum_declaration.tmpl" %} {% include "enum_declaration.tmpl" %}
......
{%- import "struct_macros.tmpl" as struct_macros %} {%- import "struct_macros.tmpl" as struct_macros %}
{%- set class_name = struct.name ~ "_Data" %} {%- set class_name = struct.name ~ "_Data" %}
// static // static
{{class_name}}* {{class_name}}::New(mojo::Buffer* buf, mojo::Buffer::Destructor dtor) { {{class_name}}* {{class_name}}::New(mojo::Buffer* buf, mojo::Buffer::Destructor dtor) {
return new (buf->Allocate(sizeof({{class_name}}), dtor)) {{class_name}}(); return new (buf->Allocate(sizeof({{class_name}}), dtor)) {{class_name}}();
......
...@@ -2,6 +2,11 @@ class {{struct.name}} { ...@@ -2,6 +2,11 @@ class {{struct.name}} {
public: public:
typedef internal::{{struct.name}}_Data Data; typedef internal::{{struct.name}}_Data Data;
{#--- Constants #}
{% for constant in struct.constants %}
static const {{constant.kind|cpp_pod_type}} {{constant.name}};
{%- endfor %}
{#--- Enums #} {#--- Enums #}
{%- for enum in struct.enums -%} {%- for enum in struct.enums -%}
{% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %} {% macro enum_def() %}{% include "enum_declaration.tmpl" %}{% endmacro %}
......
...@@ -109,3 +109,9 @@ params.{{parameter.name}}{% if not loop.last %}, {% endif -%} ...@@ -109,3 +109,9 @@ params.{{parameter.name}}{% if not loop.last %}, {% endif -%}
{{enum_def("%sProxy.%s"|format(interface.name, enum.name), enum, module)}} {{enum_def("%sProxy.%s"|format(interface.name, enum.name), enum, module)}}
{{interface.name}}Stub.{{enum.name}} = {{interface.name}}Proxy.{{enum.name}}; {{interface.name}}Stub.{{enum.name}} = {{interface.name}}Proxy.{{enum.name}};
{%- endfor %} {%- endfor %}
{#--- Constants. #}
{% for constant in interface.constants %}
{{interface.name}}Proxy.{{constant.name}} = {{constant.value|expression_to_text(module)}};
{{interface.name}}Stub.{{constant.name}} = {{interface.name}}Proxy.{{constant.name}};
{% endfor %}
...@@ -14,9 +14,14 @@ define("{{module.path}}", [ ...@@ -14,9 +14,14 @@ define("{{module.path}}", [
{%- endfor -%} {%- endfor -%}
) { ) {
{#--- Constants #}
{% for constant in module.constants %}
var {{constant.name}} = {{constant.value|expression_to_text(module)}};
{%- endfor %}
{#--- Enums #} {#--- Enums #}
{% from "enum_definition.tmpl" import enum_def -%} {%- from "enum_definition.tmpl" import enum_def %}
{% for enum in enums %} {%- for enum in enums %}
var {{ enum_def(enum.name, enum, module) }} var {{ enum_def(enum.name, enum, module) }}
{%- endfor %} {%- endfor %}
...@@ -31,6 +36,9 @@ define("{{module.path}}", [ ...@@ -31,6 +36,9 @@ define("{{module.path}}", [
{%- endfor %} {%- endfor %}
var exports = {}; var exports = {};
{% for constant in module.constants %}
exports.{{constant.name}} = {{constant.name}};
{%- endfor %}
{%- for enum in enums %} {%- for enum in enums %}
exports.{{enum.name}} = {{enum.name}}; exports.{{enum.name}} = {{enum.name}};
{%- endfor %} {%- endfor %}
......
...@@ -40,15 +40,23 @@ tmp{{depth}}.{{subfield.name}} = {{result}}; ...@@ -40,15 +40,23 @@ tmp{{depth}}.{{subfield.name}} = {{result}};
{%- endmacro %} {%- endmacro %}
{#--- Begin #} {#--- Begin #}
{#--- Enums. We must define these before the constructor because they function {{struct.name}}() {
may be used there. Later, we alias these to be class static variables. #} this.initDefaults_();
}
{#--- Enums #}
{%- from "enum_definition.tmpl" import enum_def %} {%- from "enum_definition.tmpl" import enum_def %}
{% for enum in struct.enums %} {% for enum in struct.enums %}
var {{enum_def("%s_%s"|format(struct.name, enum.name), enum, module)}} {{enum_def("%s.%s"|format(struct.name, enum.name), enum, module)}}
{% endfor %} {% endfor %}
{#--- Constructor #} {#--- Constants #}
function {{struct.name}}() { {% for constant in struct.constants %}
{{struct.name}}.{{constant.name}} = {{constant.value|expression_to_text(module)}};
{% endfor %}
{#--- Set up defaults #}
{{struct.name}}.prototype.initDefaults_ = function() {
{%- for packed_field in struct.packed.packed_fields %} {%- for packed_field in struct.packed.packed_fields %}
{%- if packed_field.field.default %} {%- if packed_field.field.default %}
{%- filter indent(4) %} {%- filter indent(4) %}
...@@ -60,12 +68,7 @@ this.{{packed_field.field.name}} = {{result}}; ...@@ -60,12 +68,7 @@ this.{{packed_field.field.name}} = {{result}};
this.{{packed_field.field.name}} = {{packed_field.field|default_value}}; this.{{packed_field.field.name}} = {{packed_field.field|default_value}};
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
} };
{#--- Alias any Struct_Enum enums to Struct.Enum #}
{% for enum in struct.enums %}
{{struct.name}}.{{enum.name}} = {{struct.name}}_{{enum.name}};
{%- endfor %}
{#--- Encoding and decoding #} {#--- Encoding and decoding #}
......
...@@ -57,6 +57,11 @@ def GetCppType(kind): ...@@ -57,6 +57,11 @@ def GetCppType(kind):
return "mojo::internal::String_Data*" return "mojo::internal::String_Data*"
return _kind_to_cpp_type[kind] return _kind_to_cpp_type[kind]
def GetCppPodType(kind):
if kind.spec == 's':
return "char*"
return _kind_to_cpp_type[kind]
def GetCppArrayArgWrapperType(kind): def GetCppArrayArgWrapperType(kind):
if isinstance(kind, (mojom.Struct, mojom.Enum)): if isinstance(kind, (mojom.Struct, mojom.Enum)):
return GetNameForKind(kind) return GetNameForKind(kind)
...@@ -148,15 +153,15 @@ def IsStructWithHandles(struct): ...@@ -148,15 +153,15 @@ def IsStructWithHandles(struct):
return False return False
def TranslateConstants(token, module): def TranslateConstants(token, module):
if isinstance(token, mojom.Constant): if isinstance(token, (mojom.NamedValue, mojom.EnumValue)):
# Enum constants are constructed like: # Both variable and enum constants are constructed like:
# Namespace::Struct::FIELD_NAME # Namespace::Struct::CONSTANT_NAME
name = [] name = []
if token.imported_from: if token.imported_from:
name.extend(NamespaceToArray(token.namespace)) name.extend(NamespaceToArray(token.namespace))
if token.parent_kind: if token.parent_kind:
name.append(token.parent_kind.name) name.append(token.parent_kind.name)
name.append(token.name[1]) name.append(token.name)
return "::".join(name) return "::".join(name)
return token return token
...@@ -173,8 +178,9 @@ class Generator(generator.Generator): ...@@ -173,8 +178,9 @@ class Generator(generator.Generator):
cpp_filters = { cpp_filters = {
"cpp_const_wrapper_type": GetCppConstWrapperType, "cpp_const_wrapper_type": GetCppConstWrapperType,
"cpp_field_type": GetCppFieldType, "cpp_field_type": GetCppFieldType,
"cpp_type": GetCppType, "cpp_pod_type": GetCppPodType,
"cpp_result_type": GetCppResultWrapperType, "cpp_result_type": GetCppResultWrapperType,
"cpp_type": GetCppType,
"cpp_wrapper_type": GetCppWrapperType, "cpp_wrapper_type": GetCppWrapperType,
"expression_to_text": ExpressionToText, "expression_to_text": ExpressionToText,
"get_pad": pack.GetPad, "get_pad": pack.GetPad,
......
...@@ -36,9 +36,9 @@ def JavaScriptDefaultValue(field): ...@@ -36,9 +36,9 @@ def JavaScriptDefaultValue(field):
if field.kind in mojom.PRIMITIVES: if field.kind in mojom.PRIMITIVES:
return _kind_to_javascript_default_value[field.kind] return _kind_to_javascript_default_value[field.kind]
if isinstance(field.kind, mojom.Struct): if isinstance(field.kind, mojom.Struct):
return "null"; return "null"
if isinstance(field.kind, mojom.Array): if isinstance(field.kind, mojom.Array):
return "[]"; return "[]"
if isinstance(field.kind, mojom.Interface): if isinstance(field.kind, mojom.Interface):
return _kind_to_javascript_default_value[mojom.MSGPIPE] return _kind_to_javascript_default_value[mojom.MSGPIPE]
if isinstance(field.kind, mojom.Enum): if isinstance(field.kind, mojom.Enum):
...@@ -48,11 +48,11 @@ def JavaScriptDefaultValue(field): ...@@ -48,11 +48,11 @@ def JavaScriptDefaultValue(field):
def JavaScriptPayloadSize(packed): def JavaScriptPayloadSize(packed):
packed_fields = packed.packed_fields packed_fields = packed.packed_fields
if not packed_fields: if not packed_fields:
return 0; return 0
last_field = packed_fields[-1] last_field = packed_fields[-1]
offset = last_field.offset + last_field.size offset = last_field.offset + last_field.size
pad = pack.GetPad(offset, 8) pad = pack.GetPad(offset, 8)
return offset + pad; return offset + pad
_kind_to_codec_type = { _kind_to_codec_type = {
...@@ -92,11 +92,11 @@ def CodecType(kind): ...@@ -92,11 +92,11 @@ def CodecType(kind):
def JavaScriptDecodeSnippet(kind): def JavaScriptDecodeSnippet(kind):
if kind in mojom.PRIMITIVES: if kind in mojom.PRIMITIVES:
return "decodeStruct(%s)" % CodecType(kind); return "decodeStruct(%s)" % CodecType(kind)
if isinstance(kind, mojom.Struct): if isinstance(kind, mojom.Struct):
return "decodeStructPointer(%s)" % CodecType(kind.name); return "decodeStructPointer(%s)" % CodecType(kind.name)
if isinstance(kind, mojom.Array): if isinstance(kind, mojom.Array):
return "decodeArrayPointer(%s)" % CodecType(kind.kind); return "decodeArrayPointer(%s)" % CodecType(kind.kind)
if isinstance(kind, mojom.Interface): if isinstance(kind, mojom.Interface):
return JavaScriptDecodeSnippet(mojom.MSGPIPE) return JavaScriptDecodeSnippet(mojom.MSGPIPE)
if isinstance(kind, mojom.Enum): if isinstance(kind, mojom.Enum):
...@@ -105,28 +105,29 @@ def JavaScriptDecodeSnippet(kind): ...@@ -105,28 +105,29 @@ def JavaScriptDecodeSnippet(kind):
def JavaScriptEncodeSnippet(kind): def JavaScriptEncodeSnippet(kind):
if kind in mojom.PRIMITIVES: if kind in mojom.PRIMITIVES:
return "encodeStruct(%s, " % CodecType(kind); return "encodeStruct(%s, " % CodecType(kind)
if isinstance(kind, mojom.Struct): if isinstance(kind, mojom.Struct):
return "encodeStructPointer(%s, " % CodecType(kind.name); return "encodeStructPointer(%s, " % CodecType(kind.name)
if isinstance(kind, mojom.Array): if isinstance(kind, mojom.Array):
return "encodeArrayPointer(%s, " % CodecType(kind.kind); return "encodeArrayPointer(%s, " % CodecType(kind.kind)
if isinstance(kind, mojom.Interface): if isinstance(kind, mojom.Interface):
return JavaScriptEncodeSnippet(mojom.MSGPIPE) return JavaScriptEncodeSnippet(mojom.MSGPIPE)
if isinstance(kind, mojom.Enum): if isinstance(kind, mojom.Enum):
return JavaScriptEncodeSnippet(mojom.INT32) return JavaScriptEncodeSnippet(mojom.INT32)
def TranslateConstants(token, module): def TranslateConstants(token, module):
if isinstance(token, mojom.Constant): if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
# Enum constants are constructed like: # Both variable and enum constants are constructed like:
# NamespaceUid.Struct_Enum.FIELD_NAME # NamespaceUid.Struct[.Enum].CONSTANT_NAME
name = [] name = []
if token.imported_from: if token.imported_from:
name.append(token.imported_from["unique_name"]) name.append(token.imported_from["unique_name"])
if token.parent_kind: if token.parent_kind:
name.append(token.parent_kind.name + "_" + token.name[0]) name.append(token.parent_kind.name)
else: if isinstance(token, mojom.EnumValue):
name.append(token.name[0]) name.append(token.enum_name)
name.append(token.name[1]) name.append(token.name)
return ".".join(name) return ".".join(name)
return token return token
......
...@@ -65,17 +65,17 @@ def LookupKind(kinds, spec, scope): ...@@ -65,17 +65,17 @@ def LookupKind(kinds, spec, scope):
return kinds.get(spec) return kinds.get(spec)
def LookupConstant(constants, name, scope): def LookupValue(values, name, scope):
"""Like LookupKind, but for constants.""" """Like LookupKind, but for constant values."""
for i in xrange(len(scope), -1, -1): for i in xrange(len(scope), -1, -1):
if i > 0: if i > 0:
test_spec = '.'.join(scope[:i]) + '.' test_spec = '.'.join(scope[:i]) + '.'
test_spec += name test_spec += name
constant = constants.get(test_spec) value = values.get(test_spec)
if constant: if value:
return constant return value
return constants.get(name) return values.get(name)
def KindToData(kind): def KindToData(kind):
return kind.spec return kind.spec
...@@ -114,12 +114,12 @@ def ImportFromData(module, data): ...@@ -114,12 +114,12 @@ def ImportFromData(module, data):
kind.imported_from is None): kind.imported_from is None):
kind = KindFromImport(kind, import_item) kind = KindFromImport(kind, import_item)
module.kinds[kind.spec] = kind module.kinds[kind.spec] = kind
# Ditto for constants. # Ditto for values.
for constant in import_module.constants.itervalues(): for value in import_module.values.itervalues():
if constant.imported_from is None: if value.imported_from is None:
constant = copy.deepcopy(constant) value = copy.deepcopy(value)
constant.imported_from = import_item value.imported_from = import_item
module.constants[constant.GetSpec()] = constant module.values[value.GetSpec()] = value
return import_item return import_item
...@@ -137,6 +137,8 @@ def StructFromData(module, data): ...@@ -137,6 +137,8 @@ def StructFromData(module, data):
module.kinds[struct.spec] = struct module.kinds[struct.spec] = struct
struct.enums = map(lambda enum: struct.enums = map(lambda enum:
EnumFromData(module, enum, struct), data['enums']) EnumFromData(module, enum, struct), data['enums'])
struct.constants = map(lambda constant:
ConstantFromData(module, constant, struct), data['constants'])
# Stash fields data here temporarily. # Stash fields data here temporarily.
struct.fields_data = data['fields'] struct.fields_data = data['fields']
return struct return struct
...@@ -160,9 +162,9 @@ def FixupExpression(module, value, scope): ...@@ -160,9 +162,9 @@ def FixupExpression(module, value, scope):
else: else:
value[i] = FixupExpression(module, value[i], scope) value[i] = FixupExpression(module, value[i], scope)
elif value: elif value:
constant = LookupConstant(module.constants, value, scope) result = LookupValue(module.values, value, scope)
if constant: if result:
return constant return result
return value return value
def FieldFromData(module, data, struct): def FieldFromData(module, data, struct):
...@@ -233,6 +235,8 @@ def InterfaceFromData(module, data): ...@@ -233,6 +235,8 @@ def InterfaceFromData(module, data):
module.kinds[interface.spec] = interface module.kinds[interface.spec] = interface
interface.enums = map(lambda enum: interface.enums = map(lambda enum:
EnumFromData(module, enum, interface), data['enums']) EnumFromData(module, enum, interface), data['enums'])
interface.constants = map(lambda constant:
ConstantFromData(module, constant, interface), data['constants'])
# Stash methods data here temporarily. # Stash methods data here temporarily.
interface.methods_data = data['methods'] interface.methods_data = data['methods']
return interface return interface
...@@ -240,14 +244,18 @@ def InterfaceFromData(module, data): ...@@ -240,14 +244,18 @@ def InterfaceFromData(module, data):
def EnumFieldFromData(module, enum, data, parent_kind): def EnumFieldFromData(module, enum, data, parent_kind):
field = mojom.EnumField() field = mojom.EnumField()
field.name = data['name'] field.name = data['name']
# TODO(mpcomplete): FixupExpression should be done in the second pass,
# so constants and enums can refer to each other.
# TODO(mpcomplete): But then, what if constants are initialized to an enum? Or
# vice versa?
if parent_kind: if parent_kind:
field.value = FixupExpression( field.value = FixupExpression(
module, data['value'], (module.namespace, parent_kind.name)) module, data['value'], (module.namespace, parent_kind.name))
else: else:
field.value = FixupExpression( field.value = FixupExpression(
module, data['value'], (module.namespace, )) module, data['value'], (module.namespace, ))
constant = mojom.Constant(module, enum, field) value = mojom.EnumValue(module, enum, field)
module.constants[constant.GetSpec()] = constant module.values[value.GetSpec()] = value
return field return field
def EnumFromData(module, data, parent_kind): def EnumFromData(module, data, parent_kind):
...@@ -265,6 +273,21 @@ def EnumFromData(module, data, parent_kind): ...@@ -265,6 +273,21 @@ def EnumFromData(module, data, parent_kind):
module.kinds[enum.spec] = enum module.kinds[enum.spec] = enum
return enum return enum
def ConstantFromData(module, data, parent_kind):
constant = mojom.Constant()
constant.name = data['name']
if parent_kind:
scope = (module.namespace, parent_kind.name)
else:
scope = (module.namespace, )
# TODO(mpcomplete): maybe we should only support POD kinds.
constant.kind = KindFromData(module.kinds, data['kind'], scope)
constant.value = FixupExpression(module, data.get('value'), scope)
value = mojom.NamedValue(module, parent_kind, constant.name)
module.values[value.GetSpec()] = value
return constant
def ModuleToData(module): def ModuleToData(module):
return { return {
istr(0, 'name'): module.name, istr(0, 'name'): module.name,
...@@ -279,7 +302,7 @@ def ModuleFromData(data): ...@@ -279,7 +302,7 @@ def ModuleFromData(data):
for kind in mojom.PRIMITIVES: for kind in mojom.PRIMITIVES:
module.kinds[kind.spec] = kind module.kinds[kind.spec] = kind
module.constants = {} module.values = {}
module.name = data['name'] module.name = data['name']
module.namespace = data['namespace'] module.namespace = data['namespace']
...@@ -298,6 +321,9 @@ def ModuleFromData(data): ...@@ -298,6 +321,9 @@ def ModuleFromData(data):
module.interfaces = map( module.interfaces = map(
lambda interface: InterfaceFromData(module, interface), lambda interface: InterfaceFromData(module, interface),
data['interfaces']) data['interfaces'])
module.constants = map(
lambda constant: ConstantFromData(module, constant, None),
data['constants'])
# Second pass expands fields and methods. This allows fields and parameters # Second pass expands fields and methods. This allows fields and parameters
# to refer to kinds defined anywhere in the mojom. # to refer to kinds defined anywhere in the mojom.
......
...@@ -60,18 +60,31 @@ PRIMITIVES = ( ...@@ -60,18 +60,31 @@ PRIMITIVES = (
) )
class Constant(object): class NamedValue(object):
def __init__(self, module, enum, field): def __init__(self, module, parent_kind, name):
self.module = module self.module = module
self.namespace = module.namespace self.namespace = module.namespace
self.parent_kind = enum.parent_kind self.parent_kind = parent_kind
self.name = [enum.name, field.name] self.name = name
self.imported_from = None self.imported_from = None
def GetSpec(self): def GetSpec(self):
return (self.namespace + '.' + return (self.namespace + '.' +
(self.parent_kind and (self.parent_kind.name + '.') or "") + \ (self.parent_kind and (self.parent_kind.name + '.') or "") +
self.name[1]) self.name)
class EnumValue(NamedValue):
def __init__(self, module, enum, field):
NamedValue.__init__(self, module, enum.parent_kind, field.name)
self.enum_name = enum.name
class Constant(object):
def __init__(self, name=None, kind=None, value=None):
self.name = name
self.kind = kind
self.value = value
class Field(object): class Field(object):
......
...@@ -67,6 +67,7 @@ class Lexer(object): ...@@ -67,6 +67,7 @@ class Lexer(object):
'STRUCT', 'STRUCT',
'INTERFACE', 'INTERFACE',
'ENUM', 'ENUM',
'CONST',
) )
keyword_map = {} keyword_map = {}
......
...@@ -101,7 +101,8 @@ class Parser(object): ...@@ -101,7 +101,8 @@ class Parser(object):
def p_definition(self, p): def p_definition(self, p):
"""definition : struct """definition : struct
| interface | interface
| enum""" | enum
| const"""
p[0] = p[1] p[0] = p[1]
def p_attribute_section(self, p): def p_attribute_section(self, p):
...@@ -131,6 +132,7 @@ class Parser(object): ...@@ -131,6 +132,7 @@ class Parser(object):
def p_struct_body(self, p): def p_struct_body(self, p):
"""struct_body : field struct_body """struct_body : field struct_body
| enum struct_body | enum struct_body
| const struct_body
| """ | """
if len(p) > 1: if len(p) > 1:
p[0] = _ListFromConcat(p[1], p[2]) p[0] = _ListFromConcat(p[1], p[2])
...@@ -154,6 +156,7 @@ class Parser(object): ...@@ -154,6 +156,7 @@ class Parser(object):
def p_interface_body(self, p): def p_interface_body(self, p):
"""interface_body : method interface_body """interface_body : method interface_body
| enum interface_body | enum interface_body
| const interface_body
| """ | """
if len(p) > 1: if len(p) > 1:
p[0] = _ListFromConcat(p[1], p[2]) p[0] = _ListFromConcat(p[1], p[2])
...@@ -243,6 +246,10 @@ class Parser(object): ...@@ -243,6 +246,10 @@ class Parser(object):
else: else:
p[0] = ('ENUM_FIELD', p[1], p[3]) p[0] = ('ENUM_FIELD', p[1], p[3])
def p_const(self, p):
"""const : CONST typename NAME EQUALS expression SEMI"""
p[0] = ('CONST', p[2], p[3], p[5])
### Expressions ### ### Expressions ###
def p_expression_object(self, p): def p_expression_object(self, p):
......
...@@ -83,6 +83,7 @@ def _MapStruct(tree): ...@@ -83,6 +83,7 @@ def _MapStruct(tree):
struct['attributes'] = _MapAttributes(tree[2]) struct['attributes'] = _MapAttributes(tree[2])
struct['fields'] = _MapTree(_MapField, tree[3], 'FIELD') struct['fields'] = _MapTree(_MapField, tree[3], 'FIELD')
struct['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') struct['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
struct['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
return struct return struct
def _MapInterface(tree): def _MapInterface(tree):
...@@ -91,6 +92,7 @@ def _MapInterface(tree): ...@@ -91,6 +92,7 @@ def _MapInterface(tree):
interface['client'] = _GetAttribute(tree[2], 'Client') interface['client'] = _GetAttribute(tree[2], 'Client')
interface['methods'] = _MapTree(_MapMethod, tree[3], 'METHOD') interface['methods'] = _MapTree(_MapMethod, tree[3], 'METHOD')
interface['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') interface['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
interface['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
return interface return interface
def _MapEnum(tree): def _MapEnum(tree):
...@@ -99,6 +101,13 @@ def _MapEnum(tree): ...@@ -99,6 +101,13 @@ def _MapEnum(tree):
enum['fields'] = _MapTree(_MapEnumField, tree[2], 'ENUM_FIELD') enum['fields'] = _MapTree(_MapEnumField, tree[2], 'ENUM_FIELD')
return enum return enum
def _MapConstant(tree):
constant = {}
constant['name'] = tree[2]
constant['kind'] = _MapKind(tree[1])
constant['value'] = tree[3]
return constant
def _MapModule(tree, name): def _MapModule(tree, name):
mojom = {} mojom = {}
mojom['name'] = name mojom['name'] = name
...@@ -107,6 +116,7 @@ def _MapModule(tree, name): ...@@ -107,6 +116,7 @@ def _MapModule(tree, name):
mojom['structs'] = _MapTree(_MapStruct, tree[3], 'STRUCT') mojom['structs'] = _MapTree(_MapStruct, tree[3], 'STRUCT')
mojom['interfaces'] = _MapTree(_MapInterface, tree[3], 'INTERFACE') mojom['interfaces'] = _MapTree(_MapInterface, tree[3], 'INTERFACE')
mojom['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM') mojom['enums'] = _MapTree(_MapEnum, tree[3], 'ENUM')
mojom['constants'] = _MapTree(_MapConstant, tree[3], 'CONST')
return mojom return mojom
def _MapImport(tree): def _MapImport(tree):
......
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