From: Donny V. <don...@gm...> - 2010-03-02 05:46:34
|
Hi all. So I've noticed a common programming pattern in other SWIG modules. Here's some pseudo-code: class MyLanguage : public Language { bool specialMode; int processSomeNode(Node* n){ if (doWeNeedSpecialMode(n)) specialMode = true; Language::processSomeNode(n); specialMode = false; } }; In English, what this pattern attempts to accomplish is to pass down a notional attribute to nodes nested in some node that contains the clues for special processing. The pattern I expected to be available to me is that some attributes could simply be inherited from the nodes that contained them. The obvious case for an attribute that should be inherited by a node's children is what its parents are, but I can imagine others. My use case: In Javascript as in many other scripting languages, "Objects" (or hashes, or tables; whatever you want to call them) are the single unified organizational paradigm for the language. OOP classes in Javascript are more or less (a bit less, actually) accomplished using Objects. Javascript's analog to a C++ namespace is an Object. Functions in Javascript can have properties (attributes) associated on them *just* like Objects, and so Javascript's analog to static class methods are (more or less) Objects. Perhaps I'm saying "Objects" too much, when what I really mean is that everything fits into a very natural hierarchical organization. Here is some early code from my SWIG module to further demonstrate what I mean, in pseudo-code form for clarity (to avoid confusion, you should know that "node" here is a "ModuleTree" element, not a SWIG Node, but they're conceptually similar): RegisterModuleTree(ModuleTree *node, JSObject *parent) { do { switch (node->type) { case TYPE_PRIMITIVE: RegisterPrimitive(node, parent); break; case TYPE_NAMESPACE JSObject *newNamespaceObject = RegisterNewObject(node, parent); if (node->hasChildren) RegisterModuleTree(node->firstChild, newNamespaceObject); break; /* other types... */ } } while (NULL != (node = node->nextSibling)); } So you can see in my wrapper code produced by SWIG, the initialization code walks through a hierarchical tree and begins defining variables and entry points for the interpreter. Emitting code to define a tree structure unsurprisingly necessitates building that tree structure (or something similar to it) in my SWIG module. I thought this would be straightforward, but I couldn't find any inheritance mechanisms, or a "parent" link for SWIG Nodes that I could use to walk up a Node tree and infer what attributes my Node should be inheriting. The need for SWIG Node attribute inheritance is so that I can avoid an annoying "push and pop" pattern of programming that is used in many other SWIG modules (no insult to any SWIG module programmers! you guys are great!:) So I thought I would just be able to do something like this: Setattr(n, "mytree:bookmark", treeParent); If I had a way of achieving inheritance, then in namespaceWrapper() or classWrapper() or any other wrapper that will require my module to define more Javascript properties as children of the Javascript Object (or constructor function, in the case of classes) this simple code would then allow me to do this: // Push myNewTreeNode into the first child position // of our tree parent treeParent = Getattr(n, "mytree:bookmark"); nextSibling = Getattr(treeParent, "mytree:firstChild"); Setattr(treeParent, "mytree:firstChild", myNewTreeNode); Setattr(myNewTreeNode, "mytree:nextSibling", nextSibling); The output of this tree structure might look something like this: TopLevel - Namespace1 -- ChildOfNamespace1 -- ChildOfNamespace2 - Class1 -- constructorFunctionForClass1 -- staticMemberVariableForClass1 -- staticMemberFunctionForClass1 -- Class1_2 // <-- a class that is also a member of Class 1 etc. etc. Some of this is easy to do differently than I'm doing, but some of it is impossible without this sort of programming. ANY advice that can be provided would be extremely appreciated, but I'm really hoping someone will say "Oh yes, here is the mechanism for SWIG Node attribute inheritance..." Thanks in advance :) -- http://codebad.com/ |
From: William S F. <ws...@fu...> - 2010-03-07 17:59:09
|
Donny Viszneki wrote: > Hi all. > > So I've noticed a common programming pattern in other SWIG modules. > Here's some pseudo-code: > > class MyLanguage : public Language { > bool specialMode; > int processSomeNode(Node* n){ > if (doWeNeedSpecialMode(n)) > specialMode = true; > Language::processSomeNode(n); > specialMode = false; > } > }; > > In English, what this pattern attempts to accomplish is to pass down a > notional attribute to nodes nested in some node that contains the > clues for special processing. > > The pattern I expected to be available to me is that some attributes > could simply be inherited from the nodes that contained them. The > obvious case for an attribute that should be inherited by a node's > children is what its parents are, but I can imagine others. > > My use case: > > In Javascript as in many other scripting languages, "Objects" (or > hashes, or tables; whatever you want to call them) are the single > unified organizational paradigm for the language. OOP classes in > Javascript are more or less (a bit less, actually) accomplished using > Objects. Javascript's analog to a C++ namespace is an Object. > Functions in Javascript can have properties (attributes) associated on > them *just* like Objects, and so Javascript's analog to static class > methods are (more or less) Objects. > > Perhaps I'm saying "Objects" too much, when what I really mean is that > everything fits into a very natural hierarchical organization. Here is > some early code from my SWIG module to further demonstrate what I > mean, in pseudo-code form for clarity (to avoid confusion, you should > know that "node" here is a "ModuleTree" element, not a SWIG Node, but > they're conceptually similar): > > RegisterModuleTree(ModuleTree *node, JSObject *parent) { > do { > switch (node->type) > { > case TYPE_PRIMITIVE: > RegisterPrimitive(node, parent); > break; > case TYPE_NAMESPACE > JSObject *newNamespaceObject = RegisterNewObject(node, parent); > if (node->hasChildren) > RegisterModuleTree(node->firstChild, newNamespaceObject); > break; > /* other types... */ > } > } while (NULL != (node = node->nextSibling)); > } > > So you can see in my wrapper code produced by SWIG, the initialization > code walks through a hierarchical tree and begins defining variables > and entry points for the interpreter. Emitting code to define a tree > structure unsurprisingly necessitates building that tree structure (or > something similar to it) in my SWIG module. I thought this would be > straightforward, but I couldn't find any inheritance mechanisms, or a > "parent" link for SWIG Nodes that I could use to walk up a Node tree > and infer what attributes my Node should be inheriting. > I think this is easily solved via a call to parentNode(n). Be aware that the parent node is not always of the same type, for example when a method is wrapped using %extend, it is different to when a normal class method is wrapped. You can view this with the swig -debug-top n option or by adding Swig_print_node(n) into the code somewhere. > The need for SWIG Node attribute inheritance is so that I can avoid an > annoying "push and pop" pattern of programming that is used in many > other SWIG modules (no insult to any SWIG module programmers! you guys > are great!:) > > So I thought I would just be able to do something like this: > > Setattr(n, "mytree:bookmark", treeParent); > > If I had a way of achieving inheritance, then in namespaceWrapper() or > classWrapper() or any other wrapper that will require my module to > define more Javascript properties as children of the Javascript Object > (or constructor function, in the case of classes) this simple code > would then allow me to do this: > > // Push myNewTreeNode into the first child position > // of our tree parent > treeParent = Getattr(n, "mytree:bookmark"); > nextSibling = Getattr(treeParent, "mytree:firstChild"); > Setattr(treeParent, "mytree:firstChild", myNewTreeNode); > Setattr(myNewTreeNode, "mytree:nextSibling", nextSibling); > > The output of this tree structure might look something like this: > > TopLevel > - Namespace1 > -- ChildOfNamespace1 > -- ChildOfNamespace2 > - Class1 > -- constructorFunctionForClass1 > -- staticMemberVariableForClass1 > -- staticMemberFunctionForClass1 > -- Class1_2 // <-- a class that is also a member of Class 1 > etc. etc. > > Some of this is easy to do differently than I'm doing, but some of it > is impossible without this sort of programming. > > ANY advice that can be provided would be extremely appreciated, but > I'm really hoping someone will say "Oh yes, here is the mechanism for > SWIG Node attribute inheritance..." > > Thanks in advance :) > Hopefully my answer above helps?? William |
From: Donny V. <don...@gm...> - 2010-03-11 10:21:50
|
Ah parentNode()! That's exactly what I was looking for. Next order of business: Because I am attempting to support unflattened namespaces, it would be really helpful if cdecl Node instances would have an attribute referencing their namespace. Perhaps for the most correct behavior, SWIG would later have to instantiate and process more Node instances representing the different aliases which result from statements like: namespace foo { void bar(void); } namespace baz = foo; For this we'd need a cdecl Node for foo::bar(), and then some other node perhaps a "cdecl-alias" that linked back to the "primordial node" representing the right cdecl. In this case perhaps you'd get a primordial "bar()" cdecl for with a new "namespace" attribute describing the "foo" namespace, and then later a "bar()" cdecl-alias with a "primordial" attribute referencing the original "bar()" cdecl node, but with a new "namespace" attribute referencing a node describing the baz namespace. For something like "namespace baz = foo" the quickest solution might be a "namespace-alias" Node, but the cdecl-alias/primordial technique in the above paragraph also covers declarations like "namespace baz { using foo::bar; }" One SWIG behavior I think I don't like is that I notice namespaces are generating getters and setters right now. My plan for wrapping namespaces in my module does not include injecting intermediate getters for each statement like "mymodule.namespace.func(1,2,3)" nor to allow statements like "mymodule.namespace1 = mymodule.namespace2". Statements like "mymodule.namespace = whatever" would either be disallowed or would simply be handled by the Javascript interpreter by (for "mymodule.namespace = whatever") setting the "namespace" property of the object referenced by "mymodule" to be a reference to the Javascript object "whatever" (or whatever other value "whatever" might be including numbers, strings, or functions.) The Javascript interpreter is already well suited to this task, as namespaces and the place where static class member functions live are simply going to be Javascript objects or Javascript functions, both of which can have arbitrary properties assigned to them. In fact my way of wrapping both namespace members as well as static class members is going to be identical, and so certainly be invoke the same wrappering code. Thanks again for taking the time to read my emails On Sun, Mar 7, 2010 at 12:33 PM, William S Fulton <ws...@fu...> wrote: > Donny Viszneki wrote: >> >> Hi all. >> >> So I've noticed a common programming pattern in other SWIG modules. >> Here's some pseudo-code: >> >> class MyLanguage : public Language { >> bool specialMode; >> int processSomeNode(Node* n){ >> if (doWeNeedSpecialMode(n)) >> specialMode = true; >> Language::processSomeNode(n); >> specialMode = false; >> } >> }; >> >> In English, what this pattern attempts to accomplish is to pass down a >> notional attribute to nodes nested in some node that contains the >> clues for special processing. >> >> The pattern I expected to be available to me is that some attributes >> could simply be inherited from the nodes that contained them. The >> obvious case for an attribute that should be inherited by a node's >> children is what its parents are, but I can imagine others. >> >> My use case: >> >> In Javascript as in many other scripting languages, "Objects" (or >> hashes, or tables; whatever you want to call them) are the single >> unified organizational paradigm for the language. OOP classes in >> Javascript are more or less (a bit less, actually) accomplished using >> Objects. Javascript's analog to a C++ namespace is an Object. >> Functions in Javascript can have properties (attributes) associated on >> them *just* like Objects, and so Javascript's analog to static class >> methods are (more or less) Objects. >> >> Perhaps I'm saying "Objects" too much, when what I really mean is that >> everything fits into a very natural hierarchical organization. Here is >> some early code from my SWIG module to further demonstrate what I >> mean, in pseudo-code form for clarity (to avoid confusion, you should >> know that "node" here is a "ModuleTree" element, not a SWIG Node, but >> they're conceptually similar): >> >> RegisterModuleTree(ModuleTree *node, JSObject *parent) { >> do { >> switch (node->type) >> { >> case TYPE_PRIMITIVE: >> RegisterPrimitive(node, parent); >> break; >> case TYPE_NAMESPACE >> JSObject *newNamespaceObject = RegisterNewObject(node, parent); >> if (node->hasChildren) >> RegisterModuleTree(node->firstChild, newNamespaceObject); >> break; >> /* other types... */ >> } >> } while (NULL != (node = node->nextSibling)); >> } >> >> So you can see in my wrapper code produced by SWIG, the initialization >> code walks through a hierarchical tree and begins defining variables >> and entry points for the interpreter. Emitting code to define a tree >> structure unsurprisingly necessitates building that tree structure (or >> something similar to it) in my SWIG module. I thought this would be >> straightforward, but I couldn't find any inheritance mechanisms, or a >> "parent" link for SWIG Nodes that I could use to walk up a Node tree >> and infer what attributes my Node should be inheriting. >> > I think this is easily solved via a call to parentNode(n). Be aware that the > parent node is not always of the same type, for example when a method is > wrapped using %extend, it is different to when a normal class method is > wrapped. You can view this with the swig -debug-top n option or by adding > Swig_print_node(n) into the code somewhere. > >> The need for SWIG Node attribute inheritance is so that I can avoid an >> annoying "push and pop" pattern of programming that is used in many >> other SWIG modules (no insult to any SWIG module programmers! you guys >> are great!:) >> >> So I thought I would just be able to do something like this: >> >> Setattr(n, "mytree:bookmark", treeParent); >> >> If I had a way of achieving inheritance, then in namespaceWrapper() or >> classWrapper() or any other wrapper that will require my module to >> define more Javascript properties as children of the Javascript Object >> (or constructor function, in the case of classes) this simple code >> would then allow me to do this: >> >> // Push myNewTreeNode into the first child position >> // of our tree parent >> treeParent = Getattr(n, "mytree:bookmark"); >> nextSibling = Getattr(treeParent, "mytree:firstChild"); >> Setattr(treeParent, "mytree:firstChild", myNewTreeNode); >> Setattr(myNewTreeNode, "mytree:nextSibling", nextSibling); >> >> The output of this tree structure might look something like this: >> >> TopLevel >> - Namespace1 >> -- ChildOfNamespace1 >> -- ChildOfNamespace2 >> - Class1 >> -- constructorFunctionForClass1 >> -- staticMemberVariableForClass1 >> -- staticMemberFunctionForClass1 >> -- Class1_2 // <-- a class that is also a member of Class 1 >> etc. etc. >> >> Some of this is easy to do differently than I'm doing, but some of it >> is impossible without this sort of programming. >> >> ANY advice that can be provided would be extremely appreciated, but >> I'm really hoping someone will say "Oh yes, here is the mechanism for >> SWIG Node attribute inheritance..." >> >> Thanks in advance :) >> > Hopefully my answer above helps?? > > William > -- http://codebad.com/ |
From: William S F. <ws...@fu...> - 2010-03-15 20:23:51
|
Donny Are you following the svn commits? If so you'd have noticed some limited support for non-flattened namespaces via the nspace feature. So currently only enums, classes, unions and structs can exist in a namespace. Of notable absence are variables and functions declared in a namespace. In your target language, you can always get the current namespace via a call to Language::getNSpace(). The namespace returned is a language specific namespace and currently for C# and Java (only supported languages), it uses "." as the namespace/package separator. I suspect many languages will just use the ".", but when one comes along that does not, we can easily make this configurable for the core code. On a more strategic level, I suggest you forget about flattening the namespaces until you can support all of SWIG's other features. One of SWIG's strengths are the number of languages it supports and a degree of consistency amongst the wrappers. I'm not likely to accept any namespace changes that don't build on the nspace feature, so please demonstrate this working plus all the other SWIG features before modifying the nspace support. Walking before running is strongly advised! More comments inline. Donny Viszneki wrote: > Ah parentNode()! That's exactly what I was looking for. > > Next order of business: > > Because I am attempting to support unflattened namespaces, it would be > really helpful if cdecl Node instances would have an attribute > referencing their namespace. Perhaps for the most correct behavior, > SWIG would later have to instantiate and process more Node instances > representing the different aliases which result from statements like: > > namespace foo { > void bar(void); > } > namespace baz = foo; > Why are you concerned with this. All the namespaces are handled within the core code. Is there some symbol table problem we should know about? > For this we'd need a cdecl Node for foo::bar(), and then some other > node perhaps a "cdecl-alias" that linked back to the "primordial node" > representing the right cdecl. In this case perhaps you'd get a > primordial "bar()" cdecl for with a new "namespace" attribute > describing the "foo" namespace, and then later a "bar()" cdecl-alias > with a "primordial" attribute referencing the original "bar()" cdecl > node, but with a new "namespace" attribute referencing a node > describing the baz namespace. > > For something like "namespace baz = foo" the quickest solution might > be a "namespace-alias" Node, but the cdecl-alias/primordial technique > in the above paragraph also covers declarations like "namespace baz { > using foo::bar; }" > I think the wrappers should always use a fully qualified type in the target language and each wrapped type can only exist in one namespace. Given that, why do you need to be concerned with namespace aliases? Surely it is just something for the parser to deal with? I believe it does this all okay. > One SWIG behavior I think I don't like is that I notice namespaces are > generating getters and setters right now. My plan for wrapping > namespaces in my module does not include injecting intermediate > getters for each statement like "mymodule.namespace.func(1,2,3)" nor > to allow statements like "mymodule.namespace1 = mymodule.namespace2". > Statements like "mymodule.namespace = whatever" would either be > disallowed or would simply be handled by the Javascript interpreter by > (for "mymodule.namespace = whatever") Again, you really don't want to be getting into this nightmare generating this kind of code. Just generate the fully qualified types. > setting the "namespace" property > of the object referenced by "mymodule" to be a reference to the > Javascript object "whatever" (or whatever other value "whatever" might > be including numbers, strings, or functions.) The Javascript > interpreter is already well suited to this task, as namespaces and the > place where static class member functions live are simply going to be > Javascript objects or Javascript functions, both of which can have > arbitrary properties assigned to them. In fact my way of wrapping both > namespace members as well as static class members is going to be > identical, and so certainly be invoke the same wrappering code. > > Thanks again for taking the time to read my emails > William > On Sun, Mar 7, 2010 at 12:33 PM, William S Fulton > <ws...@fu...> wrote: >> Donny Viszneki wrote: >>> Hi all. >>> >>> So I've noticed a common programming pattern in other SWIG modules. >>> Here's some pseudo-code: >>> >>> class MyLanguage : public Language { >>> bool specialMode; >>> int processSomeNode(Node* n){ >>> if (doWeNeedSpecialMode(n)) >>> specialMode = true; >>> Language::processSomeNode(n); >>> specialMode = false; >>> } >>> }; >>> >>> In English, what this pattern attempts to accomplish is to pass down a >>> notional attribute to nodes nested in some node that contains the >>> clues for special processing. >>> >>> The pattern I expected to be available to me is that some attributes >>> could simply be inherited from the nodes that contained them. The >>> obvious case for an attribute that should be inherited by a node's >>> children is what its parents are, but I can imagine others. >>> >>> My use case: >>> >>> In Javascript as in many other scripting languages, "Objects" (or >>> hashes, or tables; whatever you want to call them) are the single >>> unified organizational paradigm for the language. OOP classes in >>> Javascript are more or less (a bit less, actually) accomplished using >>> Objects. Javascript's analog to a C++ namespace is an Object. >>> Functions in Javascript can have properties (attributes) associated on >>> them *just* like Objects, and so Javascript's analog to static class >>> methods are (more or less) Objects. >>> >>> Perhaps I'm saying "Objects" too much, when what I really mean is that >>> everything fits into a very natural hierarchical organization. Here is >>> some early code from my SWIG module to further demonstrate what I >>> mean, in pseudo-code form for clarity (to avoid confusion, you should >>> know that "node" here is a "ModuleTree" element, not a SWIG Node, but >>> they're conceptually similar): >>> >>> RegisterModuleTree(ModuleTree *node, JSObject *parent) { >>> do { >>> switch (node->type) >>> { >>> case TYPE_PRIMITIVE: >>> RegisterPrimitive(node, parent); >>> break; >>> case TYPE_NAMESPACE >>> JSObject *newNamespaceObject = RegisterNewObject(node, parent); >>> if (node->hasChildren) >>> RegisterModuleTree(node->firstChild, newNamespaceObject); >>> break; >>> /* other types... */ >>> } >>> } while (NULL != (node = node->nextSibling)); >>> } >>> >>> So you can see in my wrapper code produced by SWIG, the initialization >>> code walks through a hierarchical tree and begins defining variables >>> and entry points for the interpreter. Emitting code to define a tree >>> structure unsurprisingly necessitates building that tree structure (or >>> something similar to it) in my SWIG module. I thought this would be >>> straightforward, but I couldn't find any inheritance mechanisms, or a >>> "parent" link for SWIG Nodes that I could use to walk up a Node tree >>> and infer what attributes my Node should be inheriting. >>> >> I think this is easily solved via a call to parentNode(n). Be aware that the >> parent node is not always of the same type, for example when a method is >> wrapped using %extend, it is different to when a normal class method is >> wrapped. You can view this with the swig -debug-top n option or by adding >> Swig_print_node(n) into the code somewhere. >> >>> The need for SWIG Node attribute inheritance is so that I can avoid an >>> annoying "push and pop" pattern of programming that is used in many >>> other SWIG modules (no insult to any SWIG module programmers! you guys >>> are great!:) >>> >>> So I thought I would just be able to do something like this: >>> >>> Setattr(n, "mytree:bookmark", treeParent); >>> >>> If I had a way of achieving inheritance, then in namespaceWrapper() or >>> classWrapper() or any other wrapper that will require my module to >>> define more Javascript properties as children of the Javascript Object >>> (or constructor function, in the case of classes) this simple code >>> would then allow me to do this: >>> >>> // Push myNewTreeNode into the first child position >>> // of our tree parent >>> treeParent = Getattr(n, "mytree:bookmark"); >>> nextSibling = Getattr(treeParent, "mytree:firstChild"); >>> Setattr(treeParent, "mytree:firstChild", myNewTreeNode); >>> Setattr(myNewTreeNode, "mytree:nextSibling", nextSibling); >>> >>> The output of this tree structure might look something like this: >>> >>> TopLevel >>> - Namespace1 >>> -- ChildOfNamespace1 >>> -- ChildOfNamespace2 >>> - Class1 >>> -- constructorFunctionForClass1 >>> -- staticMemberVariableForClass1 >>> -- staticMemberFunctionForClass1 >>> -- Class1_2 // <-- a class that is also a member of Class 1 >>> etc. etc. >>> >>> Some of this is easy to do differently than I'm doing, but some of it >>> is impossible without this sort of programming. >>> >>> ANY advice that can be provided would be extremely appreciated, but >>> I'm really hoping someone will say "Oh yes, here is the mechanism for >>> SWIG Node attribute inheritance..." >>> >>> Thanks in advance :) >>> >> Hopefully my answer above helps?? >> >> William >> > > |
From: Donny V. <don...@gm...> - 2010-03-16 02:56:27
|
On Mon, Mar 15, 2010 at 4:01 PM, William S Fulton <ws...@fu...> wrote: > Are you following the svn commits? If so you'd have noticed some limited > support for non-flattened namespaces via the nspace feature. So currently > only enums, classes, unions and structs can exist in a namespace. Of notable > absence are variables and functions declared in a namespace. No, not recently, but now I'll be sure to check it out > In your target language, you can always get the current namespace via a call > to Language::getNSpace(). The namespace returned is a language specific > namespace and currently for C# and Java (only supported languages), it uses > "." as the namespace/package separator. I suspect many languages will just > use the ".", but when one comes along that does not, we can easily make this > configurable for the core code. I find observations about the "." to be superficial and slightly irrelevant. Usability is important, so those things must be considered, however when I think about how my SWIG module should work, I mostly think about it in terms of the primitives that must work with for my target language/platform. In Javascript, the "dot operator" is the "property of" operator, and the value of an expression like "foo.bar" is a value that can be assigned (unless an exception is thrown) to any other variable, so I think much more of the object that is represented than "foo.bar" than I do of the expression "foo.bar." In practice, though, I doubt C++ statements like "namespace foo = bar" are *ever* used in the kind of code that is going to be fed to SWIG, so perhaps this should be a lower priority for me. I went after namespaces very early on for two reasons. First, because "modules" are an idea being developed for the Javascript community by the CommonJS group, and those are a lot like namespaces. Secondly because what Java and C++ call a static member function are also a very common programming idiom in Javascript, and I knew these had to be implemented in the same way that namespaces would be. > On a more strategic level, I suggest you forget about flattening the > namespaces until you can support all of SWIG's other features. One of SWIG's > strengths are the number of languages it supports and a degree of > consistency amongst the wrappers. I'm not likely to accept any namespace > changes that don't build on the nspace feature, so please demonstrate this > working plus all the other SWIG features before modifying the nspace > support. Walking before running is strongly advised! I apologize if I was unclear, I do not want to flatten namespaces. > Donny Viszneki wrote: >> Because I am attempting to support unflattened namespaces, it would be >> really helpful if cdecl Node instances would have an attribute >> referencing their namespace. Perhaps for the most correct behavior, >> SWIG would later have to instantiate and process more Node instances >> representing the different aliases which result from statements like: >> >> namespace foo { >> void bar(void); >> } >> namespace baz = foo; >> > Why are you concerned with this. All the namespaces are handled within the > core code. Is there some symbol table problem we should know about? I'm not really sure what kind of symbol table problem could have lead me in this direction. For clarity as I mentioned above, it is probably a very uncommon practice to feed SWIG code like "namespace foo = bar". >> For this we'd need a cdecl Node for foo::bar(), and then some other >> node perhaps a "cdecl-alias" that linked back to the "primordial node" >> representing the right cdecl. In this case perhaps you'd get a >> primordial "bar()" cdecl for with a new "namespace" attribute >> describing the "foo" namespace, and then later a "bar()" cdecl-alias >> with a "primordial" attribute referencing the original "bar()" cdecl >> node, but with a new "namespace" attribute referencing a node >> describing the baz namespace. >> >> For something like "namespace baz = foo" the quickest solution might >> be a "namespace-alias" Node, but the cdecl-alias/primordial technique >> in the above paragraph also covers declarations like "namespace baz { >> using foo::bar; }" >> > I think the wrappers should always use a fully qualified type in the target > language and each wrapped type can only exist in one namespace. Given that, > why do you need to be concerned with namespace aliases? Surely it is just > something for the parser to deal with? I believe it does this all okay. I'm not sure what a "fully qualified type" would be in my target language, Javascript. Did you mean that I should be satisfied with the namespace getters and setters? For me, a getter or a setter means bypassing Spidermonkey's built-in mechanisms for accomplishing what basically amounts to "getNamespaceFoo(){return namespaceFoo}" Why I would be concerned with namespace aliases is to achieve referential identity between two members of namespaces that are aliased to the same namespace. For instance for the following C++ code: namespace Foo { int add(int a, int b); } namespace Bar = Foo; The Javascript expression "Foo.add == Foo.bar" should be true. >> One SWIG behavior I think I don't like is that I notice namespaces are >> generating getters and setters right now. My plan for wrapping >> namespaces in my module does not include injecting intermediate >> getters for each statement like "mymodule.namespace.func(1,2,3)" nor >> to allow statements like "mymodule.namespace1 = mymodule.namespace2". >> Statements like "mymodule.namespace = whatever" would either be >> disallowed or would simply be handled by the Javascript interpreter by >> (for "mymodule.namespace = whatever") > > Again, you really don't want to be getting into this nightmare generating > this kind of code. Just generate the fully qualified types. Sorry for being unclear, I want to write *less* code, and allow the Javascript interpreter to provide consistent and predictable semantics to the Javascript programmer. I don't want or need getters or setters for namespaces, as namespaces will be represented in my target platform as Javascript Objects, which are a lot like Hash tables with special hooks, and once I have instantiated them, attached properties to them, and then attached them as properties of other objects to they can be reached by the programmer, I want to be done with them. No more SWIG wrapper code need intervene once it is all set up at module initialization time. Thanks again for all of your feedback, and keeping me up to date on the latest SWIG changes upstream! -- http://codebad.com/ |
From: William S F. <ws...@fu...> - 2010-03-18 19:26:30
|
Donny Viszneki wrote: > On Mon, Mar 15, 2010 at 4:01 PM, William S Fulton > <ws...@fu...> wrote: > > Are you following the svn commits? If so you'd have noticed some limited > > support for non-flattened namespaces via the nspace feature. So > currently > > only enums, classes, unions and structs can exist in a namespace. Of > notable > > absence are variables and functions declared in a namespace. > > No, not recently, but now I'll be sure to check it out > > > In your target language, you can always get the current namespace > via a call > > to Language::getNSpace(). The namespace returned is a language specific > > namespace and currently for C# and Java (only supported languages), > it uses > > "." as the namespace/package separator. I suspect many languages > will just > > use the ".", but when one comes along that does not, we can easily > make this > > configurable for the core code. > > I find observations about the "." to be superficial and slightly > irrelevant. Usability is important, so those things must be > considered, however when I think about how my SWIG module should work, > I mostly think about it in terms of the primitives that must work with > for my target language/platform. In Javascript, the "dot operator" is > the "property of" operator, and the value of an expression like > "foo.bar" is a value that can be assigned (unless an exception is > thrown) to any other variable, so I think much more of the object that > is represented than "foo.bar" than I do of the expression "foo.bar." > > In practice, though, I doubt C++ statements like "namespace foo = bar" > are *ever* used in the kind of code that is going to be fed to SWIG, > so perhaps this should be a lower priority for me. I went after > namespaces very early on for two reasons. First, because "modules" are > an idea being developed for the Javascript community by the CommonJS > group, and those are a lot like namespaces. Secondly because what Java > and C++ call a static member function are also a very common > programming idiom in Javascript, and I knew these had to be > implemented in the same way that namespaces would be. > > > On a more strategic level, I suggest you forget about flattening the > > namespaces until you can support all of SWIG's other features. One > of SWIG's > > strengths are the number of languages it supports and a degree of > > consistency amongst the wrappers. I'm not likely to accept any namespace > > changes that don't build on the nspace feature, so please > demonstrate this > > working plus all the other SWIG features before modifying the nspace > > support. Walking before running is strongly advised! > > I apologize if I was unclear, I do not want to flatten namespaces. > > > Donny Viszneki wrote: > >> Because I am attempting to support unflattened namespaces, it would be > >> really helpful if cdecl Node instances would have an attribute > >> referencing their namespace. Perhaps for the most correct behavior, > >> SWIG would later have to instantiate and process more Node instances > >> representing the different aliases which result from statements like: > >> > >> namespace foo { > >> void bar(void); > >> } > >> namespace baz = foo; > >> > > Why are you concerned with this. All the namespaces are handled > within the > > core code. Is there some symbol table problem we should know about? > > I'm not really sure what kind of symbol table problem could have lead > me in this direction. For clarity as I mentioned above, it is probably > a very uncommon practice to feed SWIG code like "namespace foo = bar". > > >> For this we'd need a cdecl Node for foo::bar(), and then some other > >> node perhaps a "cdecl-alias" that linked back to the "primordial node" > >> representing the right cdecl. In this case perhaps you'd get a > >> primordial "bar()" cdecl for with a new "namespace" attribute > >> describing the "foo" namespace, and then later a "bar()" cdecl-alias > >> with a "primordial" attribute referencing the original "bar()" cdecl > >> node, but with a new "namespace" attribute referencing a node > >> describing the baz namespace. > >> > >> For something like "namespace baz = foo" the quickest solution might > >> be a "namespace-alias" Node, but the cdecl-alias/primordial technique > >> in the above paragraph also covers declarations like "namespace baz { > >> using foo::bar; }" > >> > > I think the wrappers should always use a fully qualified type in the > target > > language and each wrapped type can only exist in one namespace. > Given that, > > why do you need to be concerned with namespace aliases? Surely it is > just > > something for the parser to deal with? I believe it does this all okay. > > I'm not sure what a "fully qualified type" would be in my target > language, Javascript. I was hoping you'd be able to answer that! Given: %feature("nspace"); namespace A { struct S {}; } namespace B { struct S {}; } In Java the fully qualified names are A.S and B.S and an instance of each is constructed like: A.S a = new A.S(); B.S b = new B.S(); How would you do the equivalent in with your Javascript proxy classes? That should answer the question on fully qualified types. > Did you mean that I should be satisfied with the > namespace getters and setters? For me, a getter or a setter means > bypassing Spidermonkey's built-in mechanisms for accomplishing what > basically amounts to "getNamespaceFoo(){return namespaceFoo}" > > Why I would be concerned with namespace aliases is to achieve > referential identity between two members of namespaces that are > aliased to the same namespace. For instance for the following C++ > code: > > namespace Foo { > int add(int a, int b); > } > namespace Bar = Foo; > > The Javascript expression "Foo.add == Foo.bar" should be true. > No! This particular concept of having namespace aliases just has never been considered before because SWIG flattens the namespaces. However, given that the nspace feature is working and it only support classes, structs, unions, enums and does not support variables and functions like add above, consider a case which works, wrapping a class: namespace Foo { struct S { void subtract(int a, int b); }; } namespace Bar = Foo; void thing(Bar::S s) {} Just Foo.S.subtract() is available in the target language, there is no Bar.S.subtract(). The namespace aliases are handled in the SWIG type system correctly, but they are effectively ignored, and you have to pass Foo.S to thing(). This is no different to SWIG's treatment of typedef. If there are a million typedefs to Foo::S, only one proxy class S is available in the target language. The same is and should remain so for namespace aliases, after all, they are just mega typedefs. I really don't see a need to change this behaviour. Referential identity would not be an issue because there is just one type for S in the target language. > >> One SWIG behavior I think I don't like is that I notice namespaces are > >> generating getters and setters right now. My plan for wrapping > >> namespaces in my module does not include injecting intermediate > >> getters for each statement like "mymodule.namespace.func(1,2,3)" nor > >> to allow statements like "mymodule.namespace1 = mymodule.namespace2". > >> Statements like "mymodule.namespace = whatever" would either be > >> disallowed or would simply be handled by the Javascript interpreter by > >> (for "mymodule.namespace = whatever") > > Again, you really don't want to be getting into this nightmare > generating > > this kind of code. Just generate the fully qualified types. > > Sorry for being unclear, I want to write *less* code, and allow the > Javascript interpreter to provide consistent and predictable semantics > to the Javascript programmer. I don't want or need getters or setters > for namespaces What do you mean by this? You can't write a 'getter' (as in a function) to get a namespace in C++. > , as namespaces will be represented in my target > platform as Javascript Objects, which are a lot like Hash tables with > special hooks, and once I have instantiated them, attached properties > to them, and then attached them as properties of other objects to they > can be reached by the programmer, I want to be done with them. No more > SWIG wrapper code need intervene once it is all set up at module > initialization time. In order to fully support namespaces by mapping them to Objects, you will need to add function and variables support to the nspace feature. Unfortunately this also means you need to ensure this works for the languages that support it at the moment ... Java and C#. Really, I would leave this to a later stage once you have got all the basics working in a flattened namespace. The majority of SWIG users are content with flattened namespaces and I suspect the same for Javascript users. William |
From: Donny V. <don...@gm...> - 2010-03-11 10:45:12
|
More follow-up: Are const static class members supported? These two declarations are giving me a syntax error during SWIG processing: class Foo { const static int Bar = 666; }; and: class Foo { const static int Bar; }; const int Foo::Bar = 666; I think ideally the semantics for static class members are the same for namespace members. On Thu, Mar 11, 2010 at 5:21 AM, Donny Viszneki <don...@gm...> wrote: > Ah parentNode()! That's exactly what I was looking for. > > Next order of business: > > Because I am attempting to support unflattened namespaces, it would be > really helpful if cdecl Node instances would have an attribute > referencing their namespace. Perhaps for the most correct behavior, > SWIG would later have to instantiate and process more Node instances > representing the different aliases which result from statements like: > > namespace foo { > void bar(void); > } > namespace baz = foo; > > For this we'd need a cdecl Node for foo::bar(), and then some other > node perhaps a "cdecl-alias" that linked back to the "primordial node" > representing the right cdecl. In this case perhaps you'd get a > primordial "bar()" cdecl for with a new "namespace" attribute > describing the "foo" namespace, and then later a "bar()" cdecl-alias > with a "primordial" attribute referencing the original "bar()" cdecl > node, but with a new "namespace" attribute referencing a node > describing the baz namespace. > > For something like "namespace baz = foo" the quickest solution might > be a "namespace-alias" Node, but the cdecl-alias/primordial technique > in the above paragraph also covers declarations like "namespace baz { > using foo::bar; }" > > One SWIG behavior I think I don't like is that I notice namespaces are > generating getters and setters right now. My plan for wrapping > namespaces in my module does not include injecting intermediate > getters for each statement like "mymodule.namespace.func(1,2,3)" nor > to allow statements like "mymodule.namespace1 = mymodule.namespace2". > Statements like "mymodule.namespace = whatever" would either be > disallowed or would simply be handled by the Javascript interpreter by > (for "mymodule.namespace = whatever") setting the "namespace" property > of the object referenced by "mymodule" to be a reference to the > Javascript object "whatever" (or whatever other value "whatever" might > be including numbers, strings, or functions.) The Javascript > interpreter is already well suited to this task, as namespaces and the > place where static class member functions live are simply going to be > Javascript objects or Javascript functions, both of which can have > arbitrary properties assigned to them. In fact my way of wrapping both > namespace members as well as static class members is going to be > identical, and so certainly be invoke the same wrappering code. > > Thanks again for taking the time to read my emails > > On Sun, Mar 7, 2010 at 12:33 PM, William S Fulton > <ws...@fu...> wrote: >> Donny Viszneki wrote: >>> >>> Hi all. >>> >>> So I've noticed a common programming pattern in other SWIG modules. >>> Here's some pseudo-code: >>> >>> class MyLanguage : public Language { >>> bool specialMode; >>> int processSomeNode(Node* n){ >>> if (doWeNeedSpecialMode(n)) >>> specialMode = true; >>> Language::processSomeNode(n); >>> specialMode = false; >>> } >>> }; >>> >>> In English, what this pattern attempts to accomplish is to pass down a >>> notional attribute to nodes nested in some node that contains the >>> clues for special processing. >>> >>> The pattern I expected to be available to me is that some attributes >>> could simply be inherited from the nodes that contained them. The >>> obvious case for an attribute that should be inherited by a node's >>> children is what its parents are, but I can imagine others. >>> >>> My use case: >>> >>> In Javascript as in many other scripting languages, "Objects" (or >>> hashes, or tables; whatever you want to call them) are the single >>> unified organizational paradigm for the language. OOP classes in >>> Javascript are more or less (a bit less, actually) accomplished using >>> Objects. Javascript's analog to a C++ namespace is an Object. >>> Functions in Javascript can have properties (attributes) associated on >>> them *just* like Objects, and so Javascript's analog to static class >>> methods are (more or less) Objects. >>> >>> Perhaps I'm saying "Objects" too much, when what I really mean is that >>> everything fits into a very natural hierarchical organization. Here is >>> some early code from my SWIG module to further demonstrate what I >>> mean, in pseudo-code form for clarity (to avoid confusion, you should >>> know that "node" here is a "ModuleTree" element, not a SWIG Node, but >>> they're conceptually similar): >>> >>> RegisterModuleTree(ModuleTree *node, JSObject *parent) { >>> do { >>> switch (node->type) >>> { >>> case TYPE_PRIMITIVE: >>> RegisterPrimitive(node, parent); >>> break; >>> case TYPE_NAMESPACE >>> JSObject *newNamespaceObject = RegisterNewObject(node, parent); >>> if (node->hasChildren) >>> RegisterModuleTree(node->firstChild, newNamespaceObject); >>> break; >>> /* other types... */ >>> } >>> } while (NULL != (node = node->nextSibling)); >>> } >>> >>> So you can see in my wrapper code produced by SWIG, the initialization >>> code walks through a hierarchical tree and begins defining variables >>> and entry points for the interpreter. Emitting code to define a tree >>> structure unsurprisingly necessitates building that tree structure (or >>> something similar to it) in my SWIG module. I thought this would be >>> straightforward, but I couldn't find any inheritance mechanisms, or a >>> "parent" link for SWIG Nodes that I could use to walk up a Node tree >>> and infer what attributes my Node should be inheriting. >>> >> I think this is easily solved via a call to parentNode(n). Be aware that the >> parent node is not always of the same type, for example when a method is >> wrapped using %extend, it is different to when a normal class method is >> wrapped. You can view this with the swig -debug-top n option or by adding >> Swig_print_node(n) into the code somewhere. >> >>> The need for SWIG Node attribute inheritance is so that I can avoid an >>> annoying "push and pop" pattern of programming that is used in many >>> other SWIG modules (no insult to any SWIG module programmers! you guys >>> are great!:) >>> >>> So I thought I would just be able to do something like this: >>> >>> Setattr(n, "mytree:bookmark", treeParent); >>> >>> If I had a way of achieving inheritance, then in namespaceWrapper() or >>> classWrapper() or any other wrapper that will require my module to >>> define more Javascript properties as children of the Javascript Object >>> (or constructor function, in the case of classes) this simple code >>> would then allow me to do this: >>> >>> // Push myNewTreeNode into the first child position >>> // of our tree parent >>> treeParent = Getattr(n, "mytree:bookmark"); >>> nextSibling = Getattr(treeParent, "mytree:firstChild"); >>> Setattr(treeParent, "mytree:firstChild", myNewTreeNode); >>> Setattr(myNewTreeNode, "mytree:nextSibling", nextSibling); >>> >>> The output of this tree structure might look something like this: >>> >>> TopLevel >>> - Namespace1 >>> -- ChildOfNamespace1 >>> -- ChildOfNamespace2 >>> - Class1 >>> -- constructorFunctionForClass1 >>> -- staticMemberVariableForClass1 >>> -- staticMemberFunctionForClass1 >>> -- Class1_2 // <-- a class that is also a member of Class 1 >>> etc. etc. >>> >>> Some of this is easy to do differently than I'm doing, but some of it >>> is impossible without this sort of programming. >>> >>> ANY advice that can be provided would be extremely appreciated, but >>> I'm really hoping someone will say "Oh yes, here is the mechanism for >>> SWIG Node attribute inheritance..." >>> >>> Thanks in advance :) >>> >> Hopefully my answer above helps?? >> >> William >> > > > -- > http://codebad.com/ > -- http://codebad.com/ |
From: Nitro <ni...@dr...> - 2010-03-11 11:30:41
|
Am 11.03.2010, 11:45 Uhr, schrieb Donny Viszneki <don...@gm...>: > More follow-up: > > Are const static class members supported? These two declarations are > giving me a syntax error during SWIG processing: > > class Foo { > const static int Bar = 666; > }; > > and: > > class Foo { > const static int Bar; > }; > const int Foo::Bar = 666; > > I think ideally the semantics for static class members are the same > for namespace members. See here: http://www.velocityreviews.com/forums/t291248-const-static-vs-static-const.html . -Matthias |
From: Donny V. <don...@gm...> - 2010-03-11 17:10:26
|
d'oh! thanks, i will get back to my swig code this evening and fix that... On Thu, Mar 11, 2010 at 6:17 AM, Nitro <ni...@dr...> wrote: > Am 11.03.2010, 11:45 Uhr, schrieb Donny Viszneki <don...@gm...>: > >> More follow-up: >> >> Are const static class members supported? These two declarations are >> giving me a syntax error during SWIG processing: >> >> class Foo { >> const static int Bar = 666; >> }; >> >> and: >> >> class Foo { >> const static int Bar; >> }; >> const int Foo::Bar = 666; >> >> I think ideally the semantics for static class members are the same >> for namespace members. > > See here: > http://www.velocityreviews.com/forums/t291248-const-static-vs-static-const.html > . > > -Matthias > -- http://codebad.com/ |