iced-js
Version:
Interface and Class ExperimenteD JavaScript
1,265 lines (1,260 loc) • 35.8 kB
JavaScript
var iced = {};
(function(){
var classes = [];
var interfaces = [];
iced.class = function(def){
var cls = {};
var curr = classes.length;
cls.constructor = undefined;
var abscheck = {};
abscheck.constructor = undefined;
var intfceCheck = {};
intfceCheck.constructor = undefined;
var intfces = {public:{},private:{},protected:{}};
if(def.roles == undefined){
def.roles = [];
}
else if( !Array.isArray(def.roles)){
def.roles = [def.roles];
}
classes.push({engine:{public:[],staticProtected:{}, abstract:{public:{},protected:{}}, roles:def.roles, virtual:[]}, class:cls});
for(var i = 0; i < def.roles.length; i++){
if(interfaces.indexOf(def.roles[i]) < 0){
throw new Exception("interace role of number "+i+" was not declared.");
}
var privs = ["public","protected","private"];
for(var j = 0; j < privs.length; j++){
for(var prop in def.roles[i][privs[j]]){
intfces[privs[j]][prop] = def.roles[i][privs[j]][prop];
intfceCheck[prop] = false;
}
}
}
if(def.parent != undefined){
var p = search(def.parent);
if(p < 0){
throw new Error("parent class not found.");
}
var privs = ["public","protected","private"];
for(var i = 0; i < privs.length; i++){
for(var prop in classes[p].engine.abstract[privs[i]]){
abscheck[prop] = false;
}
}
}
if(def.public == undefined){def.public = {}; }
if(def.private == undefined){def.private = {}; }
if(def.protected == undefined){def.protected = {}; }
var proto = {public:{},private:{},protected:{}};
var static = {public:{},private:{},protected:{}};
for(var prop in def.public){
if(abscheck[prop] != undefined){
abscheck[prop] = checkAbstract(def.public[prop], prop, "public", classes[p].engine.abstract);
}
if(intfceCheck[prop] != undefined){
intfceCheck[prop] = checkAbstract(def.public[prop], prop, "public", intfces);
}
if(def.public[prop].abstract){
classes[curr].engine.abstract.public[prop] = def.public[prop];
}
if(!def.public[prop].static){
proto.public[prop] = def.public[prop];
}
else{
static.public[prop] = def.public[prop];
}
}
for(var prop in def.protected){
if(abscheck[prop] != undefined){
abscheck[prop] = checkAbstract(def.protected[prop], prop, "protected", classes[p].engine.abstract);
}
if(intfceCheck[prop] != undefined){
intfceCheck[prop] = checkAbstract(def.protected[prop], prop, "protected", intfces);
}
if(def.protected[prop].abstract){
classes[curr].engine.abstract.protected[prop] = def.protected[prop];
}
if(!def.protected[prop].static){
proto.protected[prop] = def.protected[prop];
}
else{
static.protected[prop] = def.protected[prop];
}
}
for(var prop in def.private){
if(abscheck[prop] != undefined){
abscheck[prop] = checkAbstract(def.private[prop], prop, "private", classes[p].engine.abstract);
}
if(intfceCheck[prop] != undefined){
intfceCheck[prop] = checkAbstract(def.private[prop], prop, "private", intfces);
}
if(!def.private[prop].static){
proto.private[prop] = def.private[prop];
}
else{
static.private[prop] = def.private[prop];
}
}
for(var prop in abscheck){
if(abscheck[prop] == false){
throw new Error("Abstract inherited member "+prop+" not correctly implemented.");
}
}
for(var prop in intfceCheck){
if(intfceCheck[prop] == false){
throw new Error("Abstract interface roled member "+prop+" not correctly implemented.");
}
}
var staInternal = {};
var staInternal2 = {};
(function(){
var priv = {};
var prot = {};
var virtual = {};
if(p != undefined){
for(var prop in def.parent){
if(prop != "new" && prop != "parent"){
defineInheritedPublic(prop, def.parent);
}
}
for(var prop in classes[p].engine.protectedStatic){
if(prot[prop] == undefined && prop != "parent"){
defineInheritedProtected(prop, classes[p].engine.protectedStatic);
}
}
defineParent("parent", def.parent);
}
else{
defineParent("parent", Object);
}
function defineParent(prop, par){
Object.defineProperty(cls, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
cls[prop] = par;
}
for(var prop in static.public){
definePublic(prop, static.public[prop]);
}
for(var prop in static.protected){
defineProtected(prop, static.protected[prop]);
}
for(var prop in static.private){
definePrivate(prop, static.private[prop]);
}
classes[curr].engine.protectedStatic = prot;
function defineInheritedPublic(prop, par){
Object.defineProperty(staInternal, prop, {
get: function(){
return par[prop];
},
set: function(val){
return par[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(cls, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
}
function defineInheritedProtected(prop, par){
Object.defineProperty(staInternal, prop, {
get: function(){
return par[prop];
},
set: function(val){
return par[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return staInternal[prop];
},
set: function(val){
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
}
function definePublic(prop, defaul){
delete staInternal[prop];
delete staInternal2[prop];
delete virtual[prop];
delete priv[prop];
delete prot[prop];
delete cls[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(cls, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
if(defaul.virtual || defaul.abstract){
Object.defineProperty(priv, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(staInternal, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
if(typeof virtual[prop] == "function"){
return staInternal2[prop];
}
return virtual[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return virtual[prop].apply(virtual, arguments);
}
}
return virtual[prop] = val;
},
enumerable:true,
configurable:true
});
}
else{
Object.defineProperty(prot, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
}
cls[prop] = defaul.value || getDefault(defaul.type);
if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){
Object.defineProperty(classes[p].engine.protectedStatic, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
function defineProtected(prop, defaul){
delete staInternal[prop];
delete staInternal2[prop];
delete virtual[prop];
delete priv[prop];
delete prot[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
if(defaul.virtual || defaul.abstract){
Object.defineProperty(priv, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(staInternal, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
if(typeof virtual[prop] == "function"){
return staInternal2[prop];
}
return virtual[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return virtual[prop].apply(virtual, arguments);
}
}
return virtual[prop] = val;
},
enumerable:true,
configurable:true
});
}
else{
Object.defineProperty(prot, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
}
prot[prop] = defaul.value || getDefault(defaul.type);
if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){
Object.defineProperty(classes[p].engine.protectedStatic, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
function definePrivate(prop, defaul){
delete staInternal[prop];
delete staInternal2[prop];
delete virtual[prop];
delete priv[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
priv[prop] = defaul.value || getDefault(defaul.type);
if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){
Object.defineProperty(classes[p].engine.protectedStatic, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
})();
classes[curr].engine.create = function(calltype, args){
var pub = {};
var priv = {};
var prot = {};
var internal = {};
var internal2 = {};
var virtual = {};
for(var prop in static.public){
defineStaticPublic(prop, static.public[prop]);
}
for(var prop in static.protected){
defineStaticProtected(prop, static.protected[prop]);
}
for(var prop in static.private){
defineStaticPrivate(prop, static.private[prop]);
}
if(p != undefined){
var parentInternal = classes[p].engine.create("extends");
internal.parent = {};
prot.parent = internal.parent;
priv.parent = prot.parent;
pub.parent = {};
for(var prop in parentInternal){
defineInherited(prop);
}
}
for(var prop in proto.public){
definePublic(prop, proto.public[prop]);
}
for(var prop in proto.protected){
defineProtected(prop, proto.protected[prop]);
}
for(var prop in proto.private){
definePrivate(prop, proto.private[prop]);
}
function defineStaticPublic(prop, defaul){
classes[curr].engine.public.push(prop);
if(pub[prop] != undefined){delete pub[prop];}
if(priv[prop] != undefined){delete priv[prop];}
if(prot[prop] != undefined){delete prot[prop];}
if(internal[prop] != undefined){delete internal[prop];}
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(internal, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(pub, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
}
function defineStaticProtected(prop, defaul){
if(priv[prop] != undefined){delete priv[prop];}
if(prot[prop] != undefined){delete prot[prop];}
if(internal[prop] != undefined){delete internal[prop];}
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(internal, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
}
function defineStaticPrivate(prop, defaul){
if(internal[prop] != undefined){delete internal[prop];}
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(internal, prop, {
get: function(){
if(typeof staInternal[prop] == "function"){
return staInternal2[prop];
}
return staInternal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
staInternal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return staInternal[prop].apply(staInternal, arguments);
}
}
return staInternal[prop] = val;
},
enumerable:true,
configurable:true
});
if(priv[prop] != undefined){delete priv[prop];}
Object.defineProperty(priv, prop, {
get: function(){
return internal[prop];
},
set: function(val){
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
}
function defineInherited(prop, value){
if(prop != "parent"){
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(internal, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
if(classes[p].engine.public.indexOf(prop) >= 0){
Object.defineProperty(pub, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
}
}
Object.defineProperty(priv.parent, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
if(classes[p].engine.public.indexOf(prop) >= 0){
Object.defineProperty(pub.parent, prop, {
get: function(){
return parentInternal[prop];
},
set: function(val){
parentInternal[prop] = val;
},
enumerable: true,
configurable:true
});
}
}
function definePublic(prop, defaul){
classes[curr].engine.public.push(prop);
delete pub[prop];
delete priv[prop];
delete virtual[prop];
delete prot[prop];
delete internal2[prop];
delete internal[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(pub, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
if(defaul.abstract || defaul.virtual){
classes[curr].engine.virtual.push(prop);
Object.defineProperty(priv, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(internal, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
if(typeof virtual[prop] == "function"){
return internal2[prop];
}
return virtual[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
internal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return virtual[prop].apply(virtual, arguments);
}
}
return virtual[prop] = val;
},
enumerable:true,
configurable:true
});
pub[prop] = defaul.value || getDefault(defaul.type);
}
else{
Object.defineProperty(prot, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof internal[prop] == "function"){
return internal2[prop];
}
return internal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
internal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return internal[prop].apply(internal, arguments);
}
}
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
pub[prop] = defaul.value || getDefault(defaul.type);
}
if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){
Object.defineProperty(parentInternal, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
function defineProtected(prop, defaul){
delete priv[prop];
delete virtual[prop];
delete prot[prop];
delete internal2[prop];
delete internal[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
if(defaul.abstract || defaul.virtual){
classes[curr].engine.virtual.push(prop);
Object.defineProperty(priv, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(internal, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(prot, prop, {
get: function(){
if(typeof virtual[prop] == "function"){
return internal2[prop];
}
return virtual[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
internal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return virtual[prop].apply(virtual, arguments);
}
}
return virtual[prop] = val;
},
enumerable:true,
configurable:true
});
prot[prop] = defaul.value || getDefault(defaul.type);
}
else{
Object.defineProperty(prot, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(virtual, prop, {
get: function(){
return prot[prop];
},
set: function(val){
return prot[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof internal[prop] == "function"){
return internal2[prop];
}
return internal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
internal2[prop] = function(){
checkArgs(defaul.args, arguments, prop);
return internal[prop].apply(internal, arguments);
}
}
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
prot[prop] = defaul.value || getDefault(defaul.type);
}
if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){
Object.defineProperty(parentInternal, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
function definePrivate(prop, defaul){
delete priv[prop];
delete virtual[prop];
delete internal2[prop];
delete internal[prop];
if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){
defaul.args = [];
}
Object.defineProperty(virtual, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
Object.defineProperty(priv, prop, {
get: function(){
if(typeof internal[prop] == "function"){
return internal2[prop];
}
return internal[prop];
},
set: function(val){
if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){
throw new Error("Property "+prop+" not correctly setted. Conflicting types.");
}
if(typeof val == "function"){
checkArgs(defaul.args, arguments, prop);
internal2[prop] = function(){
return internal[prop].apply(internal, arguments);
}
}
return internal[prop] = val;
},
enumerable:true,
configurable:true
});
priv[prop] = defaul.value || getDefault(defaul.type);
if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){
Object.defineProperty(parentInternal, prop, {
get: function(){
return priv[prop];
},
set: function(val){
return priv[prop] = val;
},
enumerable:true,
configurable:true
});
}
}
if(calltype == "new"){
if(pub.constructor != undefined){
pub.constructor.apply(internal, args);
}
Object.defineProperty(pub, "constructor", {get:function(){return cls;}, configurable:true, enumerable:true});
return pub;
}
else if(calltype = "extends"){
return prot;
}
}
if(!def.abstract){
cls.new = function(){
return classes[curr].engine.create("new", arguments);
}
}
return cls;
}
iced.interface = function(def){
if(def.public == undefined){def.public = {}; }
if(def.private == undefined){def.private = {}; }
if(def.protected == undefined){def.protected = {}; }
interfaces.push(def);
return def;
}
function search(c){
for(var i = 0; i < classes.length; i++){
if(classes[i].class == c){
return i;
}
}
return -1;
}
function checkAbstract(impl, prop, priv, abs){
var privacy = searchPriv(prop, abs);
if(prop == "public" && privacy != "public" || prop == "protected" && privacy == "private" || abs[privacy][prop].static && !impl.static || !abs[privacy][prop].static && impl.static){
return false;
}
if(abs[privacy][prop].args == undefined){ abs[privacy][prop].args = []; }
if(impl.args == undefined){ impl.args = []; }
if(!argcmp( abs[privacy][prop].args, impl.args)){
return false;
}
return true;
function argcmp(expected, implemented){
var opt;
for(var i = 0; i < expected.length; i++){
opt = (expected[i].required === undefined ? "optional" : "required");
if(expected[i][opt] === undefined){
throw new Error("function arguments can only be required or optional.");
}
if(implemented[i][opt] === undefined || implemented[i][opt] != expected[i][opt]){
return false;
}
}
if(implemented.length > expected.length){
for(var i = expected.length; i < implemented.length; i++){
if(implemented[i].optional === undefined){
return false;
}
}
}
return true;
}
function searchPriv(prp, abst){
var privs = ["public","protected","private"];
for(var i = 0; i < privs.length; i++){
for(var prop in abst[privs[i]]){
if(prop == prp){
return privs[i];
}
}
}
}
}
function checkNativeType(type, val){
if(type == Number || type == "number"){
return !isNaN(val);
}
if(typeof type == "string"){
return typeof val == type;
}
return typeof val == ( type == undefined || type.name == undefined ? type : (type.name.toLowerCase()));
}
function checkObjType(type, val){
if(interfaces.indexOf(type) >= 0 && val === null){
return true;
}
var parent = (val instanceof Object && val.constructor != undefined ? val.constructor : false);
while(parent != Object && parent){
if(parent == type){
return true;
}
if(classes[search(parent)].engine.roles.indexOf(type) >= 0){
return true;
}
parent = parent.parent;
}
return false;
}
function getDefault(type){
if(type != undefined && type.new != undefined){
return type.new();
}
if(typeof type == "string"){
type = type.slice(0,1).toUpperCase() + type.slice(1, type.length);
return (typeof window[type] == "function" ? window[type]() : undefined);
}
if(typeof type == "function"){
return type();
}
return null;
}
function checkArgs(expected, passed, funcname){
funcname = funcname || arguments.callee.name;
var required = true;
var opt = "required";
for(var i = 0; i < expected.length; i++){
if(expected[i].required === undefined){
required = false;
opt = "optional";
}
else{
opt = "required"
}
if(expected[i][opt] === undefined){
throw new Error("function arguments can only be required or optional.");
}
if(required && passed[i] === undefined){
throw new Error("Too few arguments for function "+funcname);
}
if(passed[i] != undefined && expected[i][opt] != undefined && expected[i][opt] != null && !checkNativeType(expected[i][opt], passed[i]) && !checkObjType(expected[i][opt], passed[i]) ){
throw new Error("argument of number "+(i+1)+" was passed with wrong type.");
}
}
}
iced.getDefault = getDefault;
iced.checkObjType = checkObjType;
iced.checkNativeType = checkNativeType;
})();