/* This file is part of the Free Pascal pas2js tool. Copyright (c) 2017 Mattias Gaertner Basic RTL for pas2js programs. See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ var pas = {}; var rtl = { quiet: false, debug_load_units: false, 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, 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); }, isArray: function(a) { return a instanceof Array; }, isNumber: function(n){ return typeof(n)=="number"; }, isInteger: function(A){ return Math.floor(A)===A; }, isBoolean: function(b){ return typeof(b)=="boolean"; }, isString: function(s){ return typeof(s)=="string"; }, isObject: function(o){ return typeof(o)=="object"; }, isFunction: function(f){ return typeof(f)=="function"; }, isNull: function(o){ return (o==null && typeof(o)=='object') || o==undefined; }, isRecord: function(r){ return (typeof(r)=="function") && (typeof(r.$create) == "function"); }, isClass: function(c){ return (typeof(o)=="object") && (o.$class == o); }, isClassInstance: function(c){ return (typeof(o)=="object") && (o.$class == Object.getPrototypeOf(o)); }, hasString: function(s){ return rtl.isString(s) && (s.length>0); }, module: function(module_name, intfuseslist, code, impluseslist){ if (rtl.debug_load_units) rtl.debug('rtl.module name="'+module_name+'" intfuses='+intfuseslist+' impluses='+impluseslist); 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(code)) rtl.error('invalid module code of "'+module_name+'"'); if ((impluseslist!=undefined) && !rtl.isArray(impluseslist)) rtl.error('invalid implementation useslist of "'+module_name+'"'); if (pas[module_name]) rtl.error('module "'+module_name+'" already registered'); var module = pas[module_name] = { $name: module_name, $intfuseslist: intfuseslist, $impluseslist: impluseslist, $state: rtl.m_loading, $code: code }; }, run: function(module_name){ if (module_name==undefined) module_name='program'; if (rtl.debug_load_units) rtl.debug('rtl.run module="'+module_name+'"'); var module = pas[module_name]; rtl.loadintf(module); rtl.loadimpl(module); if (module_name=='program'){ if (rtl.debug_load_units) rtl.debug('running $main'); pas.program.$main(); } return pas.System.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.$code(module.$intfuseslist,module); // 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