fpc/utils/pas2js/dist/rtl.js
michael 0ef3fc2f29 * Math.trunc polyfill
git-svn-id: trunk@38051 -
2018-01-26 20:33:42 +00:00

870 lines
26 KiB
JavaScript

var pas = {};
var rtl = {
quiet: false,
debug_load_units: false,
debug_rtti: false,
debug: function(){
if (rtl.quiet || !console || !console.log) return;
console.log(arguments);
},
error: function(s){
rtl.debug('Error: ',s);
throw s;
},
warn: function(s){
rtl.debug('Warn: ',s);
},
hasString: function(s){
return rtl.isString(s) && (s.length>0);
},
isArray: function(a) {
return Array.isArray(a);
},
isFunction: function(f){
return typeof(f)==="function";
},
isModule: function(m){
return rtl.isObject(m) && rtl.hasString(m.$name) && (pas[m.$name]===m);
},
isImplementation: function(m){
return rtl.isObject(m) && rtl.isModule(m.$module) && (m.$module.$impl===m);
},
isNumber: function(n){
return typeof(n)==="number";
},
isObject: function(o){
var s=typeof(o);
return (typeof(o)==="object") && (o!=null);
},
isString: function(s){
return typeof(s)==="string";
},
getNumber: function(n){
return typeof(n)==="number"?n:NaN;
},
getChar: function(c){
return ((typeof(c)==="string") && (c.length===1)) ? c : "";
},
getObject: function(o){
return ((typeof(o)==="object") || (typeof(o)==='function')) ? o : null;
},
isPasClass: function(type){
return (rtl.isObject(type) && type.hasOwnProperty('$classname') && rtl.isObject(type.$module));
},
isPasClassInstance: function(type){
return (rtl.isObject(type) && rtl.isPasClass(type.$class));
},
m_loading: 0,
m_loading_intf: 1,
m_intf_loaded: 2,
m_loading_impl: 3, // loading all used unit
m_initializing: 4, // running initialization
m_initialized: 5,
module: function(module_name, intfuseslist, intfcode, impluseslist, implcode){
if (rtl.debug_load_units) rtl.debug('rtl.module name="'+module_name+'" intfuses='+intfuseslist+' impluses='+impluseslist+' hasimplcode='+rtl.isFunction(implcode));
if (!rtl.hasString(module_name)) rtl.error('invalid module name "'+module_name+'"');
if (!rtl.isArray(intfuseslist)) rtl.error('invalid interface useslist of "'+module_name+'"');
if (!rtl.isFunction(intfcode)) rtl.error('invalid interface code of "'+module_name+'"');
if (!(impluseslist==undefined) && !rtl.isArray(impluseslist)) rtl.error('invalid implementation useslist of "'+module_name+'"');
if (!(implcode==undefined) && !rtl.isFunction(implcode)) rtl.error('invalid implementation code of "'+module_name+'"');
if (pas[module_name])
rtl.error('module "'+module_name+'" is already registered');
var module = pas[module_name] = {
$name: module_name,
$intfuseslist: intfuseslist,
$impluseslist: impluseslist,
$state: rtl.m_loading,
$intfcode: intfcode,
$implcode: implcode,
$impl: null,
$rtti: Object.create(rtl.tSectionRTTI),
};
module.$rtti.$module = module;
if (implcode) module.$impl = {
$module: module,
$rtti: module.$rtti,
};
},
exitcode: 0,
// Create needed polyfills for the rtl to run.
createPolyFills : function () {
if (!Math.trunc) {
Math.trunc = function(v) {
v = +v;
if (!isFinite(v)) return v;
return (v - v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
};
}
},
run: function(module_name){
function doRun(){
if (!rtl.hasString(module_name)) module_name='program';
if (rtl.debug_load_units) rtl.debug('rtl.run module="'+module_name+'"');
rtl.initRTTI();
var module = pas[module_name];
if (!module) rtl.error('rtl.run module "'+module_name+'" missing');
rtl.loadintf(module);
rtl.loadimpl(module);
if (module_name=='program'){
if (rtl.debug_load_units) rtl.debug('running $main');
var r = pas.program.$main();
if (rtl.isNumber(r)) rtl.exitcode = r;
}
}
rtl.createPolyFills();
if (rtl.showUncaughtExceptions) {
try{
doRun();
} catch(re) {
var errMsg = re.hasOwnProperty('$class') ? re.$class.$classname : '';
errMsg += ((errMsg) ? ': ' : '') + (re.hasOwnProperty('fMessage') ? re.fMessage : re);
alert('Uncaught Exception : '+errMsg);
rtl.exitCode = 216;
}
} else {
doRun();
}
return rtl.exitcode;
},
loadintf: function(module){
if (module.$state>rtl.m_loading_intf) return; // already finished
if (rtl.debug_load_units) rtl.debug('loadintf: "'+module.$name+'"');
if (module.$state===rtl.m_loading_intf)
rtl.error('unit cycle detected "'+module.$name+'"');
module.$state=rtl.m_loading_intf;
// load interfaces of interface useslist
rtl.loaduseslist(module,module.$intfuseslist,rtl.loadintf);
// run interface
if (rtl.debug_load_units) rtl.debug('loadintf: run intf of "'+module.$name+'"');
module.$intfcode(module.$intfuseslist);
// success
module.$state=rtl.m_intf_loaded;
// Note: units only used in implementations are not yet loaded (not even their interfaces)
},
loaduseslist: function(module,useslist,f){
if (useslist==undefined) return;
for (var i in useslist){
var unitname=useslist[i];
if (rtl.debug_load_units) rtl.debug('loaduseslist of "'+module.$name+'" uses="'+unitname+'"');
if (pas[unitname]==undefined)
rtl.error('module "'+module.$name+'" misses "'+unitname+'"');
f(pas[unitname]);
}
},
loadimpl: function(module){
if (module.$state>=rtl.m_loading_impl) return; // already processing
if (module.$state<rtl.m_intf_loaded) rtl.error('loadimpl: interface not loaded of "'+module.$name+'"');
if (rtl.debug_load_units) rtl.debug('loadimpl: load uses of "'+module.$name+'"');
module.$state=rtl.m_loading_impl;
// load interfaces of implementation useslist
rtl.loaduseslist(module,module.$impluseslist,rtl.loadintf);
// load implementation of interfaces useslist
rtl.loaduseslist(module,module.$intfuseslist,rtl.loadimpl);
// load implementation of implementation useslist
rtl.loaduseslist(module,module.$impluseslist,rtl.loadimpl);
// Note: At this point all interfaces used by this unit are loaded. If
// there are implementation uses cycles some used units might not yet be
// initialized. This is by design.
// run implementation
if (rtl.debug_load_units) rtl.debug('loadimpl: run impl of "'+module.$name+'"');
if (rtl.isFunction(module.$implcode)) module.$implcode(module.$impluseslist);
// run initialization
if (rtl.debug_load_units) rtl.debug('loadimpl: run init of "'+module.$name+'"');
module.$state=rtl.m_initializing;
if (rtl.isFunction(module.$init)) module.$init();
// unit initialized
module.$state=rtl.m_initialized;
},
createCallback: function(scope, fn){
var cb;
if (typeof(fn)==='string'){
cb = function(){
return scope[fn].apply(scope,arguments);
};
} else {
cb = function(){
return fn.apply(scope,arguments);
};
};
cb.scope = scope;
cb.fn = fn;
return cb;
},
cloneCallback: function(cb){
return rtl.createCallback(cb.scope,cb.fn);
},
eqCallback: function(a,b){
// can be a function or a function wrapper
if (a==b){
return true;
} else {
return (a!=null) && (b!=null) && (a.fn) && (a.scope===b.scope) && (a.fn==b.fn);
}
},
initClass: function(c,parent,name,initfn){
parent[name] = c;
c.$classname = name;
if ((parent.$module) && (parent.$module.$impl===parent)) parent=parent.$module;
c.$parent = parent;
c.$fullname = parent.$name+'.'+name;
if (rtl.isModule(parent)){
c.$module = parent;
c.$name = name;
} else {
c.$module = parent.$module;
c.$name = parent.name+'.'+name;
};
// rtti
if (rtl.debug_rtti) rtl.debug('initClass '+c.$fullname);
var t = c.$module.$rtti.$Class(c.$name,{ "class": c, module: parent });
c.$rtti = t;
if (rtl.isObject(c.$ancestor)) t.ancestor = c.$ancestor.$rtti;
if (!t.ancestor) t.ancestor = null;
// init members
initfn.call(c);
},
createClass: function(parent,name,ancestor,initfn){
// create a normal class,
// ancestor must be null or a normal class,
// the root ancestor can be an external class
var c = null;
if (ancestor != null){
c = Object.create(ancestor);
c.$ancestor = ancestor;
// Note:
// if root is an "object" then c.$ancestor === Object.getPrototypeOf(c)
// if root is a "function" then c.$ancestor === c.__proto__, Object.getPrototypeOf(c) returns the root
} else {
c = {};
c.$create = function(fnname,args){
if (args == undefined) args = [];
var o = Object.create(this);
o.$class = this; // Note: o.$class === Object.getPrototypeOf(o)
o.$init();
try{
o[fnname].apply(o,args);
o.AfterConstruction();
} catch($e){
o.$destroy;
throw $e;
}
return o;
};
c.$destroy = function(fnname){
this.BeforeDestruction();
this[fnname]();
this.$final;
};
};
rtl.initClass(c,parent,name,initfn);
},
createClassExt: function(parent,name,ancestor,newinstancefnname,initfn){
// Create a class using an external ancestor.
// If newinstancefnname is given, use that function to create the new object.
// If exist call BeforeDestruction and AfterConstruction.
var c = null;
c = Object.create(ancestor);
c.$create = function(fnname,args){
if (args == undefined) args = [];
var o = null;
if (newinstancefnname.length>0){
o = this[newinstancefnname](fnname,args);
} else {
o = Object.create(this);
}
o.$class = this; // Note: o.$class === Object.getPrototypeOf(o)
o.$init();
try{
o[fnname].apply(o,args);
if (o.AfterConstruction) o.AfterConstruction();
} catch($e){
o.$destroy;
throw $e;
}
return o;
};
c.$destroy = function(fnname){
if (this.BeforeDestruction) this.BeforeDestruction();
this[fnname]();
this.$final;
};
rtl.initClass(c,parent,name,initfn);
},
tObjectDestroy: "Destroy",
free: function(obj,name){
if (obj[name]==null) return;
obj[name].$destroy(rtl.tObjectDestroy);
obj[name]=null;
},
freeLoc: function(obj){
if (obj==null) return;
obj.$destroy(rtl.tObjectDestroy);
return null;
},
is: function(instance,type){
return type.isPrototypeOf(instance) || (instance===type);
},
isExt: function(instance,type,mode){
// mode===1 means instance must be a Pascal class instance
// mode===2 means instance must be a Pascal class
// Notes:
// isPrototypeOf and instanceof return false on equal
// isPrototypeOf does not work for Date.isPrototypeOf(new Date())
// so if isPrototypeOf is false test with instanceof
// instanceof needs a function on right side
if (instance == null) return false; // Note: ==null checks for undefined too
if ((typeof(type) !== 'object') && (typeof(type) !== 'function')) return false;
if (instance === type){
if (mode===1) return false;
if (mode===2) return rtl.isPasClass(instance);
return true;
}
if (type.isPrototypeOf && type.isPrototypeOf(instance)){
if (mode===1) return rtl.isPasClassInstance(instance);
if (mode===2) return rtl.isPasClass(instance);
return true;
}
if ((typeof type == 'function') && (instance instanceof type)) return true;
return false;
},
EInvalidCast: null,
raiseEInvalidCast: function(){
if (rtl.EInvalidCast){
if (rtl.EInvalidCast.Create){
throw rtl.EInvalidCast.$create("Create");
} else {
throw rtl.EInvalidCast.$create("create");
}
} else {
throw "invalid type cast";
}
},
as: function(instance,type){
if((instance === null) || rtl.is(instance,type)) return instance;
rtl.raiseEInvalidCast();
},
asExt: function(instance,type,mode){
if((instance === null) || rtl.isExt(instance,type,mode)) return instance;
rtl.raiseEInvalidCast();
},
checkMethodCall: function(obj,type){
if (rtl.isObject(obj) && rtl.is(obj,type)) return;
rtl.raiseEInvalidCast();
},
raiseRangeCheck: function(){
var m = pas.sysutils || pas.SysUtils;
if (m){
var t = m.ERangeError || m.erangeerror;
if (rtl.isPasClass(t)){
var f = 'Create';
if (rtl.isFunction(t[f])){
throw t.$create(f);
} else {
throw t.$create('create');
}
}
}
throw 'range error';
},
rc: function(i,minval,maxval){
// range check integer
if ((Math.floor(i)===i) && (i>=minval) && (i<=maxval)) return i;
rtl.raiseRangeCheck();
},
length: function(arr){
return (arr == null) ? 0 : arr.length;
},
arraySetLength: function(arr,defaultvalue,newlength){
// multi dim: (arr,defaultvalue,dim1,dim2,...)
if (arr == null) arr = [];
var p = arguments;
function setLength(a,argNo){
var oldlen = a.length;
var newlen = p[argNo];
if (oldlen!==newlength){
a.length = newlength;
if (argNo === p.length-1){
if (rtl.isArray(defaultvalue)){
for (var i=oldlen; i<newlen; i++) a[i]=[]; // nested array
} else if (rtl.isFunction(defaultvalue)){
for (var i=oldlen; i<newlen; i++) a[i]=new defaultvalue(); // e.g. record
} else if (rtl.isObject(defaultvalue)) {
for (var i=oldlen; i<newlen; i++) a[i]={}; // e.g. set
} else {
for (var i=oldlen; i<newlen; i++) a[i]=defaultvalue;
}
} else {
for (var i=oldlen; i<newlen; i++) a[i]=[]; // nested array
}
}
if (argNo < p.length-1){
// multi argNo
for (var i=0; i<newlen; i++) a[i]=setLength(a[i],argNo+1);
}
return a;
}
return setLength(arr,2);
},
arrayClone: function(type,src,srcpos,end,dst,dstpos){
// type: 0 for references, "refset" for calling refSet(), a function for new type()
// src must not be null
// This function does not range check.
if (rtl.isFunction(type)){
for (; srcpos<end; srcpos++) dst[dstpos++] = new type(src[srcpos]); // clone record
} else if(isString(type) && (type === 'refSet')) {
for (; srcpos<end; srcpos++) dst[dstpos++] = refSet(src[srcpos]); // ref set
} else {
for (; srcpos<end; srcpos++) dst[dstpos++] = src[srcpos]; // reference
};
},
arrayConcat: function(type){
// type: see rtl.arrayClone
var a = [];
var l = 0;
for (var i=1; i<arguments.length; i++) l+=arguments[i].length;
a.length = l;
l=0;
for (var i=1; i<arguments.length; i++){
var src = arguments[i];
if (src == null) continue;
rtl.arrayClone(type,src,0,src.length,a,l);
l+=src.length;
};
return a;
},
arrayCopy: function(type, srcarray, index, count){
// type: see rtl.arrayClone
// if count is missing, use srcarray.length
if (srcarray == null) return [];
if (index < 0) index = 0;
if (count === undefined) count=srcarray.length;
var end = index+count;
if (end>scrarray.length) end = scrarray.length;
if (index>=end) return [];
if (type===0){
return srcarray.slice(index,end);
} else {
var a = [];
a.length = end-index;
rtl.arrayClone(type,srcarray,index,end,a,0);
return a;
}
},
setCharAt: function(s,index,c){
return s.substr(0,index)+c+s.substr(index+1);
},
getResStr: function(mod,name){
var rs = mod.$resourcestrings[name];
return rs.current?rs.current:rs.org;
},
createSet: function(){
var s = {};
for (var i=0; i<arguments.length; i++){
if (arguments[i]!=null){
s[arguments[i]]=true;
} else {
var first=arguments[i+=1];
var last=arguments[i+=1];
for(var j=first; j<=last; j++) s[j]=true;
}
}
return s;
},
cloneSet: function(s){
var r = {};
for (var key in s) r[key]=true;
return r;
},
refSet: function(s){
s.$shared = true;
return s;
},
includeSet: function(s,enumvalue){
if (s.$shared) s = rtl.cloneSet(s);
s[enumvalue] = true;
return s;
},
excludeSet: function(s,enumvalue){
if (s.$shared) s = rtl.cloneSet(s);
delete s[enumvalue];
return s;
},
diffSet: function(s,t){
var r = {};
for (var key in s) if (!t[key]) r[key]=true;
delete r.$shared;
return r;
},
unionSet: function(s,t){
var r = {};
for (var key in s) r[key]=true;
for (var key in t) r[key]=true;
delete r.$shared;
return r;
},
intersectSet: function(s,t){
var r = {};
for (var key in s) if (t[key]) r[key]=true;
delete r.$shared;
return r;
},
symDiffSet: function(s,t){
var r = {};
for (var key in s) if (!t[key]) r[key]=true;
for (var key in t) if (!s[key]) r[key]=true;
delete r.$shared;
return r;
},
eqSet: function(s,t){
for (var key in s) if (!t[key] && (key!='$shared')) return false;
for (var key in t) if (!s[key] && (key!='$shared')) return false;
return true;
},
neSet: function(s,t){
return !rtl.eqSet(s,t);
},
leSet: function(s,t){
for (var key in s) if (!t[key] && (key!='$shared')) return false;
return true;
},
geSet: function(s,t){
for (var key in t) if (!s[key] && (key!='$shared')) return false;
return true;
},
strSetLength: function(s,newlen){
var oldlen = s.length;
if (oldlen > newlen){
return s.substring(0,newlen);
} else if (s.repeat){
// Note: repeat needs ECMAScript6!
return s+' '.repeat(newlen-oldlen);
} else {
while (oldlen<newlen){
s+=' ';
oldlen++;
};
return s;
}
},
spaceLeft: function(s,width){
var l=s.length;
if (l>=width) return s;
if (s.repeat){
// Note: repeat needs ECMAScript6!
return ' '.repeat(width-l) + s;
} else {
while (l<width){
s=' '+s;
l++;
};
};
},
floatToStr : function(d,w,p){
// input 1-3 arguments: double, width, precision
if (arguments.length>2){
return rtl.spaceLeft(d.toFixed(p),w);
} else {
// exponent width
var pad = "";
var ad = Math.abs(d);
if (ad<1.0e+10) {
pad='00';
} else if (ad<1.0e+100) {
pad='0';
}
if (arguments.length<2) {
w=9;
} else if (w<9) {
w=9;
}
var p = w-8;
var s=(d>0 ? " " : "" ) + d.toExponential(p);
s=s.replace(/e(.)/,'E$1'+pad);
return rtl.spaceLeft(s,w);
}
},
initRTTI: function(){
if (rtl.debug_rtti) rtl.debug('initRTTI');
// base types
rtl.tTypeInfo = { name: "tTypeInfo" };
function newBaseTI(name,kind,ancestor){
if (!ancestor) ancestor = rtl.tTypeInfo;
if (rtl.debug_rtti) rtl.debug('initRTTI.newBaseTI "'+name+'" '+kind+' ("'+ancestor.name+'")');
var t = Object.create(ancestor);
t.name = name;
t.kind = kind;
rtl[name] = t;
return t;
};
function newBaseInt(name,minvalue,maxvalue,ordtype){
var t = newBaseTI(name,1 /* tkInteger */,rtl.tTypeInfoInteger);
t.minvalue = minvalue;
t.maxvalue = maxvalue;
t.ordtype = ordtype;
return t;
};
newBaseTI("tTypeInfoInteger",1 /* tkInteger */);
newBaseInt("shortint",-0x80,0x7f,0);
newBaseInt("byte",0,0xff,1);
newBaseInt("smallint",-0x8000,0x7fff,2);
newBaseInt("word",0,0xffff,3);
newBaseInt("longint",-0x80000000,0x7fffffff,4);
newBaseInt("longword",0,0xffffffff,5);
newBaseInt("nativeint",-0x10000000000000,0xfffffffffffff,6);
newBaseInt("nativeuint",0,0xfffffffffffff,7);
newBaseTI("char",2 /* tkChar */);
newBaseTI("string",3 /* tkString */);
newBaseTI("tTypeInfoEnum",4 /* tkEnumeration */,rtl.tTypeInfoInteger);
newBaseTI("tTypeInfoSet",5 /* tkSet */);
newBaseTI("double",6 /* tkDouble */);
newBaseTI("boolean",7 /* tkBool */);
newBaseTI("tTypeInfoProcVar",8 /* tkProcVar */);
newBaseTI("tTypeInfoMethodVar",9 /* tkMethod */,rtl.tTypeInfoProcVar);
newBaseTI("tTypeInfoArray",10 /* tkArray */);
newBaseTI("tTypeInfoDynArray",11 /* tkDynArray */);
newBaseTI("tTypeInfoPointer",15 /* tkPointer */);
var t = newBaseTI("pointer",15 /* tkPointer */,rtl.tTypeInfoPointer);
t.reftype = null;
newBaseTI("jsvalue",16 /* tkJSValue */);
newBaseTI("tTypeInfoRefToProcVar",17 /* tkRefToProcVar */,rtl.tTypeInfoProcVar);
// member kinds
rtl.tTypeMember = {};
function newMember(name,kind){
var m = Object.create(rtl.tTypeMember);
m.name = name;
m.kind = kind;
rtl[name] = m;
};
newMember("tTypeMemberField",1); // tmkField
newMember("tTypeMemberMethod",2); // tmkMethod
newMember("tTypeMemberProperty",3); // tmkProperty
// base object for storing members: a simple object
rtl.tTypeMembers = {};
// tTypeInfoStruct - base object for tTypeInfoClass and tTypeInfoRecord
var tis = newBaseTI("tTypeInfoStruct",0);
tis.$addMember = function(name,ancestor,options){
if (rtl.debug_rtti){
if (!rtl.hasString(name) || (name.charAt()==='$')) throw 'invalid member "'+name+'", this="'+this.name+'"';
if (!rtl.is(ancestor,rtl.tTypeMember)) throw 'invalid ancestor "'+ancestor+':'+ancestor.name+'", "'+this.name+'.'+name+'"';
if ((options!=undefined) && (typeof(options)!='object')) throw 'invalid options "'+options+'", "'+this.name+'.'+name+'"';
};
var t = Object.create(ancestor);
t.name = name;
this.members[name] = t;
this.names.push(name);
if (rtl.isObject(options)){
for (var key in options) if (options.hasOwnProperty(key)) t[key] = options[key];
};
return t;
};
tis.addField = function(name,type,options){
var t = this.$addMember(name,rtl.tTypeMemberField,options);
if (rtl.debug_rtti){
if (!rtl.is(type,rtl.tTypeInfo)) throw 'invalid type "'+type+'", "'+this.name+'.'+name+'"';
};
t.typeinfo = type;
this.fields.push(name);
return t;
};
tis.addFields = function(){
var i=0;
while(i<arguments.length){
var name = arguments[i++];
var type = arguments[i++];
if ((i<arguments.length) && (typeof(arguments[i])==='object')){
this.addField(name,type,arguments[i++]);
} else {
this.addField(name,type);
};
};
};
tis.addMethod = function(name,methodkind,params,result,options){
var t = this.$addMember(name,rtl.tTypeMemberMethod,options);
t.methodkind = methodkind;
t.procsig = rtl.newTIProcSig(params);
t.procsig.resulttype = result?result:null;
this.methods.push(name);
return t;
};
tis.addProperty = function(name,flags,result,getter,setter,options){
var t = this.$addMember(name,rtl.tTypeMemberProperty,options);
t.flags = flags;
t.typeinfo = result;
t.getter = getter;
t.setter = setter;
// Note: in options: params, stored, defaultvalue
if (rtl.isArray(t.params)) t.params = rtl.newTIParams(t.params);
this.properties.push(name);
if (!rtl.isString(t.stored)) t.stored = "";
return t;
};
tis.getField = function(index){
return this.members[this.fields[index]];
};
tis.getMethod = function(index){
return this.members[this.methods[index]];
};
tis.getProperty = function(index){
return this.members[this.properties[index]];
};
newBaseTI("tTypeInfoRecord",12 /* tkRecord */,rtl.tTypeInfoStruct);
newBaseTI("tTypeInfoClass",13 /* tkClass */,rtl.tTypeInfoStruct);
newBaseTI("tTypeInfoClassRef",14 /* tkClassRef */);
},
tSectionRTTI: {
$module: null,
$inherited: function(name,ancestor,o){
if (rtl.debug_rtti){
rtl.debug('tSectionRTTI.newTI "'+(this.$module?this.$module.$name:"(no module)")
+'"."'+name+'" ('+ancestor.name+') '+(o?'init':'forward'));
};
var t = this[name];
if (t){
if (!t.$forward) throw 'duplicate type "'+name+'"';
if (!ancestor.isPrototypeOf(t)) throw 'typeinfo ancestor mismatch "'+name+'" ancestor="'+ancestor.name+'" t.name="'+t.name+'"';
} else {
t = Object.create(ancestor);
t.name = name;
t.module = this.module;
this[name] = t;
}
if (o){
delete t.$forward;
for (var key in o) if (o.hasOwnProperty(key)) t[key]=o[key];
} else {
t.$forward = true;
}
return t;
},
$Scope: function(name,ancestor,o){
var t=this.$inherited(name,ancestor,o);
t.members = {};
t.names = [];
t.fields = [];
t.methods = [];
t.properties = [];
return t;
},
$TI: function(name,kind,o){ var t=this.$inherited(name,rtl.tTypeInfo,o); t.kind = kind; return t; },
$Int: function(name,o){ return this.$inherited(name,rtl.tTypeInfoInteger,o); },
$Enum: function(name,o){ return this.$inherited(name,rtl.tTypeInfoEnum,o); },
$Set: function(name,o){ return this.$inherited(name,rtl.tTypeInfoSet,o); },
$StaticArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoArray,o); },
$DynArray: function(name,o){ return this.$inherited(name,rtl.tTypeInfoDynArray,o); },
$ProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoProcVar,o); },
$RefToProcVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoRefToProcVar,o); },
$MethodVar: function(name,o){ return this.$inherited(name,rtl.tTypeInfoMethodVar,o); },
$Record: function(name,o){ return this.$Scope(name,rtl.tTypeInfoRecord,o); },
$Class: function(name,o){ return this.$Scope(name,rtl.tTypeInfoClass,o); },
$ClassRef: function(name,o){ return this.$inherited(name,rtl.tTypeInfoClassRef,o); },
$Pointer: function(name,o){ return this.$inherited(name,rtl.tTypeInfoPointer,o); },
},
newTIParam: function(param){
// param is an array, 0=name, 1=type, 2=optional flags
var t = {
name: param[0],
typeinfo: param[1],
flags: (rtl.isNumber(param[2]) ? param[2] : 0),
};
return t;
},
newTIParams: function(list){
// list: optional array of [paramname,typeinfo,optional flags]
var params = [];
if (rtl.isArray(list)){
for (var i=0; i<list.length; i++) params.push(rtl.newTIParam(list[i]));
};
return params;
},
newTIProcSig: function(params,result,flags){
var s = {
params: rtl.newTIParams(params),
resulttype: result,
flags: flags
};
return s;
},
}