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; }, 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, 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; } } 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.$state0){ 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(descendant,type){ return type.isPrototypeOf(descendant) || (descendant===type); }, isExt: function(instance,type){ // 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 if ((typeof(type) !== 'object') && (typeof(type) !== 'function')) return false; if (instance === type) return true; if (type.isPrototypeOf && type.isPrototypeOf(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){ if((instance === null) || rtl.isExt(instance,type)) return instance; rtl.raiseEInvalidCast(); }, checkMethodCall: function(obj,type){ if (rtl.isObject(obj) && rtl.is(obj,type)) return; rtl.raiseEInvalidCast(); }, 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; iscrarray.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 newlen){ return s.substring(0,newlen); } else if (s.repeat){ // Note: repeat needs ECMAScript6! return s+' '.repeat(newlen-oldlen); } else { while (oldlen=width) return s; if (s.repeat){ // Note: repeat needs ECMAScript6! return ' '.repeat(width-l) + s; } else { while (l2){ 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