Created
June 9, 2010 19:26
-
-
Save bmeck/432045 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var sys=require("sys"); | |
//and so the evil begins... | |
function Interface() { | |
//BE SURE TO UPDATE compile -> var a = ... | |
var $this={} | |
, _tags = {} | |
, _properties = {} | |
, _arguments = [] | |
//adds an argument, higher priority than a private variable | |
$this.addArgument=function(argumentName,position,defaultValue) { | |
if(!_arguments[position]) { | |
_arguments[position]={ | |
name:argumentName | |
,value:defaultValue | |
}; | |
} | |
else { | |
throw "argument already exists at that index" | |
} | |
} | |
$this.addProperty=function(propertyName,propertyDescriptor) { | |
_properties[propertyName]=propertyDescriptor; | |
} | |
$this.tagProperty=function(propertyName,tagName) { | |
if(tagName in _tags) { | |
_tags[tagName].push(propertyName); | |
} | |
else { | |
_tags[tagName]=[propertyName]; | |
} | |
} | |
$this.getTag=function(tagName) { | |
return _tags[tagName]; | |
} | |
//Generate a JS function for this Interface, loses native and closure based values | |
$this.compile=function( | |
excludeTags//dont include properties with these flags (dictionary) {flag:true} | |
,allowExtension/*can put on other objects/can use constructor (boolean) */ | |
,privateProperties/*closure based variables, hidden beyond this...should we return this? (dictionary) */ | |
) { | |
var a={ | |
//arguments is used as the this variable, sneak sneak | |
// {"this":x,"src":compileString} | |
"arguments":{src:""} | |
, a:undefined//dont let them just get a anyway... | |
//from compile | |
, excludTags:undefined | |
, allowExtensions:undefined | |
, privateProperties:undefined | |
//from Interface | |
, $this:undefined | |
, _tags:undefined | |
, _properties:undefined | |
, _arguments:undefined | |
, | |
} | |
{//scope our data dealing ways | |
var compilingProperties={}; | |
for(var propertyName in _properties) { | |
var valid=true; | |
for(var exclude in excludeTags) { | |
if(exclude in _tags && _tags[exclude].indexOf(propertyName)!==-1) { | |
valid=false; | |
break; | |
} | |
} | |
if(valid) { | |
compilingProperties[propertyName]=_properties[propertyName]; | |
} | |
} | |
var compileSourceBody="return function(" | |
var scopedArgs=[] | |
for(var i=0;i<_arguments.length;i++) { | |
var value=_arguments[i]; | |
scopedArgs[i]=value.name; | |
} | |
compileSourceBody+=scopedArgs.join(",")+"){"; | |
for(var i=0;i<_arguments.length;i++) { | |
var value=_arguments[i]; | |
compileSourceBody+="if(typeof("+value.name+")==='undefined')"+value.name+"="+value.value+";" | |
} | |
for(var propertyName in compilingProperties) { | |
var propertyDescriptor=compilingProperties[propertyName]; | |
var value=propertyDescriptor.value | |
if(value) { | |
compileSourceBody+="this["+JSON.stringify(propertyName)+"]=("+value+");"; | |
} | |
} | |
for(var propertyName in privateProperties) { | |
a[propertyName]=privateProperties[propertyName]; | |
} | |
compileSourceBody+=";return this;}" | |
compileSourceBody="arguments=(function(){return function(){" | |
+(allowExtension | |
?"" | |
:"if(this!==(function(){return this;})()){throw new Error('not-extensible');};" | |
) | |
+compileSourceBody | |
+".apply(this!==(function(){return this;})()?this:{},arguments)}}).call(arguments);" | |
sys.puts("src::",compileSourceBody) | |
a.arguments.src=compileSourceBody | |
} | |
with(a) { | |
(eval( | |
arguments["src"] | |
)) | |
} | |
return a["arguments"]; | |
} | |
//Generate a JS string for this interface, loses all closures / native functions | |
$this.exportable=function( | |
excludeTags//dont include properties with these flags (dictionary) {flag:true} | |
,allowExtension/*can put on other objects/can use constructor (boolean) */ | |
,privateProperties/*closure based variables, hidden beyond this...should we return this? (dictionary) */ | |
) { | |
var compilingProperties={}; | |
for(var propertyName in _properties) { | |
var valid=true; | |
for(var exclude in excludeTags) { | |
if(exclude in _tags && _tags[exclude].indexOf(propertyName)!==-1) { | |
valid=false; | |
break; | |
} | |
} | |
if(valid) { | |
compilingProperties[propertyName]=_properties[propertyName]; | |
} | |
} | |
var compileSourceBody="" | |
var scopedArgs=[] | |
for(var i=0;i<_arguments.length;i++) { | |
var value=_arguments[i]; | |
scopedArgs[i]=value.name; | |
} | |
for(var i=0;i<_arguments.length;i++) { | |
var value=_arguments[i]; | |
compileSourceBody+="if(typeof("+value.name+")==='undefined')"+value.name+"="+value.value+";" | |
} | |
for(var propertyName in privateProperties) { | |
compileSourceBody+="var "+propertyName+"="+privateProperties[propertyName]+";"; | |
} | |
for(var propertyName in compilingProperties) { | |
var propertyDescriptor=compilingProperties[propertyName]; | |
var value=propertyDescriptor.value | |
if(value) { | |
compileSourceBody+="this["+JSON.stringify(propertyName)+"]=("+value+");"; | |
} | |
} | |
compileSourceBody+=";return this;}" | |
compileSourceBody="function(" | |
+(allowExtension | |
?"" | |
:"){if(this!==(function(){return this;})()){throw new Error('not-extensible');}; return function(" | |
) | |
+scopedArgs.join(",")+"){" | |
+compileSourceBody | |
+(allowExtension | |
?"" | |
:"}.apply(this!==(function(){return this;})()?this:{},arguments)}" | |
) | |
+"" | |
//sys.puts("exptsrc::",compileSourceBody) | |
return compileSourceBody | |
} | |
return $this; | |
} | |
var Car=Interface(); | |
//Car.addArgument("_wheels",0,4) | |
var _wheels=22; | |
Car.addProperty("wheels",{value:function(){return _wheels;}}); | |
Car.addProperty("fly",{value:true}); | |
Car.tagProperty("fly","todo") | |
var VW=Car.compile( | |
//exclude tags | |
{ | |
//todo:true | |
},true,{ | |
_wheels:3 | |
} | |
) | |
sys.puts( | |
"EXPORTABLE:::" | |
,Car.exportable({},true,{_wheels:4}) | |
) | |
sys.puts( | |
"INSPECTING:::" | |
,sys.inspect(VW.toString()) | |
,sys.inspect(VW()) | |
,sys.inspect(VW().wheels()) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment