diff options
Diffstat (limited to 'src/components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r-- | src/components/script/dom/bindings/codegen/CodegenRust.py | 736 |
1 files changed, 231 insertions, 505 deletions
diff --git a/src/components/script/dom/bindings/codegen/CodegenRust.py b/src/components/script/dom/bindings/codegen/CodegenRust.py index 833ebaf1d63..2162d445c24 100644 --- a/src/components/script/dom/bindings/codegen/CodegenRust.py +++ b/src/components/script/dom/bindings/codegen/CodegenRust.py @@ -141,11 +141,9 @@ class CGThing(): """ def __init__(self): pass # Nothing for now - def declare(self): - """Produce code for a header file.""" - assert(False) # Override me! + def define(self): - """Produce code for a cpp file.""" + """Produce code for a Rust file.""" assert(False) # Override me! class CGMethodCall(CGThing): @@ -599,215 +597,28 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, if isMember: raise TypeError("Can't handle unions as members, we have a " "holderType") - nullable = type.nullable(); - if nullable: - type = type.inner - - assert(defaultValue is None or - (isinstance(defaultValue, IDLNullValue) and nullable)) - - unionArgumentObj = "${holderName}" - #if isOptional or nullable: - # unionArgumentObj += ".get_mut_ref()" - - memberTypes = type.flatMemberTypes - names = [] - interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes) - if len(interfaceMemberTypes) > 0: - interfaceObject = [] - for memberType in interfaceMemberTypes: - if type.isGeckoInterface(): - name = memberType.inner.identifier.name - else: - name = memberType.name - interfaceObject.append(CGGeneric("{res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()}" % (unionArgumentObj, name))) - names.append(name) - interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"), pre="done = ", post=";\n", reindent=True) - else: - interfaceObject = None - - arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes) - if len(arrayObjectMemberTypes) > 0: - assert len(arrayObjectMemberTypes) == 1 - memberType = arrayObjectMemberTypes[0] - name = memberType.name - arrayObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) - # XXX Now we're supposed to check for an array or a platform object - # that supports indexed properties... skip that last for now. It's a - # bit of a pain. - arrayObject = CGWrapper(CGIndenter(arrayObject), - pre="if (IsArrayLike(cx, &argObj)) {\n", - post="}") - names.append(name) - else: - arrayObject = None - - dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes) - if len(dateObjectMemberTypes) > 0: - assert len(dateObjectMemberTypes) == 1 - memberType = dateObjectMemberTypes[0] - name = memberType.name - dateObject = CGGeneric("%s.SetTo%s(cx, ${val}, ${valPtr});\n" - "done = true;" % (unionArgumentObj, name)) - dateObject = CGWrapper(CGIndenter(dateObject), - pre="if (JS_ObjectIsDate(cx, &argObj)) {\n", - post="\n}") - names.append(name) - else: - dateObject = None - - callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) - if len(callbackMemberTypes) > 0: - assert len(callbackMemberTypes) == 1 - memberType = callbackMemberTypes[0] - name = memberType.name - callbackObject = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) - names.append(name) - else: - callbackObject = None - - dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes) - if len(dictionaryMemberTypes) > 0: - raise TypeError("No support for unwrapping dictionaries as member " - "of a union") - else: - dictionaryObject = None - - if callbackObject or dictionaryObject: - nonPlatformObject = CGList([callbackObject, dictionaryObject], "\n") - nonPlatformObject = CGWrapper(CGIndenter(nonPlatformObject), - pre="if (!IsPlatformObject(cx, &argObj)) {\n", - post="\n}") - else: - nonPlatformObject = None - - objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) - if len(objectMemberTypes) > 0: - object = CGGeneric("%s.SetToObject(&argObj);\n" - "done = true;" % unionArgumentObj) - else: - object = None - - hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object - if hasObjectTypes: - # If we try more specific object types first then we need to check - # whether that succeeded before converting to object. - if object and (interfaceObject or arrayObject or dateObject or nonPlatformObject): - object = CGWrapper(CGIndenter(object), pre="if (!done) {\n", - post=("\n}")) - - if arrayObject or dateObject or nonPlatformObject: - # An object can be both an array object and not a platform - # object, but we shouldn't have both in the union's members - # because they are not distinguishable. - assert not (arrayObject and nonPlatformObject) - templateBody = CGList([arrayObject, dateObject, nonPlatformObject], " else ") - else: - templateBody = None - if interfaceObject: - if templateBody: - templateBody = CGList([templateBody, object], "\n") - templateBody = CGWrapper(CGIndenter(templateBody), - pre="if (!done) {\n", post=("\n}")) - templateBody = CGList([interfaceObject, templateBody], "\n") - else: - templateBody = CGList([templateBody, object], "\n") - - if any([arrayObject, dateObject, nonPlatformObject, object]): - templateBody.prepend(CGGeneric("JSObject& argObj = ${val}.toObject();")) - templateBody = CGWrapper(CGIndenter(templateBody), - pre="if (${val}).is_object() {\n", - post="\n}") - else: - templateBody = CGGeneric() - - otherMemberTypes = filter(lambda t: t.isString() or t.isEnum(), - memberTypes) - otherMemberTypes.extend(t for t in memberTypes if t.isPrimitive()) - if len(otherMemberTypes) > 0: - assert len(otherMemberTypes) == 1 - memberType = otherMemberTypes[0] - if memberType.isEnum(): - name = memberType.inner.identifier.name - else: - name = memberType.name - other = CGGeneric("done = {res = %s.TrySetTo%s(cx, ${val}, ${valPtr}); res.is_err() || !res.unwrap()};" % (unionArgumentObj, name)) - names.append(name) - if hasObjectTypes: - other = CGWrapper(CGIndenter(other), "{\n", post="\n}") - if object: - join = " else " - else: - other = CGWrapper(other, pre="if (!done) ") - join = "\n" - templateBody = CGList([templateBody, other], join) - else: - other = None - - templateBody = CGWrapper(templateBody, pre="let mut done = false;\n" - "let mut res = Ok(true);\n") - throw = CGGeneric("if res.is_err() {\n" - " return 0;\n" - "}\n" - "if !done {\n" - " return throw_not_in_union(cx, \"%s\");\n" - "}" % ", ".join(names)) - templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw], "\n")), pre="{\n", post="\n}") - - typeName = type.name - argumentTypeName = typeName + "Argument" - if nullable: - typeName = "Option<" + typeName + " >" - nonConstDecl = "${declName}" - - def handleNull(templateBody, setToNullVar, extraConditionForNull=""): - null = CGGeneric("if %s((${val}).is_null_or_undefined()) {\n" - " %s = None;\n" - "}" % (extraConditionForNull, setToNullVar)) - templateBody = CGWrapper(CGIndenter(templateBody), pre="{\n", post="\n}") - return CGList([null, templateBody], " else ") + declType = CGGeneric(type.name) + value = CGGeneric("value") + if type.nullable(): + declType = CGWrapper(declType, pre="Option<", post=" >") + value = CGWrapper(value, pre="Some(", post=")") - if type.hasNullableType: - templateBody = handleNull(templateBody, unionArgumentObj) + templateBody = CGGeneric("match %s::from_value(cx, ${val}) {\n" + " Err(()) => { %s },\n" + " Ok(value) => ${declName} = %s,\n" + "}" % (type.name, exceptionCode, value.define())) - declType = CGGeneric(typeName) - holderType = CGGeneric(argumentTypeName) - if isOptional: - mutableDecl = nonConstDecl + ".Value()" - declType = CGWrapper(declType, pre="const Optional<", post=" >") - holderType = CGWrapper(holderType, pre="Option<", post=" >") - constructDecl = CGGeneric(nonConstDecl + ".Construct();") - if nullable: - constructHolder = CGGeneric("${holderName} = Some(%s.SetValue());" % mutableDecl) - else: - constructHolder = CGGeneric("${holderName} = Some(${declName}.Value());") - else: - mutableDecl = nonConstDecl - constructDecl = None - holderInit = "${declName}" - if nullable: - holderInit += ".get_mut_ref()" - else: - holderInit = "&mut " + holderInit - constructHolder = CGWrapper(holderType, pre="let mut ${holderName} = ", post="::new(" + holderInit + ");") - if nullable: - constructHolder = CGWrapper(constructHolder, pre="${declName} = Some(uninit());\n") - holderType = None + if type.nullable(): + templateBody = CGIfElseWrapper( + "(${val}).is_null_or_undefined()", + CGGeneric("${declName} = None;"), + templateBody) - templateBody = CGList([constructHolder, templateBody], "\n") - if nullable: - if defaultValue: - assert(isinstance(defaultValue, IDLNullValue)) - valueMissing = "!(${haveValue}) || " - else: - valueMissing = "" - templateBody = handleNull(templateBody, mutableDecl, - extraConditionForNull=valueMissing) - templateBody = CGWrapper(CGIndenter(CGList([constructDecl, templateBody], "\n")), - pre="{\n", post="\n}") + templateBody = handleDefaultNull(templateBody.define(), + "${declName} = None") - return templateBody.define(), declType, holderType, False, "uninit()" if not nullable else None + return (templateBody, declType, None, isOptional, "None" if isOptional else None) if type.isGeckoInterface(): assert not isEnforceRange and not isClamp @@ -1084,8 +895,8 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None, template = ( "match FromJSValConvertible::from_jsval(cx, ${val}, ()) {\n" " Ok(v) => ${declName} = %s,\n" - " Err(_) => %s\n" - "}" % (successVal, failureCode)) + " Err(_) => { %s }\n" + "}" % (successVal, exceptionCode)) if type.nullable(): declType = CGGeneric("Option<" + typeName + ">") @@ -1762,9 +1573,7 @@ class CGNativePropertyHooks(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor - def declare(self): - #return "extern const NativePropertyHooks NativeHooks;\n" - return "" + def define(self): if self.descriptor.concrete and self.descriptor.proxy: resolveOwnProperty = "ResolveOwnProperty" @@ -1787,20 +1596,14 @@ class CGIndenter(CGThing): A class that takes another CGThing and generates code that indents that CGThing by some number of spaces. The default indent is two spaces. """ - def __init__(self, child, indentLevel=2, declareOnly=False): + def __init__(self, child, indentLevel=2): CGThing.__init__(self) self.child = child self.indent = " " * indentLevel - self.declareOnly = declareOnly - def declare(self): - decl = self.child.declare() - if decl is not "": - return re.sub(lineStartDetector, self.indent, decl) - else: - return "" + def define(self): defn = self.child.define() - if defn is not "" and not self.declareOnly: + if defn is not "": return re.sub(lineStartDetector, self.indent, defn) else: return defn @@ -1809,38 +1612,21 @@ class CGWrapper(CGThing): """ Generic CGThing that wraps other CGThings with pre and post text. """ - def __init__(self, child, pre="", post="", declarePre=None, - declarePost=None, definePre=None, definePost=None, - declareOnly=False, defineOnly=False, reindent=False): + def __init__(self, child, pre="", post="", reindent=False): CGThing.__init__(self) self.child = child - self.declarePre = declarePre or pre - self.declarePost = declarePost or post - self.definePre = definePre or pre - self.definePost = definePost or post - self.declareOnly = declareOnly - self.defineOnly = defineOnly + self.pre = pre + self.post = post self.reindent = reindent - def declare(self): - if self.defineOnly: - return '' - decl = self.child.declare() - if self.reindent: - # We don't use lineStartDetector because we don't want to - # insert whitespace at the beginning of our _first_ line. - decl = stripTrailingWhitespace( - decl.replace("\n", "\n" + (" " * len(self.declarePre)))) - return self.declarePre + decl + self.declarePost + def define(self): - if self.declareOnly: - return '' defn = self.child.define() if self.reindent: # We don't use lineStartDetector because we don't want to # insert whitespace at the beginning of our _first_ line. defn = stripTrailingWhitespace( - defn.replace("\n", "\n" + (" " * len(self.definePre)))) - return self.definePre + defn + self.definePost + defn.replace("\n", "\n" + (" " * len(self.pre)))) + return self.pre + defn + self.post class CGImports(CGWrapper): """ @@ -1868,7 +1654,7 @@ class CGImports(CGWrapper): statements.extend('use %s;' % i for i in sorted(imports)) CGWrapper.__init__(self, child, - declarePre='\n'.join(statements) + '\n\n') + pre='\n'.join(statements) + '\n\n') @staticmethod def getDeclarationFilename(decl): @@ -1885,23 +1671,20 @@ class CGIfWrapper(CGWrapper): post="\n}") class CGNamespace(CGWrapper): - def __init__(self, namespace, child, declareOnly=False, public=False): + def __init__(self, namespace, child, public=False): pre = "%smod %s {\n" % ("pub " if public else "", namespace) post = "} // mod %s\n" % namespace - CGWrapper.__init__(self, child, pre=pre, post=post, - declareOnly=declareOnly) + CGWrapper.__init__(self, child, pre=pre, post=post) + @staticmethod - def build(namespaces, child, declareOnly=False, public=False): + def build(namespaces, child, public=False): """ Static helper method to build multiple wrapped namespaces. """ if not namespaces: - return CGWrapper(child, declareOnly=declareOnly) - inner = CGNamespace.build(namespaces[1:], child, declareOnly=declareOnly, public=public) - return CGNamespace(namespaces[0], inner, declareOnly=declareOnly, public=public) - - def declare(self): - return "" + return child + inner = CGNamespace.build(namespaces[1:], child, public=public) + return CGNamespace(namespaces[0], inner, public=public) def DOMClass(descriptor): protoList = ['PrototypeList::id::' + proto for proto in descriptor.prototypeChain] @@ -1924,9 +1707,7 @@ class CGDOMJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor - def declare(self): - #return "extern DOMJSClass Class;\n" - return "" + def define(self): traceHook = "Some(%s)" % TRACE_HOOK_NAME if self.descriptor.createGlobal: @@ -1978,9 +1759,7 @@ class CGPrototypeJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor - def declare(self): - # We're purely for internal consumption - return "" + def define(self): return """ static PrototypeClassName__: [u8, ..%s] = %s; @@ -2016,9 +1795,7 @@ class CGInterfaceObjectJSClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor - def declare(self): - # We're purely for internal consumption - return "" + def define(self): if True: return "" @@ -2059,23 +1836,28 @@ class CGList(CGThing): self.children.insert(0, child) def join(self, generator): return self.joiner.join(filter(lambda s: len(s) > 0, (child for child in generator))) - def declare(self): - return self.join(child.declare() for child in self.children if child is not None) + def define(self): return self.join(child.define() for child in self.children if child is not None) + +class CGIfElseWrapper(CGList): + def __init__(self, condition, ifTrue, ifFalse): + kids = [ CGIfWrapper(ifTrue, condition), + CGWrapper(CGIndenter(ifFalse), pre=" else {\n", post="\n}") ] + CGList.__init__(self, kids) + + class CGGeneric(CGThing): """ A class that spits out a fixed string into the codegen. Can spit out a separate string for the declaration too. """ - def __init__(self, define="", declare=""): - self.declareText = declare - self.defineText = define - def declare(self): - return self.declareText + def __init__(self, text): + self.text = text + def define(self): - return self.defineText + return self.text def getTypes(descriptor): """ @@ -2224,7 +2006,6 @@ class CGAbstractMethod(CGThing): self.name = name self.returnType = returnType self.args = args - self.inline = inline self.alwaysInline = alwaysInline self.extern = extern self.templateArgs = templateArgs @@ -2258,17 +2039,10 @@ class CGAbstractMethod(CGThing): return "\n unsafe {" if self.unsafe else "" def _unsafe_close(self): return "\n }\n" if self.unsafe else "" - def declare(self): - if self.inline: - return self._define() - #return "%sfn %s%s(%s)%s;\n" % (self._decorators(), self.name, self._template(), - # self._argstring(), self._returnType()) - return "" - def _define(self, fromDeclare=False): + def define(self, fromDeclare=False): return self.definition_prologue(fromDeclare) + "\n" + self.definition_body() + self.definition_epilogue() - def define(self): - return "" if self.inline else self._define() + def definition_prologue(self, fromDeclare): return "%sfn %s%s(%s)%s {%s" % (self._decorators(), self.name, self._template(), self._argstring(fromDeclare), self._returnType(), self._unsafe_open()) @@ -2359,9 +2133,6 @@ class CGAbstractExternMethod(CGAbstractMethod): def __init__(self, descriptor, name, returnType, args): CGAbstractMethod.__init__(self, descriptor, name, returnType, args, inline=False, extern=True) - def declare(self): - # We only have implementation - return "" class PropertyArrays(): def __init__(self, descriptor): @@ -2559,10 +2330,6 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): args = [Argument('&mut JSPageInfo', 'js_info')] CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface', 'bool', args, pub=True) - def declare(self): - #return CGAbstractMethod.declare(self) - return "" - def define(self): return CGAbstractMethod.define(self) @@ -3124,9 +2891,6 @@ class CGMemberJITInfo(CGThing): self.member = member self.descriptor = descriptor - def declare(self): - return "" - def defineJitInfo(self, infoName, opName, infallible): protoID = "PrototypeList::id::%s as u32" % self.descriptor.name depth = self.descriptor.interface.inheritanceDepth() @@ -3200,9 +2964,6 @@ class CGEnum(CGThing): CGThing.__init__(self) self.enum = enum - def declare(self): - return "" - def define(self): return """ #[repr(uint)] @@ -3320,176 +3081,178 @@ def getUnionTypeTemplateVars(type, descriptorProvider): name = type.name typeName = "/*" + type.name + "*/" - tryNextCode = """{ - return Ok(true); -}""" (template, declType, holderType, dealWithOptional, initialValue) = getJSToNativeConversionTemplate( - type, descriptorProvider, failureCode=tryNextCode, - isDefinitelyObject=True, isOptional=type.nullable(), preSuccess="e" + name + "(", postSuccess=")") + type, descriptorProvider, failureCode="return Ok(None);", + exceptionCode='return Err(());', + isDefinitelyObject=True, isOptional=False) structType = declType.define() externalType = getUnionAccessorSignatureType(type, descriptorProvider).define() - if type.isObject(): - setter = CGGeneric("pub fn SetToObject(obj: *JSObject) {\n" - " mUnion = Some(eObject(obj));\n" - "}") - else: - jsConversion = string.Template(template).substitute( - { - "val": "value", - "valPtr": "pvalue", - "declName": "*self.mUnion", - "holderName": "m" + name + "Holder" - } - ) - jsConversion = CGWrapper(CGGeneric(jsConversion), - post="\n" - "return Ok(false);") - setter = CGWrapper(CGIndenter(jsConversion), - pre="pub fn TrySetTo" + name + "(&mut self, cx: *JSContext, value: JSVal, pvalue: *JSVal) -> Result<bool,()> {\n", - post="\n" - "}") + assert not type.isObject() + jsConversion = string.Template(template).substitute({ + "val": "value", + "valPtr": None, + "declName": "retval", + "holderName": None, + }) + jsConversion = CGWrapper(CGGeneric(jsConversion), + pre="let retval;\n", + post="\nOk(Some(retval))") return { - "name": name, - "typeName": typeName, - "structType": structType, - "externalType": externalType, - "optRef": 'ref ' if externalType[0] == '&' else '', - "setter": CGIndenter(setter).define(), - "holderType": holderType.define() if holderType else None - } - -def mapTemplate(template, templateVarArray): - return map(lambda v: string.Template(template).substitute(v), - templateVarArray) + "name": name, + "typeName": typeName, + "jsConversion": jsConversion, + } class CGUnionStruct(CGThing): def __init__(self, type, descriptorProvider): + assert not type.nullable() + assert not type.hasNullableType + CGThing.__init__(self) - self.type = type.unroll() + self.type = type self.descriptorProvider = descriptorProvider - def declare(self): + def define(self): templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider), self.type.flatMemberTypes) + enumValues = [ + " e%s(%s)," % (v["name"], v["typeName"]) for v in templateVars + ] + return ("pub enum %s {\n" + "%s\n" + "}\n") % (self.type, "\n".join(enumValues)) - callDestructors = [] - enumValues = [] - methods = [] - if self.type.hasNullableType: - callDestructors.append(" case eNull:\n" - " break;") - enumValues.append("eNull") - methods.append(""" pub fn IsNull(&self) -> bool { - match *self { - eNull => true, - _ => false - } - }""") - - destructorTemplate = """ fn Destroy${name}(&mut self) { - assert!(Is${name}(), "Wrong type!"); - *self.mUnion = None; - }""" - destructors = mapTemplate(destructorTemplate, templateVars) - callDestructors.extend(mapTemplate(" case e${name}:\n" - " Destroy${name}();\n" - " break;", templateVars)) - enumValues.extend(mapTemplate("e${name}(${typeName})", templateVars)) - methodTemplate = """ pub fn Is${name}(&self) -> bool { - match *self { - e${name}(_) => true, - _ => false - } - } - pub fn GetAs${name}<'a>(&'a self) -> ${externalType} { - assert!(self.Is${name}()); - match *self { - e${name}(${optRef}inner) => inner, - _ => unreachable!() - } - }""" - methods.extend(mapTemplate(methodTemplate, templateVars)) - values = mapTemplate("UnionMember<${structType} > m${name};", templateVars) - return string.Template(""" -pub enum ${structName} { - ${enumValues} -} - -impl ${structName} { -${methods} -} -""").substitute( - { - "structName": self.type.__str__(), - "callDestructors": "\n".join(callDestructors), - "destructors": "\n".join(destructors), - "methods": "\n\n".join(methods), - "enumValues": ",\n ".join(enumValues), - "values": "\n ".join(values), - }) - - def define(self): - return """ -""" class CGUnionConversionStruct(CGThing): def __init__(self, type, descriptorProvider): + assert not type.nullable() + assert not type.hasNullableType + CGThing.__init__(self) - self.type = type.unroll() + self.type = type self.descriptorProvider = descriptorProvider - def declare(self): - setters = [] + def from_value_method(self): + memberTypes = self.type.flatMemberTypes + names = [] + conversions = [] - if self.type.hasNullableType: - setters.append(""" pub fn SetNull(&mut self) -> bool - { - mUnion = Some(eNull); - return true; - }""") + interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes) + if len(interfaceMemberTypes) > 0: + def get_name(memberType): + if self.type.isGeckoInterface(): + return memberType.inner.identifier.name + + return memberType.name + + def get_match(name): + return ( + "match %s::TryConvertTo%s(cx, value) {\n" + " Err(_) => return Err(()),\n" + " Ok(Some(value)) => return Ok(e%s(value)),\n" + " Ok(None) => (),\n" + "}\n") % (self.type, name, name) + + typeNames = [get_name(memberType) for memberType in interfaceMemberTypes] + interfaceObject = CGList(CGGeneric(get_match(typeName)) for typeName in typeNames) + names.extend(typeNames) + else: + interfaceObject = None - templateVars = map(lambda t: getUnionTypeTemplateVars(t, self.descriptorProvider), - self.type.flatMemberTypes) - structName = self.type.__str__() - - setters.extend(mapTemplate("${setter}", templateVars)) - private = "\n".join(mapTemplate(""" fn SetAs${name}() -> &${structType} - { - mUnion.mType = mUnion.e${name}; - return mUnion.mValue.m${name}.SetValue(); - }""", templateVars)) - private += "\n\n" - holders = filter(lambda v: v["holderType"] is not None, templateVars) - if len(holders) > 0: - private += "\n".join(mapTemplate(" ${holderType} m${name}Holder;", holders)) - private += "\n\n" - private += " " + structName + "& mUnion;" - return string.Template(""" -pub struct ${structName}Argument<'a> { - mUnion: &'a mut ${innerType} -} + arrayObjectMemberTypes = filter(lambda t: t.isArray() or t.isSequence(), memberTypes) + if len(arrayObjectMemberTypes) > 0: + assert len(arrayObjectMemberTypes) == 1 + raise TypeError("Can't handle arrays or sequences in unions.") + else: + arrayObject = None -impl<'a> ${structName}Argument<'a> { - pub fn new(union: &'a mut ${innerType}) -> ${structName}Argument<'a> { - ${structName}Argument { - mUnion: union - } - } + dateObjectMemberTypes = filter(lambda t: t.isDate(), memberTypes) + if len(dateObjectMemberTypes) > 0: + assert len(dateObjectMemberTypes) == 1 + raise TypeError("Can't handle dates in unions.") + else: + dateObject = None -${setters} -} -""").substitute({"structName": structName, - "innerType": ("Option<%s>" % structName) if self.type.nullable() else structName, - "setters": "\n\n".join(setters), - }) + callbackMemberTypes = filter(lambda t: t.isCallback() or t.isCallbackInterface(), memberTypes) + if len(callbackMemberTypes) > 0: + assert len(callbackMemberTypes) == 1 + raise TypeError("Can't handle callbacks in unions.") + else: + callbackObject = None + + dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes) + if len(dictionaryMemberTypes) > 0: + raise TypeError("No support for unwrapping dictionaries as member " + "of a union") + else: + dictionaryObject = None + + if callbackObject or dictionaryObject: + assert False, "Not currently supported" + else: + nonPlatformObject = None + + objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) + if len(objectMemberTypes) > 0: + raise TypeError("Can't handle objects in unions.") + else: + object = None + + hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object + if hasObjectTypes: + assert interfaceObject + templateBody = CGList([interfaceObject], "\n") + conversions.append(CGIfWrapper(templateBody, "value.is_object()")) + + otherMemberTypes = [ + t for t in memberTypes if t.isPrimitive() or t.isString() or t.isEnum() + ] + if len(otherMemberTypes) > 0: + assert len(otherMemberTypes) == 1 + memberType = otherMemberTypes[0] + if memberType.isEnum(): + name = memberType.inner.identifier.name + else: + name = memberType.name + match = ( + "match %s::TryConvertTo%s(cx, value) {\n" + " Err(_) => return Err(()),\n" + " Ok(Some(value)) => return Ok(e%s(value)),\n" + " Ok(None) => (),\n" + "}\n") % (self.type, name, name) + conversions.append(CGGeneric(match)) + names.append(name) + + conversions.append(CGGeneric( + "throw_not_in_union(cx, \"%s\");\n" + "Err(())" % ", ".join(names))) + return CGWrapper( + CGIndenter(CGList(conversions, "\n\n")), + pre="pub fn from_value(cx: *JSContext, value: JSVal) -> Result<%s, ()> {\n" % self.type, + post="\n}") + + def try_method(self, t): + templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider) + returnType = "Result<Option<%s>, ()>" % templateVars["typeName"] + jsConversion = templateVars["jsConversion"] + + return CGWrapper( + CGIndenter(jsConversion, 4), + pre="pub fn TryConvertTo%s(cx: *JSContext, value: JSVal) -> %s {\n" % (t.name, returnType), + post="\n}") def define(self): + methods = [self.from_value_method()] + methods.extend(self.try_method(t) for t in self.type.flatMemberTypes) return """ -""" +impl %s { +%s +}""" % (self.type, CGIndenter(CGList(methods, "\n\n")).define()) + class ClassItem: """ Use with CGClass """ @@ -3872,7 +3635,7 @@ class CGClass(CGThing): in self.templateSpecialization]) return className - def declare(self): + def define(self): result = '' if self.templateArgs: templateArgs = [a.declare() for a in self.templateArgs] @@ -3948,8 +3711,6 @@ class CGClass(CGThing): result += "}" return result - def define(self): - return '' class CGXrayHelper(CGAbstractExternMethod): def __init__(self, descriptor, name, args, properties): @@ -4103,8 +3864,7 @@ class CGProxyUnwrap(CGAbstractMethod): def __init__(self, descriptor): args = [Argument('*JSObject', 'obj')] CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", '*' + descriptor.concreteType, args, alwaysInline=True) - def declare(self): - return "" + def definition_body(self): return """ /*if (xpc::WrapperFactory::IsXrayWrapper(obj)) { obj = js::UnwrapObject(obj); @@ -4493,9 +4253,7 @@ class CGDOMJSProxyHandlerDOMClass(CGThing): def __init__(self, descriptor): CGThing.__init__(self) self.descriptor = descriptor - def declare(self): - #return "extern const DOMClass Class;\n" - return "" + def define(self): return """ static Class: DOMClass = """ + DOMClass(self.descriptor) + """; @@ -4555,7 +4313,7 @@ class CGDescriptor(CGThing): cgThings.append(CGPrototypeJSClass(descriptor)) properties = PropertyArrays(descriptor) - cgThings.append(CGGeneric(define=str(properties))) + cgThings.append(CGGeneric(str(properties))) cgThings.append(CGCreateInterfaceObjectsMethod(descriptor, properties)) # Set up our Xray callbacks as needed. @@ -4605,8 +4363,6 @@ class CGDescriptor(CGThing): # post='\n') self.cgRoot = cgThings - def declare(self): - return self.cgRoot.declare() def define(self): return self.cgRoot.define() @@ -4650,8 +4406,6 @@ class CGNamespacedEnum(CGThing): # Save the result. self.node = curr - def declare(self): - return self.node.declare() def define(self): return self.node.define() @@ -4674,9 +4428,12 @@ class CGDictionary(CGThing): defaultValue=member.defaultValue)) for member in dictionary.members ] - def declare(self): + def define(self): if not self.generatable: return "" + return self.struct() + "\n" + self.impl() + + def struct(self): d = self.dictionary if d.parent: inheritance = " parent: %s::%s,\n" % (self.makeModuleName(d.parent), @@ -4697,9 +4454,7 @@ class CGDictionary(CGThing): "}").substitute( { "selfName": self.makeClassName(d), "inheritance": inheritance })) - def define(self): - if not self.generatable: - return "" + def impl(self): d = self.dictionary if d.parent: initParent = ("// Per spec, we init the parent's members first\n" @@ -4928,8 +4683,8 @@ class CGBindingRoot(CGThing): CGList([CGGeneric(" use dom::bindings::utils::EnumEntry;"), CGEnum(e)]), public=True) def makeEnumTypedef(e): - return CGGeneric(declare=("pub type %s = self::%sValues::valuelist;\n" % - (e.identifier.name, e.identifier.name))) + return CGGeneric("pub type %s = self::%sValues::valuelist;\n" % + (e.identifier.name, e.identifier.name)) cgthings = [ fun(e) for e in config.getEnums(webIDLFile) for fun in [makeEnum, makeEnumTypedef] ] @@ -5028,10 +4783,8 @@ class CGBindingRoot(CGThing): 'dom::bindings::conversions::{Default, Empty}', 'dom::bindings::codegen::*', 'dom::bindings::codegen::UnionTypes::*', - 'dom::bindings::codegen::UnionConversions::*', 'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}', 'dom::bindings::error::{throw_method_failed_with_details}', - 'dom::bindings::error::{throw_not_in_union}', 'script_task::JSPageInfo', 'dom::bindings::proxyhandler', 'dom::bindings::proxyhandler::{_obj_toString, defineProperty}', @@ -5045,7 +4798,6 @@ class CGBindingRoot(CGThing): 'std::vec', 'std::str', 'std::num', - 'std::unstable::intrinsics::uninit', 'std::unstable::raw::Box', ]) @@ -5054,8 +4806,7 @@ class CGBindingRoot(CGThing): # Store the final result. self.root = curr - def declare(self): - return stripTrailingWhitespace(self.root.declare()) + def define(self): return stripTrailingWhitespace(self.root.define()) @@ -5971,7 +5722,7 @@ class GlobalGenRoots(): return "dom::%s" % descriptor.name.lower() descriptors = [d.name for d in config.getDescriptors(register=True, hasInterfaceObject=True)] - curr = CGList([CGGeneric(declare="pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors]) + curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors]) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) return curr @@ -5979,7 +5730,7 @@ class GlobalGenRoots(): def BindingDeclarations(config): descriptors = [d.name for d in config.getDescriptors(register=True)] - curr = CGList([CGGeneric(declare="pub mod %sBinding;\n" % name) for name in descriptors]) + curr = CGList([CGGeneric("pub mod %sBinding;\n" % name) for name in descriptors]) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) return curr @@ -5987,19 +5738,19 @@ class GlobalGenRoots(): def InheritTypes(config): descriptors = config.getDescriptors(register=True, hasInterfaceObject=True) - allprotos = [CGGeneric(declare="#[allow(unused_imports)];\n"), - CGGeneric(declare="use dom::types::*;\n"), - CGGeneric(declare="use dom::bindings::js::JS;\n"), - CGGeneric(declare="use dom::bindings::trace::Traceable;\n"), - CGGeneric(declare="use extra::serialize::{Encodable, Encoder};\n"), - CGGeneric(declare="use js::jsapi::JSTracer;\n\n")] + allprotos = [CGGeneric("#[allow(unused_imports)];\n"), + CGGeneric("use dom::types::*;\n"), + CGGeneric("use dom::bindings::js::JS;\n"), + CGGeneric("use dom::bindings::trace::Traceable;\n"), + CGGeneric("use extra::serialize::{Encodable, Encoder};\n"), + CGGeneric("use js::jsapi::JSTracer;\n\n")] for descriptor in descriptors: name = descriptor.name - protos = [CGGeneric(declare='pub trait %s {}\n' % (name + 'Base'))] + protos = [CGGeneric('pub trait %s {}\n' % (name + 'Base'))] for proto in descriptor.prototypeChain: - protos += [CGGeneric(declare='impl %s for %s {}\n' % (proto + 'Base', + protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base', descriptor.concreteType))] - derived = [CGGeneric(declare='pub trait %s { fn %s(&self) -> bool; }\n' % + derived = [CGGeneric('pub trait %s { fn %s(&self) -> bool; }\n' % (name + 'Derived', 'is_' + name.lower()))] for protoName in descriptor.prototypeChain[1:-1]: protoDescriptor = config.getDescriptor(protoName) @@ -6012,10 +5763,10 @@ class GlobalGenRoots(): 'selfName': name + 'Derived', 'baseName': protoDescriptor.concreteType, 'parentName': protoDescriptor.prototypeChain[-2].lower()}) - derived += [CGGeneric(declare=delegate)] - derived += [CGGeneric(declare='\n')] + derived += [CGGeneric(delegate)] + derived += [CGGeneric('\n')] - cast = [CGGeneric(declare=string.Template('''pub trait ${castTraitName} { + cast = [CGGeneric(string.Template('''pub trait ${castTraitName} { fn from<T: ${fromBound}>(derived: &JS<T>) -> JS<Self> { unsafe { derived.clone().transmute() } } @@ -6029,9 +5780,9 @@ class GlobalGenRoots(): 'castTraitName': name + 'Cast', 'fromBound': name + 'Base', 'toBound': name + 'Derived'})), - CGGeneric(declare="impl %s for %s {}\n\n" % (name + 'Cast', name))] + CGGeneric("impl %s for %s {}\n\n" % (name + 'Cast', name))] - trace = [CGGeneric(declare=string.Template('''impl Traceable for ${name} { + trace = [CGGeneric(string.Template('''impl Traceable for ${name} { fn trace(&self, tracer: *mut JSTracer) { unsafe { self.encode(&mut *tracer); @@ -6086,7 +5837,7 @@ class GlobalGenRoots(): #stack[len(elements)].append(clazz) - curr = CGList([stack[0], curr], "\n") + curr = CGList([stack[0], curr, UnionConversions(config.getDescriptors())], "\n") #curr = CGHeaders([], [], includes, [], curr) @@ -6094,37 +5845,12 @@ class GlobalGenRoots(): #curr = CGIncludeGuard('UnionTypes', curr) curr = CGImports(curr, [ - 'dom::bindings::js::JS', - 'dom::types::*', - ]) - - # Add the auto-generated comment. - curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) - - # Done. - return curr - - @staticmethod - def UnionConversions(config): - - unions = UnionConversions(config.getDescriptors()) - curr = unions - - # Wrap all of that in our namespaces. - #curr = CGNamespace.build(['mozilla', 'dom'], unions) - - curr = CGWrapper(curr, post='\n') - - #curr = CGHeaders([], [], ["nsDebug.h", "mozilla/dom/UnionTypes.h", "nsDOMQS.h"], [], curr) - - # Add include guards. - #curr = CGIncludeGuard('UnionConversions', curr) - - curr = CGImports(curr, [ 'dom::bindings::utils::unwrap_jsmanaged', - 'dom::bindings::codegen::UnionTypes::*', 'dom::bindings::codegen::PrototypeList', 'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}', + 'dom::bindings::error::throw_not_in_union', + 'dom::bindings::js::JS', + 'dom::types::*', 'js::{crust, JS_ARGV, JS_CALLEE, JS_THIS_OBJECT}', 'js::{JSCLASS_GLOBAL_SLOT_COUNT, JSCLASS_IS_DOMJSCLASS}', 'js::{JSCLASS_IS_GLOBAL, JSCLASS_RESERVED_SLOTS_SHIFT}', |