{"id":314,"date":"2011-04-29T14:17:58","date_gmt":"2011-04-29T22:17:58","guid":{"rendered":"http:\/\/www.wirfs-brock.com\/allen\/?p=314"},"modified":"2011-04-29T14:17:58","modified_gmt":"2011-04-29T22:17:58","slug":"combining-mirror-facets","status":"publish","type":"post","link":"https:\/\/wirfs-brock.com\/allen\/posts\/314","title":{"rendered":"Combining Mirror Facets"},"content":{"rendered":"<p><a href=\"http:\/\/www.wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets-300x225.png\" alt=\"\" title=\"mirrorfacets\" width=\"300\" height=\"225\" class=\"alignright size-medium wp-image-349\" srcset=\"https:\/\/wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets-300x225.png 300w, https:\/\/wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets-1024x768.png 1024w, https:\/\/wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets-1200x900-cropped.png 1200w, https:\/\/wirfs-brock.com\/allen\/wp-content\/uploads\/2011\/04\/mirrorfacets.png 1280w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>In my last couple posts I introduced idea of using <a title=\"Experimenting with Mirrors for JavaScript\" href=\"http:\/\/www.wirfs-brock.com\/allen\/posts\/228\" target=\"_self\">Mirrors for JavaScript reflection<\/a> and took a first look <a title=\"Looking into Mirrors\" href=\"http:\/\/www.wirfs-brock.com\/allen\/posts\/245\">at the introspection interfaces<\/a> of my <a title=\"jsmirrors on github\" href=\"https:\/\/github.com\/allenwb\/jsmirrors\" target=\"_blank\">jsmirrors<\/a> prototype.  In this post I&#8217;m going to look at the other reflection interfaces in jsmirrors and how they are mixed together to provide various levels of reflection privilege.<\/p>\n<p>When building this prototype I knew that I wanted to have a number of separable sets of reflection capabilities that I could mix and match in various ways.  I also knew that the implementation was likely to change several times as I experimented with the prototype. I wanted to make sure that as I evolved the implementation that I could keep track of what belonged in each separable piece.  The way I ultimately accomplished this was by maintaining a  file of interface definitions  that are separate from the actual code that implements <a title=\"jsmirrors on github\" href=\"https:\/\/github.com\/allenwb\/jsmirrors\" target=\"_blank\">jsmirrors<\/a>. The interface specifications are contained in the file <a title=\"mirrorsInterfaceSpec.js\" href=\"https:\/\/github.com\/allenwb\/jsmirrors\/blob\/master\/mirrorsInterfaceSpec.js\" target=\"_blank\">mirrorsInterfaceSpec.js<\/a>. I look at the interface file when I need to remind myself how to use one of the specific reflection interfaces and as a specification as I make changes to the implementaiton.  Also, whenever I perform a major refactoring of the implementation I check it against the interface specification.  Here is the interface specification of the basic object introspection interface that I  demonstrated in the  <a title=\"Looking into Mirrors\" href=\"http:\/\/www.wirfs-brock.com\/allen\/posts\/245\">Looking into Mirrors<\/a> post: <\/p>\n<pre class=\"brush: jscript; light: true; title: ; notranslate\" title=\"\">\r\n\/\/Mirror for introspect upon all objects\r\nvar objectMirrorInterface = extendsInterface(objectBasicMirrorInterface, {\r\n   prototype:  getAccess(objectMirrorInterface|null),\r\n     \/\/return a mirror on the reflected object's &#x5B;&#x5B;Prototype]]\r\n   extensible: getAccess(Boolean),\r\n     \/\/return true if the reflected object is extensible\r\n   ownProperties: getAccess(array(propertyMirrorInterface)),\r\n     \/\/return an array containing property mirrors\r\n     \/\/on the reflected object's own properties\r\n   ownPropertyNames: getAccess(array(String)),\r\n     \/\/return an array containing the string names\r\n     \/\/of the reflected object's own properties\r\n   keys: getAccess(array(String)),\r\n     \/\/return an array containing the string names of the\r\n     \/\/reflected object's enumerable own properties\r\n   enumerationOrder: getAccess(array(String)),\r\n     \/\/return an array containing the string names of the\r\n     \/\/reflected object's enumerable own and inherited properties\r\n   prop: method({name:String}, returns(propertyMirrorInterface|undefined)),\r\n     \/\/return a mirror on an own property\r\n   lookup: method({name:String},returns(propertyMirrorInterface|undefined)),\r\n     \/\/return mirror on the result of a property lookup. It may be inherited \r\n   has: method({name:String}, returns(Boolean)),\r\n     \/\/return true if the reflected object has a property named 'name'\r\n   hasOwn: method({name:String}, returns(Boolean)),\r\n     \/\/return true if the reflected object has an own property named 'name'\r\n   specialClass: getAccess(String)\r\n    \/\/return the value of the reflected object's &#x5B;&#x5B;Class]] internal property\r\n});\r\n<\/pre>\n<p>I used JavaScript object literals and a few helper functions to describe these interfaces.  Here is the definition of the helper functions used for this interface:<\/p>\n<pre class=\"brush: jscript; light: true; title: ; notranslate\" title=\"\">\r\nfunction getAccess(returnInterface) {}; \/\/a &quot;get-able&quot; property\r\nfunction method(arguments,returnInterface){}; \/\/ a method property\r\nfunction extendsInterface(supers,members) {};\/\/a interface adding to supers\r\nfunction returns(returnInterface) {};   \/\/return value of a method\r\nfunction array(elementInterface) {};\/\/array elements all support a interface\r\n<\/pre>\n<p>The JavaScript code of the interface definitions don&#8217;t actually do anything but I find that being able to parse the interface specification using JavaScript forces me to apply some useful structuring discipline that I might skip if I was just writing prose descriptions. Plus I think it is going to be quite useful to have these interface specifications in a form that is easily processed.  For example, now that I have an initial implementation of jsmirrors, I may use it to create a little tool that can reflect upon the objects created by the interface specifications and perform useful tasks.  For example I may generate unit test stubs for implementations of the interfaces. I may also use reflection over the interfaces to directly validate the completeness of my implementations.<\/p>\n<p>In factoring the jsmirrors functionality for reflecting upon objects I divided it to three primary interfaces.  <code>objectMirrorInterface<\/code>, shown above, is the basic introspection interface. <code>objectMutationMirrorInterface<\/code> allows changes to be made to a reflected object such as adding or removing properties or changing the object&#8217;s prototype. <code>objectEvalMirrorInterface<\/code> allows various forms of evaluation upon reflected objects such as doing &#8220;puts&#8221; and &#8220;gets&#8221; (which may invoke accessor property functions) to access property values of a reflected object or to invoke a method property.  There are also corresponding introspection, mutation, and evaluation interfaces for function object mirrors and also for property mirrors.<\/p>\n<p>In the actual implementation, these interfaces are combined in various ways to produce five different kinds of concrete mirrors on local objects.  These various kinds of mirrors are accessible via factory functions that are accessed as properties of the <code>Mirrors<\/code> module object.  The five  local object mirror factories are:<\/p>\n<ul>\n<li><code>Mirrors.introspect<\/code>  &#8211;  supports only introspection using <code>objectMirrorInterface<\/code>.<\/li>\n<li><code>Mirrors.evaluation<\/code>  &#8211; supports only  evaluation using <code>objectEvalMirrorInterface<\/code>.<\/li>\n<li><code>Mirrors.introspectEval<\/code>  &#8211;  supports introspection and evaluation using <code>objectMirrorInterface<\/code> and <code>objectEvalMirrorInterface<\/code>.<\/li>\n<li><code>Mirrors.mutate<\/code>  &#8211;  supports introspection and mutation using <code>objectMirrorInterface<\/code> and <code>objectMutationMirrorInterface<\/code>.<\/li>\n<li><code>Mirrors.fullLocal<\/code>  &#8211;  supports introspection, mutation, and evaluation using all three interfaces.<\/li>\n<\/ul>\n<p>I demonstrated the use of <code>Mirrors.introspect<\/code> is my previous  <a title=\"Looking into Mirrors\" href=\"http:\/\/www.wirfs-brock.com\/allen\/posts\/245\">post<\/a>.  The other <code>Mirror<\/code> factories are used in exactly the same manner and, except for <code>Mirrors.evaluation<\/code>, could be used to run all the same examples.  However, the other factories expose additional functionality that isn&#8217;t available using <code>Mirrors.introspect<\/code>. Take a look at the actual interface specification in <a title=\"mirrorsInterfaceSpec.js\" href=\"https:\/\/github.com\/allenwb\/jsmirrors\/blob\/master\/mirrorsInterfaceSpec.js\" target=\"_blank\">mirrorsInterfaceSpec.js<\/a> to see which capabilities are provided by the mirror objects produced by each of these factories.<\/p>\n<p>The reason for providing multiple mirror factories  is to demonstrate that by using mirror-based reflection we can decide exactly how much reflection capability we will make available to any specific client or tool. We might allow one tool to use the full range of reflective interfaces. For another we may only expose introspection or evaluation capabilities or perhaps introspection and mutation capabilities without the ability to actually do reflective evaluation. However, so far, I&#8217;ve only shown mirrors that know how to reflect upon local objects that exist in the same heap as the mirror objects.  In my next post I&#8217;ll look at how to use the same interfaces to reflect upon non-local objects that might be encoded in a file or exist in a remote environment.<\/p>\n<p>(<a href=\"http:\/\/www.flickr.com\/photos\/16782093@N03\/3951491170\/\" target=\"_blank\">Photo<\/a> by \u201cMetro Centric\u201d, Creative Commons Attribution License)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my last couple posts I introduced idea of using Mirrors for JavaScript reflection and took a first look at the introspection interfaces of my jsmirrors prototype. In this post I&#8217;m going to look at the other reflection interfaces in jsmirrors and how they are mixed together to provide various levels of reflection privilege. When [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,45],"tags":[32,43,60,13,41,42,40],"_links":{"self":[{"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/posts\/314"}],"collection":[{"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/comments?post=314"}],"version-history":[{"count":41,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/posts\/314\/revisions"}],"predecessor-version":[{"id":356,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/posts\/314\/revisions\/356"}],"wp:attachment":[{"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/media?parent=314"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/categories?post=314"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wirfs-brock.com\/allen\/wp-json\/wp\/v2\/tags?post=314"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}