Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
		
							parent
							
								
									2cb1713348
								
							
						
					
					
						commit
						01afa18734
					
				
							
								
								
									
										397
									
								
								js/top/.rcs/jam.js,v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								js/top/.rcs/jam.js,v
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,397 @@ | ||||||
|  | head	1.2; | ||||||
|  | access; | ||||||
|  | symbols; | ||||||
|  | locks | ||||||
|  | 	sbosse:1.2; strict; | ||||||
|  | comment	@# @; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 1.2 | ||||||
|  | date	2020.02.03.09.45.01;	author sbosse;	state Exp; | ||||||
|  | branches; | ||||||
|  | next	1.1; | ||||||
|  | 
 | ||||||
|  | 1.1 | ||||||
|  | date	2017.05.23.07.00.54;	author sbosse;	state Exp; | ||||||
|  | branches; | ||||||
|  | next	; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | desc | ||||||
|  | @@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 1.2 | ||||||
|  | log | ||||||
|  | @. | ||||||
|  | @ | ||||||
|  | text | ||||||
|  | @/** | ||||||
|  |  **      ============================== | ||||||
|  |  **       O           O      O   OOOO | ||||||
|  |  **       O           O     O O  O   O | ||||||
|  |  **       O           O     O O  O   O | ||||||
|  |  **       OOOO   OOOO O     OOO  OOOO | ||||||
|  |  **       O   O       O    O   O O   O | ||||||
|  |  **       O   O       O    O   O O   O | ||||||
|  |  **       OOOO        OOOO O   O OOOO | ||||||
|  |  **      ============================== | ||||||
|  |  **      Dr. Stefan Bosse http://www.bsslab.de | ||||||
|  |  ** | ||||||
|  |  **      COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED | ||||||
|  |  **                 BY THE AUTHOR(S). | ||||||
|  |  **                 THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, | ||||||
|  |  **                 MODIFIED, OR OTHERWISE USED IN A CONTEXT | ||||||
|  |  **                 OUTSIDE OF THE SOFTWARE SYSTEM. | ||||||
|  |  ** | ||||||
|  |  **    $AUTHORS:     Stefan Bosse | ||||||
|  |  **    $INITIAL:     (C) 2006-2017 bLAB | ||||||
|  |  **    $CREATED:     10-3-16 by sbosse. | ||||||
|  |  **    $VERSION:     1.3.4 | ||||||
|  |  ** | ||||||
|  |  **    $INFO: | ||||||
|  |  ** | ||||||
|  |  **  JAM Standalone Node VM | ||||||
|  |  ** | ||||||
|  |  **    $ENDOFINFO | ||||||
|  |  */ | ||||||
|  | var onexit=false; | ||||||
|  | var start=false; | ||||||
|  | var options = { | ||||||
|  |   amp:false, | ||||||
|  |   aport:6000, | ||||||
|  |   connect:[], | ||||||
|  |   debug:false, | ||||||
|  |   verbose:0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | global.config={simulation:false}; | ||||||
|  | 
 | ||||||
|  | var Io = Require('com/io'); | ||||||
|  | var Comp = Require('com/compat'); | ||||||
|  | var Db = Require('db/db'); | ||||||
|  | var Aios = Require('jam/aios'); | ||||||
|  | var Buf = Require('dos/buf'); | ||||||
|  | var Net = Require('dos/network'); | ||||||
|  | var Esprima = Require('parser/esprima'); | ||||||
|  | var Json = Require('jam/jsonfn'); | ||||||
|  | var Db = Require('db/db'); | ||||||
|  | 
 | ||||||
|  | var out = function (msg) { Io.out('[JAM] '+msg)}; | ||||||
|  | 
 | ||||||
|  | var jam = function (options) { | ||||||
|  |   var self=this; | ||||||
|  |   this.options = options||{}; | ||||||
|  |   this.verbose = options.verbose||0; | ||||||
|  |   if (!this.options.id) this.options.id=Aios.aidgen(); | ||||||
|  |   this.world = Aios.World.World([],{id:this.options.id,classes:options.classes||[]}); | ||||||
|  |   this.node = Aios.Node.Node({id:this.options.id,position:{x:0,y:0}},true); | ||||||
|  |   this.world.addNode(this.node); | ||||||
|  |   this.run=false; | ||||||
|  |   this.loopnext=none; | ||||||
|  |   this.looprun=false; | ||||||
|  |   this.loop = function () { | ||||||
|  |     var loop = function () {   | ||||||
|  |       self.looprun=true; | ||||||
|  |       var nexttime=Aios.scheduler(); | ||||||
|  |       self.looprun=false; | ||||||
|  |       var curtime=Aios.time(); | ||||||
|  |       if (self.options.verbose>1) self.out('loop: nexttime='+nexttime+ | ||||||
|  |                                            ' ('+(nexttime>0?nexttime-curtime:0)+')'); | ||||||
|  |       if (nexttime>0) self.looprun=setTimeout(loop,nexttime-curtime); | ||||||
|  |       else if (nexttime<0) self.looprun=setImmediate(loop); | ||||||
|  |       else self.looprun=setTimeout(loop,1000); | ||||||
|  |     }; | ||||||
|  |     self.loopnext = setTimeout(loop,1); | ||||||
|  |   }; | ||||||
|  |    | ||||||
|  |   this.out=function (msg) {  | ||||||
|  |     Io.out('[JAM '+self.options.id+'] '+msg) | ||||||
|  |   }; | ||||||
|  |   this.err=function (msg,err) { | ||||||
|  |     self.out('Error: '+msg); | ||||||
|  |     throw (err||'Error'); | ||||||
|  |   } | ||||||
|  |   this.warn=function (msg) { | ||||||
|  |     self.out('Warning: '+msg); | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   this.amp=options.amp; | ||||||
|  |   this.aport=options.aport||6000; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Import analyzer class... | ||||||
|  | var JamAnal = Require('jam/analyzer'); | ||||||
|  | JamAnal.current(Aios); | ||||||
|  | jam.prototype.analyze=JamAnal.jamc.prototype.analyze; | ||||||
|  | jam.prototype.syntax=JamAnal.jamc.prototype.syntax; | ||||||
|  | 
 | ||||||
|  | /** Add agent class to the JAM world and create sandboxed constructors. | ||||||
|  |  *  type constructor = function|string | ||||||
|  |  */ | ||||||
|  | jam.prototype.addClass = function (name,constructor,env) { | ||||||
|  |   this.world.addClass(name,constructor,env); | ||||||
|  |   if (this.verbose) this.out('Agent class '+name+' added to world library.'); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** Create and start an agent from class ac with arguments.  | ||||||
|  |  *  Ac is either already loaded (i.e., ac specifies the class name) or  | ||||||
|  |  *  AC is supplied as a constructor function (ac), a class name, or a sandboxed constructor | ||||||
|  |  *  {fun:function,mask:{}} object for a specific level. | ||||||
|  |  * | ||||||
|  |  *  type of ac = string|object|function | ||||||
|  |  *  type of args = * [] | ||||||
|  |  *  level = {0,1,2,3} | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | jam.prototype.create = function (ac,args,level) { | ||||||
|  |   var node=this.node, | ||||||
|  |       process=none,sac; | ||||||
|  |   if (level==undefined) level=1; | ||||||
|  |   if (Comp.obj.isFunction(ac) || Comp.obj.isObject(ac)) { | ||||||
|  |     // Create a sandboxed constructor function and agent process | ||||||
|  |     process = Aios.Code.createOn(node,ac,args,level); | ||||||
|  |     if (process) return process.agent.id;    | ||||||
|  |   } else { | ||||||
|  |     // Use an already sandboxed constructor | ||||||
|  |     if (this.world.classes[ac]) | ||||||
|  |       process = Aios.Code.createOn(node,this.world.classes[ac][level],args); | ||||||
|  |     else this.out('create: Cannot find agent class '+ac); | ||||||
|  |     if (process) { | ||||||
|  |       process.agent.ac=ac; | ||||||
|  |       return process.agent.id;  | ||||||
|  |     } else | ||||||
|  |       this.out('create: Cannot find agent class '+ac+' for level '+level);        | ||||||
|  |     return none; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Read and compile agent class templates from file | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | jam.prototype.readClass = function (file) { | ||||||
|  |   var ac, | ||||||
|  |       text, | ||||||
|  |       modu={}, | ||||||
|  |       m,p, | ||||||
|  |       env, | ||||||
|  |       interface, | ||||||
|  |       regex1, | ||||||
|  |       ast=null, | ||||||
|  |       all=null, | ||||||
|  |       off=null; | ||||||
|  |   if (this.options.verbose>0) this.out('Looking up agent class template(s) from '+file); | ||||||
|  |   modu=Require(file); | ||||||
|  |   if (Comp.obj.isEmpty(modu)) { | ||||||
|  |     if (this.options.verbose>0) this.out('Importing agent class template(s) from file '+file); | ||||||
|  |     if (Comp.string.get(file,0)!='/') file = './'+file; | ||||||
|  |     all=Io.read_file(file); | ||||||
|  |     ast=Esprima.parse(all, { tolerant: true, loc:true }); | ||||||
|  |     modu=require(file); | ||||||
|  |   } | ||||||
|  |   if (!modu) this.out('Importing of agent class template(s) from '+file+' failed (empty).'); | ||||||
|  |   for (m in modu) { | ||||||
|  |     ac=modu[m]; | ||||||
|  |     env={}; | ||||||
|  |     if (all) off=this.syntax.find(ast,'VariableDeclarator',m); | ||||||
|  |     if (off && off.loc) this.syntax.offset=off.loc.start.line-1; | ||||||
|  |     content = 'var ac = '+ac; | ||||||
|  |     syntax = Esprima.parse(content, {tolerant: true, loc:true }); | ||||||
|  |     interface = this.analyze(syntax,{classname:m,level:2,verbose:this.options.verbose||0}); | ||||||
|  |     for (var p in interface.activities) env[p]=p; | ||||||
|  |     with (env) { eval(content) }; | ||||||
|  | 
 | ||||||
|  |     if (options.verbose>0) this.out('Adding agent class constructor '+m+' ('+(typeof ac)+').'); | ||||||
|  |     this.addClass(m,ac,env); | ||||||
|  |     this.syntax.offset=0; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** Start the JAM scheduler | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | jam.prototype.start=function () { | ||||||
|  |   this.run=true; | ||||||
|  |   this.out('Starting ..'); | ||||||
|  |   this.loop(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Start AMP service port | ||||||
|  |  */ | ||||||
|  | jam.prototype.startAmp = function () { | ||||||
|  |   var self=this; | ||||||
|  |   var ip = 'localhost'; | ||||||
|  |   this.out('Starting AMP server on port '+this.aport); | ||||||
|  |   this.amp = Aios.Chan.Amp({rcv:ip+':'+this.aport,snd_ip:ip,verbose:this.options.verbose}); | ||||||
|  |   this.amp.receiver(function (handler) { | ||||||
|  |       var code,agentid,stat; | ||||||
|  |       if (!handler) return; | ||||||
|  |       if (self.options.verbose>0) { self.out('AMP: got request:'); console.log(handler) }; | ||||||
|  |       switch (handler.cmd) { | ||||||
|  |         case Net.Command.PS_EXEC: | ||||||
|  |           code = Buf.buf_get_string(handler.buf); | ||||||
|  |           // console.log(code); | ||||||
|  |           // console.log(myJam.amp.url(handler.remote)) | ||||||
|  |           self.node.receive(code); | ||||||
|  |           break; | ||||||
|  |         case Net.Command.PS_STUN: | ||||||
|  |           agentid = Buf.buf_get_string(handler.buf); | ||||||
|  |           stat=Aios.kill(agentid); | ||||||
|  |           if (stat) self.out('Agent '+agentid+' terminated.'); | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** Stop the JAM scheduler | ||||||
|  |  *  | ||||||
|  |  */ | ||||||
|  | jam.prototype.stop=function () { | ||||||
|  |   this.run=false; | ||||||
|  |   this.out('Stopping ..'); | ||||||
|  |   if (this.loopnext) | ||||||
|  |     clearTimeout(this.loopnext); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | var Jam = function(options) { | ||||||
|  |   var obj = new jam(options); | ||||||
|  |   return obj; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function usage(error) { | ||||||
|  |   var msg='Agent JavaScript Machine'+NL; | ||||||
|  |   msg += 'usage: jam [options]'+NL; | ||||||
|  |   msg += ' -c <agentclass>.js : Load an agent class template from file'+NL; | ||||||
|  |   msg += ' -r <agentclass> [<arg>,<arg>,..] : Create an agent from a class template'+NL; | ||||||
|  |   msg += ' -A <port>          : Start AMP service on specified port'+NL; | ||||||
|  |   msg += ' -L <dir> <from> <to>  : Connect this node (from) to another (to) using AMP (url/port)'+NL; | ||||||
|  |   msg += ' -s                 : Start scheduler loop'+NL; | ||||||
|  |   msg += ' -v                 : Increase verbosity level'+NL; | ||||||
|  |   msg += ' -h -help --help    : Print this help'+NL; | ||||||
|  |   msg += ' <dir>              : N,S,W,E,NW,NE,SW,SE,UP,DOWN'+NL; | ||||||
|  |   out(msg);   | ||||||
|  |   if (error) out(error); | ||||||
|  |   onexit=true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Comp.args.parse(Io.getargs(),[ | ||||||
|  |   [['-h','-help','--help'],0,function () {usage()}], | ||||||
|  |   ['-v',0,function () {options.verbose++; out('Setting verbosity level to '+options.verbose); config.verbose=true;}], | ||||||
|  |   ['-s',0,function () {start=true;}], | ||||||
|  |   ['-d',0,function () {options.debug=true;}] | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | var myJam = Jam(options); | ||||||
|  | 
 | ||||||
|  | Comp.args.parse(Io.getargs(),[ | ||||||
|  |   ['-c',1,function (file) { | ||||||
|  |     if (options.debug) | ||||||
|  |      myJam.readClass(file); | ||||||
|  |     else try { | ||||||
|  |       myJam.readClass(file) | ||||||
|  |     } catch (e) { | ||||||
|  |       myJam.out('Compilation failed: '+e+'.'); | ||||||
|  |       Io.exit(); | ||||||
|  |     } | ||||||
|  |   }], | ||||||
|  |   ['-A',1,function (port) { | ||||||
|  |     myJam.amp=true; | ||||||
|  |     myJam.aport=port; | ||||||
|  |     myJam.startAmp(); | ||||||
|  |   }], | ||||||
|  |   ['-L',3,function (dir,port1,port2) { | ||||||
|  |     var _options; | ||||||
|  |     switch (dir) { | ||||||
|  |       case 'N': dir=Aios.DIR.NORTH;break; | ||||||
|  |       case 'S': dir=Aios.DIR.SOUTH; break; | ||||||
|  |       case 'W': dir=Aios.DIR.WEST; break; | ||||||
|  |       case 'E': dir=Aios.DIR.EAST; break; | ||||||
|  |       default: | ||||||
|  |         usage('Invalid first argment of -L'); | ||||||
|  |     } | ||||||
|  |     _options={rcv:port1,snd:port2,amp:true,verbose:options.verbose}; | ||||||
|  |     myJam.world.connectPhy(dir,myJam.node,_options); | ||||||
|  |   }], | ||||||
|  |   ['-r',2,function (ac,args) { | ||||||
|  |     try { | ||||||
|  |       if (args.length < 2) args='[]'; | ||||||
|  |       var _args = Comp.array.map(Comp.string.split(',',Comp.string.trim(args,1,1)),function (arg) { | ||||||
|  |         try {var num=Number(arg); if (isNaN(num)) return arg; else return num;} | ||||||
|  |         catch (e) {return arg } | ||||||
|  |       }); | ||||||
|  |       myJam.create(ac,_args) | ||||||
|  |     } catch (e) { | ||||||
|  |       myJam.out('Failed to start agent '+ac+' '+args+': '+e); | ||||||
|  |     } | ||||||
|  |   }], | ||||||
|  |   ['-db',2,function (path,chan) { | ||||||
|  |     var res; | ||||||
|  |     myJam.db=Db.Sqlc(path,chan); | ||||||
|  |     myJam.db.init(function (res){ | ||||||
|  |       console.log('init: '+res); | ||||||
|  |       myJam.db.exec('help',function (repl) { | ||||||
|  |         console.log(repl); | ||||||
|  |       }); | ||||||
|  |     } ); | ||||||
|  |   }] | ||||||
|  | ]); | ||||||
|  | if (!onexit && start) myJam.start(); | ||||||
|  | @ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 1.1 | ||||||
|  | log | ||||||
|  | @Initial revision | ||||||
|  | @ | ||||||
|  | text | ||||||
|  | @d36 1 | ||||||
|  | d57 1 | ||||||
|  | d101 2 | ||||||
|  | a102 3 | ||||||
|  | /** Add one or more agent class templates  | ||||||
|  |  *  {<ac name>:<ac constructor fun>,..} to the JAM world | ||||||
|  |  *  by creating sandboxed constructors {function,mask}. | ||||||
|  | d104 3 | ||||||
|  | a106 10 | ||||||
|  | jam.prototype.addClass = function (templates) { | ||||||
|  |   for (var p in templates) { | ||||||
|  |     if (this.options.verbose>0) this.out((this.world.classes[p]?'Updating':'Adding')+' agent class template '+p+'.'); | ||||||
|  |     this.world.classes[p]=[ | ||||||
|  |       Aios.Code.makeSandbox(templates[p],0), | ||||||
|  |       Aios.Code.makeSandbox(templates[p],1), | ||||||
|  |       Aios.Code.makeSandbox(templates[p],2), | ||||||
|  |       Aios.Code.makeSandbox(templates[p],3)       | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  | d148 3 | ||||||
|  | a150 1 | ||||||
|  |       p, | ||||||
|  | a159 1 | ||||||
|  |     modu=require(file); | ||||||
|  | d162 1 | ||||||
|  | d165 10 | ||||||
|  | d176 2 | ||||||
|  | a177 15 | ||||||
|  |   for (p in modu) { | ||||||
|  |     ac={}; | ||||||
|  |     ac[p]=modu[p]; | ||||||
|  |     if (all) off=this.syntax.find(ast,'VariableDeclarator',p); | ||||||
|  |     if (off && off.loc) this.syntax.offset=off.loc.start.line-1; | ||||||
|  |     content = 'var ac = '+modu[p]; | ||||||
|  |     syntax = Esprima.parse(content, { tolerant: true, loc:true }); | ||||||
|  |     this.analyze(syntax,{classname:p,level:2}); | ||||||
|  |     text=Json.stringify(ac); | ||||||
|  |     regex1= /this\.next=([a-zA-Z0-9_]+)/; | ||||||
|  |     text=text.replace(regex1,"this.next='$1'"); | ||||||
|  |     // console.log(text); | ||||||
|  |     ac=Json.parse(text,{});     | ||||||
|  |     if (this.options.verbose>0) this.out('Adding agent class template '+p+'.'); | ||||||
|  |     this.addClass(ac); | ||||||
|  | d253 2 | ||||||
|  | a254 1 | ||||||
|  |   ['-s',0,function () {start=true;}] | ||||||
|  | d261 1 | ||||||
|  | a261 1 | ||||||
|  |     if (global.DEBUG) | ||||||
|  | @ | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user