ActiveCellsRuntime.mod 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. (** Active Cells Runtime Base Code for Variations of ActiveCellsRuntime Implementations
  2. Felix Friedrich, ETH Z 2015
  3. *)
  4. module ActiveCellsRuntime;
  5. import
  6. system, Heaps, Modules, Diagnostics, Strings, Objects, Reflection, Commands, Streams;
  7. const
  8. EnableTrace* = false;
  9. type
  10. (* do not inherit from this object -- not supported. This object contains hidden fields instantiated by the compiler that would be lost. *)
  11. Cell* = object (* must be exported for compiler *)
  12. var
  13. c: any;
  14. end Cell;
  15. Context*= object
  16. var
  17. topNet-: any; (** top-level CELLNET object specific to this runtime context *)
  18. finishedAssembly-: boolean; (** assigned to TRUE after the whole architecture has been assembled *)
  19. res*: longint; (** error code, 0 in case of success *)
  20. procedure Allocate*(scope: any; var c: any; t: Modules.TypeDesc; const name: array of char; isCellNet, isEngine: boolean);
  21. end Allocate;
  22. procedure AddPort*(c: any; var p: any; const name: array of char; inout: set; width: longint);
  23. end AddPort;
  24. procedure AddPortArray*(c: any; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
  25. end AddPortArray;
  26. procedure AddStaticPortArray*(c: any; var ports: array of any; const name: array of char; inout: set; width: longint);
  27. end AddStaticPortArray;
  28. procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
  29. end AddPortIntegerProperty;
  30. procedure AddFlagProperty*(c: any; const name: array of char);
  31. end AddFlagProperty;
  32. procedure AddStringProperty*(c: any; const name: array of char; const value: array of char);
  33. end AddStringProperty;
  34. procedure AddIntegerProperty*(c: any; const name: array of char; value: longint);
  35. end AddIntegerProperty;
  36. procedure AddBooleanProperty*(c: any; const name: array of char; value: boolean);
  37. end AddBooleanProperty;
  38. procedure AddRealProperty*(c: any; const name: array of char; value: longreal);
  39. end AddRealProperty;
  40. procedure AddSetProperty*(c: any; const name: array of char; s: set);
  41. end AddSetProperty;
  42. procedure FinishedProperties*(var c: any);
  43. end FinishedProperties;
  44. procedure Connect*(outPort, inPort: any; depth: longint);
  45. end Connect;
  46. procedure Delegate*(netPort: any; cellPort: any);
  47. end Delegate;
  48. procedure Start*(c: any; proc: procedure{DELEGATE});
  49. end Start;
  50. procedure Send*(p: any; value: longint);
  51. end Send;
  52. procedure BulkSend*(p: any; const value: array of system.byte);
  53. end BulkSend;
  54. procedure SendNonBlocking*(p: any; value: longint): boolean;
  55. end SendNonBlocking;
  56. procedure Receive*(p: any; var value: longint);
  57. end Receive;
  58. procedure BulkReceive*(p: any; var value: array of system.byte);
  59. end BulkReceive;
  60. procedure ReceiveNonBlocking*(p: any; var value: longint): boolean;
  61. begin
  62. end ReceiveNonBlocking;
  63. (* called in Execute after the architecture is fully assembled *)
  64. procedure FinishedAssembly();
  65. begin{EXCLUSIVE}
  66. finishedAssembly := true;
  67. end FinishedAssembly;
  68. procedure WaitUntilFinishedAssembly();
  69. begin{EXCLUSIVE}
  70. await(finishedAssembly or (res # 0));
  71. end WaitUntilFinishedAssembly;
  72. end Context;
  73. Launcher* = object
  74. var
  75. proc: procedure {DELEGATE};
  76. context: Context;
  77. finished, delayedStart: boolean;
  78. error-: boolean;
  79. procedure & Init*(context: Context);
  80. begin
  81. self.context := context;
  82. proc := nil;
  83. finished := false;
  84. end Init;
  85. procedure Start*(p: procedure{DELEGATE}; doWait: boolean);
  86. begin{EXCLUSIVE}
  87. proc := p;
  88. if ~doWait then delayedStart := true; end; (* delay actual start until the whole architecture is fully assembled *)
  89. await(~doWait or finished);
  90. end Start;
  91. begin{ACTIVE}
  92. begin{EXCLUSIVE}
  93. await(proc # nil);
  94. end;
  95. if delayedStart then
  96. context.WaitUntilFinishedAssembly;
  97. end;
  98. if context.res = 0 then
  99. proc;
  100. end;
  101. begin{EXCLUSIVE}
  102. finished := true
  103. end;
  104. finally
  105. begin{EXCLUSIVE}
  106. if ~finished then
  107. error := true;
  108. finished := true;
  109. end;
  110. end;
  111. end Launcher;
  112. procedure GetContext(): Context;
  113. begin
  114. return Objects.ActiveObject()(Launcher).context;
  115. end GetContext;
  116. procedure AllocateOnContext(context: Context;scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
  117. var
  118. a: any;
  119. typeInfo: Modules.TypeDesc;
  120. s, ac: any;
  121. begin
  122. (* allocation of cells must use the tag provided, it contains all internally stored metadata *)
  123. Heaps.NewRec(a, tag, false);
  124. system.get(tag-sizeof(address),typeInfo);
  125. if EnableTrace then trace(scope, c, typeInfo, name, isCellnet, isEngine); end;
  126. if scope # nil then s := scope.c else s := nil end;
  127. if c # nil then ac := c.c else ac := nil end;
  128. c := a(Cell);
  129. context.Allocate(s, ac, typeInfo, name, isCellnet, isEngine);
  130. c.c := ac;
  131. if scope = nil then context.topNet := ac; end;
  132. end AllocateOnContext;
  133. procedure Allocate*(scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
  134. begin
  135. AllocateOnContext(GetContext(), scope, c, tag, name, isCellnet, isEngine);
  136. end Allocate;
  137. procedure AddPort*(c: Cell; var p: any; const name: array of char; inout: set; width: longint);
  138. begin
  139. if EnableTrace then trace(c,p,name, inout, width); end;
  140. GetContext().AddPort(c.c, p, name, inout, width);
  141. end AddPort;
  142. procedure AddPortArray*(c: Cell; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
  143. begin
  144. if EnableTrace then trace(name, inout, width, len(lens)); end;
  145. GetContext().AddPortArray(c.c, ports, name, inout, width, lens);
  146. end AddPortArray;
  147. procedure AddStaticPortArray*(c: Cell; var ports: array of any; const name: array of char; inout: set; width: longint);
  148. begin
  149. if EnableTrace then trace(name, inout, width, len(ports)); end;
  150. GetContext().AddStaticPortArray(c.c, ports, name, inout, width);
  151. end AddStaticPortArray;
  152. procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
  153. begin
  154. if EnableTrace then trace(p, name, value); end;
  155. GetContext().AddPortIntegerProperty(p,name,value);
  156. end AddPortIntegerProperty;
  157. procedure AddFlagProperty*(c: Cell; const name: array of char);
  158. begin
  159. if EnableTrace then trace(c, name); end;
  160. GetContext().AddFlagProperty(c.c, name);
  161. end AddFlagProperty;
  162. procedure AddStringProperty*(c: Cell; const name: array of char; var newValue: array of char; const value: array of char);
  163. begin
  164. if EnableTrace then trace(c, name, newValue, value); end;
  165. copy(value, newValue);
  166. GetContext().AddStringProperty(c.c, name, value);
  167. end AddStringProperty;
  168. procedure AddIntegerProperty*(c: Cell; const name: array of char; var newValue: longint; value: longint);
  169. begin
  170. if EnableTrace then trace(c, name, newValue, value); end;
  171. newValue := value;
  172. GetContext().AddIntegerProperty(c.c, name, value);
  173. end AddIntegerProperty;
  174. procedure AddBooleanProperty*(c: Cell; const name: array of char; var newValue: boolean; value: boolean);
  175. begin
  176. if EnableTrace then trace(c, name, newValue, value); end;
  177. newValue := value;
  178. GetContext().AddBooleanProperty(c.c, name, value);
  179. end AddBooleanProperty;
  180. procedure AddRealProperty*(c: Cell; const name: array of char; var newValue: longreal; value: longreal);
  181. begin
  182. if EnableTrace then trace(c, name, newValue, value, entier(value)); end;
  183. newValue := value;
  184. GetContext().AddRealProperty(c.c, name, value);
  185. end AddRealProperty;
  186. procedure AddSetProperty*(c: Cell; const name: array of char; var newValue: set; value: set);
  187. begin
  188. if EnableTrace then trace(c, name, newValue, value); end;
  189. newValue := value;
  190. GetContext().AddSetProperty(c.c, name, value);
  191. end AddSetProperty;
  192. procedure FinishedProperties*(c: Cell);
  193. begin
  194. if EnableTrace then trace(c); end;
  195. GetContext().FinishedProperties(c.c);
  196. end FinishedProperties;
  197. procedure Connect*(outPort, inPort: any; depth: longint);
  198. begin
  199. if EnableTrace then trace(outPort, inPort, outPort, inPort, depth); end;
  200. GetContext().Connect(outPort, inPort, depth);
  201. end Connect;
  202. procedure Delegate*(netPort: any; cellPort: any);
  203. begin
  204. if EnableTrace then trace(netPort, cellPort); end;
  205. GetContext().Delegate(netPort, cellPort);
  206. end Delegate;
  207. procedure Start*(c: Cell; proc: procedure{DELEGATE});
  208. begin
  209. if EnableTrace then trace(c, proc); end;
  210. GetContext().Start(c.c, proc);
  211. end Start;
  212. procedure Send*(p: any; value: longint);
  213. begin
  214. GetContext().Send(p, value);
  215. end Send;
  216. procedure BulkSend*(p: any; const value: array of system.byte);
  217. begin
  218. GetContext().BulkSend(p,value);
  219. end BulkSend;
  220. procedure SendNonBlocking*(p: any; value: longint): boolean;
  221. begin
  222. return GetContext().SendNonBlocking(p, value);
  223. end SendNonBlocking;
  224. procedure Receive*(p: any; var value: longint);
  225. begin
  226. GetContext().Receive(p, value);
  227. end Receive;
  228. procedure BulkReceive*(p: any; var value: array of system.byte);
  229. begin
  230. GetContext().BulkReceive(p,value);
  231. end BulkReceive;
  232. procedure ReceiveNonBlocking*(p: any; var value: longint): boolean;
  233. begin
  234. return GetContext().ReceiveNonBlocking(p, value);
  235. end ReceiveNonBlocking;
  236. type
  237. Module = pointer to record
  238. next: Module;
  239. checked, imports: boolean;
  240. m: Modules.Module
  241. end;
  242. procedure Find(root: Module; m: Modules.Module): Module;
  243. begin
  244. while (root # nil) & (root.m # m) do root := root.next end;
  245. return root
  246. end Find;
  247. procedure Imports(root, m: Module; const name: array of char): boolean;
  248. var i: longint;
  249. begin
  250. if ~m.checked then
  251. if m.m.name # name then
  252. i := 0;
  253. while i # len(m.m.module) do
  254. if (m.m.module[i].name = name) or Imports(root, Find(root, m.m.module[i]), name) then
  255. m.imports := true; i := len(m.m.module)
  256. else
  257. inc(i)
  258. end
  259. end
  260. else
  261. m.imports := true
  262. end;
  263. m.checked := true
  264. end;
  265. return m.imports
  266. end Imports;
  267. (*! caution: this is not thread safe -- must be moved to Modules.Mod *)
  268. procedure CopyModules(): Module;
  269. var firstm, lastm, c: Module; m: Modules.Module;
  270. begin
  271. new(firstm); firstm.next := nil; lastm := firstm;
  272. m := Modules.root;
  273. while m # nil do
  274. new(c); c.checked := false; c.imports := false; c.m := m;
  275. c.next := nil; lastm.next := c; lastm := c;
  276. m := m.next
  277. end;
  278. return firstm.next
  279. end CopyModules;
  280. procedure FreeDownTo(const modulename: array of char): longint;
  281. var
  282. root, m: Module; res: longint;
  283. nbrOfUnloadedModules : longint;
  284. msg: array 32 of char;
  285. begin
  286. nbrOfUnloadedModules := 0;
  287. root := CopyModules();
  288. m := root;
  289. while m # nil do
  290. if Imports(root, m, modulename) then
  291. Modules.FreeModule(m.m.name, res, msg);
  292. if res # 0 then
  293. (*context.error.String(msg);*)
  294. else
  295. inc(nbrOfUnloadedModules);
  296. end
  297. end;
  298. m := m.next
  299. end;
  300. return nbrOfUnloadedModules;
  301. end FreeDownTo;
  302. (**
  303. Execute ActiveCells CELLNET code
  304. cellNet: name of a CELLNET type in the format "ModuleName.TypeName", e.g. TestActiveCells.TestCellNet
  305. context: runtime context used for executing the ActiveCells code
  306. diagnostics: interface for generation of diagnostic messages (see Diagnostics.Mod)
  307. *)
  308. procedure Execute*(const cellNet: array of char; context: Context; diagnostics: Diagnostics.Diagnostics);
  309. type
  310. StartProc = procedure{DELEGATE}();
  311. Starter = object
  312. var
  313. p: StartProc;
  314. c: Cell;
  315. procedure & InitStarter(proc: address; scope: Cell);
  316. var startProcDesc: record proc: address; selfParam: address; end;
  317. begin
  318. startProcDesc.proc := proc;
  319. startProcDesc.selfParam := scope;
  320. system.move(address of startProcDesc, address of p, 2 * size of address);
  321. c := scope;
  322. end InitStarter;
  323. procedure P;
  324. begin
  325. Start(c, p)
  326. end P;
  327. end Starter;
  328. var
  329. moduleName, typeName, name: array 256 of char;
  330. m: Modules.Module;
  331. typeInfo: Modules.TypeDesc;
  332. i: size; res: longint;
  333. str: array 256 of char;
  334. scope: Cell;
  335. unloaded: longint;
  336. starter: Starter;
  337. launcher: Launcher;
  338. offset: size;
  339. pc: address;
  340. begin
  341. assert(context # nil);
  342. context.topNet := nil;
  343. i := Strings.IndexOfByte2(".",cellNet);
  344. if i = -1 then
  345. diagnostics.Error("",Streams.Invalid, "CELLNET type name is malformed");
  346. return;
  347. end;
  348. Strings.Copy(cellNet,0,i,moduleName);
  349. Strings.Copy(cellNet,i+1,Strings.Length(cellNet)-Strings.Length(moduleName),typeName);
  350. unloaded := FreeDownTo(moduleName);
  351. if unloaded > 0 then
  352. (*param.ctx.Information("", Streams.Invalid,"unloaded " & unloaded & " modules")*)
  353. end;
  354. m := Modules.ThisModule(moduleName,res,str);
  355. if m = nil then
  356. Strings.Concat('failed to load module "',moduleName,str);
  357. Strings.Concat(str,'"',str);
  358. diagnostics.Error("",Streams.Invalid,str);
  359. return;
  360. end;
  361. typeInfo := Modules.ThisType(m,typeName);
  362. if typeInfo = nil then
  363. Strings.Concat('failed to find CELLNET type "',cellNet,str);
  364. Strings.Concat(str,'" in module "',str);
  365. Strings.Concat(str,moduleName,str);
  366. Strings.Concat(str,'"',str);
  367. diagnostics.Error("",Streams.Invalid,str);
  368. return;
  369. end;
  370. copy(typeName, name);
  371. Strings.Append(name, ".@Body");
  372. trace(name);
  373. trace(m.refs);
  374. offset := Reflection.FindByName(m.refs, 0, name, true);
  375. if offset # 0 then
  376. if Reflection.GetChar(m.refs,offset) = Reflection.sfProcedure then
  377. Reflection.SkipSize(offset);
  378. Reflection.SkipString(m.refs,offset);
  379. pc := Reflection.GetAddress(m.refs, offset);
  380. trace(pc);
  381. (*assert(len(typeInfo.procedures) = 1);
  382. assert(typeInfo.procedures[0].name^ = "@Body");
  383. *)
  384. (* allocate the top level cellnet *)
  385. AllocateOnContext(context, nil,scope,typeInfo.tag,typeName,true,false);
  386. assert(scope # nil);
  387. assert(scope.c # nil);
  388. new(starter, pc, scope);
  389. end;
  390. new(launcher, context);
  391. launcher.Start(starter.P, true);
  392. context.FinishedAssembly;
  393. assert(~launcher.error);
  394. else
  395. Reflection.Report(Commands.GetContext().out, m.refs, offset);
  396. end;
  397. end Execute;
  398. type bytearray= array of system.byte;
  399. operator "<<"* (p: port out; const a: bytearray);
  400. begin
  401. if EnableTrace then trace('bulk send',len(a)); end;
  402. BulkSend(system.val(any,p),a);
  403. end "<<";
  404. operator "<<"* (var a: bytearray; p: port in);
  405. begin
  406. if EnableTrace then trace('bulk rec',len(a));end;
  407. BulkReceive(system.val(any,p),a);
  408. end "<<";
  409. (*The extra functions for longint and real were introduced because right now primitive types cannot be passed as byte arrays*)
  410. type longintSpecial= longint;
  411. operator "<<"* (p: port out; a: longintSpecial);
  412. begin
  413. if EnableTrace then trace('longint send');end;
  414. BulkSend(system.val(any,p),a);
  415. end "<<";
  416. operator "<<"* (var a: longintSpecial; p: port in);
  417. begin
  418. if EnableTrace then trace('longint rec');end;
  419. BulkReceive(system.val(any,p),a);
  420. end "<<";
  421. type realSpecial= real;
  422. operator "<<"* (p: port out; a: realSpecial);
  423. begin
  424. if EnableTrace then trace('real send');end;
  425. BulkSend(system.val(any,p),a);
  426. end "<<";
  427. operator "<<"* (var a:realSpecial; p: port in);
  428. begin
  429. if EnableTrace then trace('real rec');end;
  430. BulkReceive(system.val(any,p),a);
  431. end "<<";
  432. type Pin = port in; Pout = port out;
  433. operator ">>"* (pout: Pout; pin: Pin);
  434. begin
  435. Connect(system.val(any, pout), system.val(any, pin), 0);
  436. end ">>";
  437. operator ">>"* (cellPort: Pout; netPort: Pout);
  438. begin
  439. Delegate(system.val(any, cellPort), system.val(any, netPort));
  440. end ">>";
  441. operator ">>"* (netPort: Pin; cellPort: Pin);
  442. begin
  443. Delegate(system.val(any, netPort), system.val(any, cellPort));
  444. end ">>";
  445. end ActiveCellsRuntime.
  446. System.FreeDownTo FoxSemanticChecker ~