123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- (** Active Cells Runtime Base Code for Variations of ActiveCellsRuntime Implementations
- Felix Friedrich, ETH Z 2015
- *)
- module ActiveCellsRuntime;
- import
- system, Heaps, Modules, Diagnostics, Strings, Objects, Reflection, Commands, Streams;
- const
- EnableTrace* = false;
- type
- (* do not inherit from this object -- not supported. This object contains hidden fields instantiated by the compiler that would be lost. *)
- Cell* = object (* must be exported for compiler *)
- var
- c: any;
- end Cell;
- Context*= object
- var
- topNet-: any; (** top-level CELLNET object specific to this runtime context *)
- finishedAssembly-: boolean; (** assigned to TRUE after the whole architecture has been assembled *)
- res*: longint; (** error code, 0 in case of success *)
-
- procedure Allocate*(scope: any; var c: any; t: Modules.TypeDesc; const name: array of char; isCellNet, isEngine: boolean);
- end Allocate;
-
- procedure AddPort*(c: any; var p: any; const name: array of char; inout: set; width: longint);
- end AddPort;
-
- procedure AddPortArray*(c: any; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
- end AddPortArray;
- procedure AddStaticPortArray*(c: any; var ports: array of any; const name: array of char; inout: set; width: longint);
- end AddStaticPortArray;
- procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
- end AddPortIntegerProperty;
- procedure AddFlagProperty*(c: any; const name: array of char);
- end AddFlagProperty;
- procedure AddStringProperty*(c: any; const name: array of char; const value: array of char);
- end AddStringProperty;
- procedure AddIntegerProperty*(c: any; const name: array of char; value: longint);
- end AddIntegerProperty;
- procedure AddBooleanProperty*(c: any; const name: array of char; value: boolean);
- end AddBooleanProperty;
- procedure AddRealProperty*(c: any; const name: array of char; value: longreal);
- end AddRealProperty;
- procedure AddSetProperty*(c: any; const name: array of char; s: set);
- end AddSetProperty;
- procedure FinishedProperties*(var c: any);
- end FinishedProperties;
- procedure Connect*(outPort, inPort: any; depth: longint);
- end Connect;
- procedure Delegate*(netPort: any; cellPort: any);
- end Delegate;
- procedure Start*(c: any; proc: procedure{DELEGATE});
- end Start;
- procedure Send*(p: any; value: longint);
- end Send;
-
- procedure BulkSend*(p: any; const value: array of system.byte);
- end BulkSend;
-
- procedure SendNonBlocking*(p: any; value: longint): boolean;
- end SendNonBlocking;
- procedure Receive*(p: any; var value: longint);
- end Receive;
-
- procedure BulkReceive*(p: any; var value: array of system.byte);
- end BulkReceive;
-
- procedure ReceiveNonBlocking*(p: any; var value: longint): boolean;
- begin
- end ReceiveNonBlocking;
-
- (* called in Execute after the architecture is fully assembled *)
- procedure FinishedAssembly();
- begin{EXCLUSIVE}
- finishedAssembly := true;
- end FinishedAssembly;
- procedure WaitUntilFinishedAssembly();
- begin{EXCLUSIVE}
- await(finishedAssembly or (res # 0));
- end WaitUntilFinishedAssembly;
-
- end Context;
-
- Launcher* = object
- var
- proc: procedure {DELEGATE};
- context: Context;
- finished, delayedStart: boolean;
- error-: boolean;
-
- procedure & Init*(context: Context);
- begin
- self.context := context;
- proc := nil;
- finished := false;
- end Init;
-
- procedure Start*(p: procedure{DELEGATE}; doWait: boolean);
- begin{EXCLUSIVE}
- proc := p;
- if ~doWait then delayedStart := true; end; (* delay actual start until the whole architecture is fully assembled *)
- await(~doWait or finished);
- end Start;
-
- begin{ACTIVE}
- begin{EXCLUSIVE}
- await(proc # nil);
- end;
- if delayedStart then
- context.WaitUntilFinishedAssembly;
- end;
- if context.res = 0 then
- proc;
- end;
- begin{EXCLUSIVE}
- finished := true
- end;
- finally
- begin{EXCLUSIVE}
- if ~finished then
- error := true;
- finished := true;
- end;
- end;
- end Launcher;
-
- procedure GetContext(): Context;
- begin
- return Objects.ActiveObject()(Launcher).context;
- end GetContext;
-
- procedure AllocateOnContext(context: Context;scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
- var
- a: any;
- typeInfo: Modules.TypeDesc;
- s, ac: any;
- begin
- (* allocation of cells must use the tag provided, it contains all internally stored metadata *)
- Heaps.NewRec(a, tag, false);
- system.get(tag-sizeof(address),typeInfo);
- if EnableTrace then trace(scope, c, typeInfo, name, isCellnet, isEngine); end;
-
- if scope # nil then s := scope.c else s := nil end;
- if c # nil then ac := c.c else ac := nil end;
- c := a(Cell);
- context.Allocate(s, ac, typeInfo, name, isCellnet, isEngine);
- c.c := ac;
-
- if scope = nil then context.topNet := ac; end;
- end AllocateOnContext;
-
- procedure Allocate*(scope: Cell; var c: Cell; tag: address; const name: array of char; isCellnet, isEngine: boolean);
- begin
- AllocateOnContext(GetContext(), scope, c, tag, name, isCellnet, isEngine);
- end Allocate;
- procedure AddPort*(c: Cell; var p: any; const name: array of char; inout: set; width: longint);
- begin
- if EnableTrace then trace(c,p,name, inout, width); end;
- GetContext().AddPort(c.c, p, name, inout, width);
- end AddPort;
- procedure AddPortArray*(c: Cell; var ports: any; const name: array of char; inout: set; width: longint; const lens: array of longint);
- begin
- if EnableTrace then trace(name, inout, width, len(lens)); end;
- GetContext().AddPortArray(c.c, ports, name, inout, width, lens);
- end AddPortArray;
- procedure AddStaticPortArray*(c: Cell; var ports: array of any; const name: array of char; inout: set; width: longint);
- begin
- if EnableTrace then trace(name, inout, width, len(ports)); end;
- GetContext().AddStaticPortArray(c.c, ports, name, inout, width);
- end AddStaticPortArray;
- procedure AddPortIntegerProperty*(p: any; const name: array of char; value: longint);
- begin
- if EnableTrace then trace(p, name, value); end;
- GetContext().AddPortIntegerProperty(p,name,value);
- end AddPortIntegerProperty;
- procedure AddFlagProperty*(c: Cell; const name: array of char);
- begin
- if EnableTrace then trace(c, name); end;
- GetContext().AddFlagProperty(c.c, name);
- end AddFlagProperty;
- procedure AddStringProperty*(c: Cell; const name: array of char; var newValue: array of char; const value: array of char);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- copy(value, newValue);
- GetContext().AddStringProperty(c.c, name, value);
- end AddStringProperty;
- procedure AddIntegerProperty*(c: Cell; const name: array of char; var newValue: longint; value: longint);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- newValue := value;
- GetContext().AddIntegerProperty(c.c, name, value);
- end AddIntegerProperty;
- procedure AddBooleanProperty*(c: Cell; const name: array of char; var newValue: boolean; value: boolean);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- newValue := value;
- GetContext().AddBooleanProperty(c.c, name, value);
- end AddBooleanProperty;
- procedure AddRealProperty*(c: Cell; const name: array of char; var newValue: longreal; value: longreal);
- begin
- if EnableTrace then trace(c, name, newValue, value, entier(value)); end;
- newValue := value;
- GetContext().AddRealProperty(c.c, name, value);
- end AddRealProperty;
- procedure AddSetProperty*(c: Cell; const name: array of char; var newValue: set; value: set);
- begin
- if EnableTrace then trace(c, name, newValue, value); end;
- newValue := value;
- GetContext().AddSetProperty(c.c, name, value);
- end AddSetProperty;
- procedure FinishedProperties*(c: Cell);
- begin
- if EnableTrace then trace(c); end;
- GetContext().FinishedProperties(c.c);
- end FinishedProperties;
- procedure Connect*(outPort, inPort: any; depth: longint);
- begin
- if EnableTrace then trace(outPort, inPort, outPort, inPort, depth); end;
- GetContext().Connect(outPort, inPort, depth);
- end Connect;
- procedure Delegate*(netPort: any; cellPort: any);
- begin
- if EnableTrace then trace(netPort, cellPort); end;
- GetContext().Delegate(netPort, cellPort);
- end Delegate;
- procedure Start*(c: Cell; proc: procedure{DELEGATE});
- begin
- if EnableTrace then trace(c, proc); end;
- GetContext().Start(c.c, proc);
- end Start;
-
- procedure Send*(p: any; value: longint);
- begin
- GetContext().Send(p, value);
- end Send;
-
- procedure BulkSend*(p: any; const value: array of system.byte);
- begin
- GetContext().BulkSend(p,value);
- end BulkSend;
-
- procedure SendNonBlocking*(p: any; value: longint): boolean;
- begin
- return GetContext().SendNonBlocking(p, value);
- end SendNonBlocking;
- procedure Receive*(p: any; var value: longint);
- begin
- GetContext().Receive(p, value);
- end Receive;
-
- procedure BulkReceive*(p: any; var value: array of system.byte);
- begin
- GetContext().BulkReceive(p,value);
- end BulkReceive;
-
- procedure ReceiveNonBlocking*(p: any; var value: longint): boolean;
- begin
- return GetContext().ReceiveNonBlocking(p, value);
- end ReceiveNonBlocking;
- type
- Module = pointer to record
- next: Module;
- checked, imports: boolean;
- m: Modules.Module
- end;
-
- procedure Find(root: Module; m: Modules.Module): Module;
- begin
- while (root # nil) & (root.m # m) do root := root.next end;
- return root
- end Find;
- procedure Imports(root, m: Module; const name: array of char): boolean;
- var i: longint;
- begin
- if ~m.checked then
- if m.m.name # name then
- i := 0;
- while i # len(m.m.module) do
- if (m.m.module[i].name = name) or Imports(root, Find(root, m.m.module[i]), name) then
- m.imports := true; i := len(m.m.module)
- else
- inc(i)
- end
- end
- else
- m.imports := true
- end;
- m.checked := true
- end;
- return m.imports
- end Imports;
- (*! caution: this is not thread safe -- must be moved to Modules.Mod *)
- procedure CopyModules(): Module;
- var firstm, lastm, c: Module; m: Modules.Module;
- begin
- new(firstm); firstm.next := nil; lastm := firstm;
- m := Modules.root;
- while m # nil do
- new(c); c.checked := false; c.imports := false; c.m := m;
- c.next := nil; lastm.next := c; lastm := c;
- m := m.next
- end;
- return firstm.next
- end CopyModules;
- procedure FreeDownTo(const modulename: array of char): longint;
- var
- root, m: Module; res: longint;
- nbrOfUnloadedModules : longint;
- msg: array 32 of char;
- begin
- nbrOfUnloadedModules := 0;
- root := CopyModules();
- m := root;
- while m # nil do
- if Imports(root, m, modulename) then
- Modules.FreeModule(m.m.name, res, msg);
- if res # 0 then
- (*context.error.String(msg);*)
- else
- inc(nbrOfUnloadedModules);
- end
- end;
- m := m.next
- end;
- return nbrOfUnloadedModules;
- end FreeDownTo;
-
- (**
- Execute ActiveCells CELLNET code
-
- cellNet: name of a CELLNET type in the format "ModuleName.TypeName", e.g. TestActiveCells.TestCellNet
- context: runtime context used for executing the ActiveCells code
- diagnostics: interface for generation of diagnostic messages (see Diagnostics.Mod)
- *)
- procedure Execute*(const cellNet: array of char; context: Context; diagnostics: Diagnostics.Diagnostics);
- type
- StartProc = procedure{DELEGATE}();
-
- Starter = object
- var
- p: StartProc;
- c: Cell;
- procedure & InitStarter(proc: address; scope: Cell);
- var startProcDesc: record proc: address; selfParam: address; end;
- begin
- startProcDesc.proc := proc;
- startProcDesc.selfParam := scope;
- system.move(address of startProcDesc, address of p, 2 * size of address);
- c := scope;
- end InitStarter;
- procedure P;
- begin
- Start(c, p)
- end P;
- end Starter;
-
- var
- moduleName, typeName, name: array 256 of char;
- m: Modules.Module;
- typeInfo: Modules.TypeDesc;
- i: size; res: longint;
- str: array 256 of char;
- scope: Cell;
- unloaded: longint;
- starter: Starter;
- launcher: Launcher;
- offset: size;
- pc: address;
- begin
- assert(context # nil);
- context.topNet := nil;
-
- i := Strings.IndexOfByte2(".",cellNet);
- if i = -1 then
- diagnostics.Error("",Streams.Invalid, "CELLNET type name is malformed");
- return;
- end;
- Strings.Copy(cellNet,0,i,moduleName);
- Strings.Copy(cellNet,i+1,Strings.Length(cellNet)-Strings.Length(moduleName),typeName);
- unloaded := FreeDownTo(moduleName);
- if unloaded > 0 then
- (*param.ctx.Information("", Streams.Invalid,"unloaded " & unloaded & " modules")*)
- end;
- m := Modules.ThisModule(moduleName,res,str);
- if m = nil then
- Strings.Concat('failed to load module "',moduleName,str);
- Strings.Concat(str,'"',str);
- diagnostics.Error("",Streams.Invalid,str);
- return;
- end;
- typeInfo := Modules.ThisType(m,typeName);
- if typeInfo = nil then
- Strings.Concat('failed to find CELLNET type "',cellNet,str);
- Strings.Concat(str,'" in module "',str);
- Strings.Concat(str,moduleName,str);
- Strings.Concat(str,'"',str);
- diagnostics.Error("",Streams.Invalid,str);
- return;
- end;
- copy(typeName, name);
- Strings.Append(name, ".@Body");
- trace(name);
- trace(m.refs);
- offset := Reflection.FindByName(m.refs, 0, name, true);
- if offset # 0 then
- if Reflection.GetChar(m.refs,offset) = Reflection.sfProcedure then
- Reflection.SkipSize(offset);
- Reflection.SkipString(m.refs,offset);
- pc := Reflection.GetAddress(m.refs, offset);
- trace(pc);
-
- (*assert(len(typeInfo.procedures) = 1);
- assert(typeInfo.procedures[0].name^ = "@Body");
- *)
- (* allocate the top level cellnet *)
- AllocateOnContext(context, nil,scope,typeInfo.tag,typeName,true,false);
- assert(scope # nil);
- assert(scope.c # nil);
- new(starter, pc, scope);
- end;
- new(launcher, context);
- launcher.Start(starter.P, true);
- context.FinishedAssembly;
- assert(~launcher.error);
- else
- Reflection.Report(Commands.GetContext().out, m.refs, offset);
- end;
- end Execute;
-
- type bytearray= array of system.byte;
- operator "<<"* (p: port out; const a: bytearray);
- begin
- if EnableTrace then trace('bulk send',len(a)); end;
- BulkSend(system.val(any,p),a);
- end "<<";
-
-
- operator "<<"* (var a: bytearray; p: port in);
- begin
- if EnableTrace then trace('bulk rec',len(a));end;
- BulkReceive(system.val(any,p),a);
- end "<<";
-
- (*The extra functions for longint and real were introduced because right now primitive types cannot be passed as byte arrays*)
- type longintSpecial= longint;
- operator "<<"* (p: port out; a: longintSpecial);
- begin
- if EnableTrace then trace('longint send');end;
- BulkSend(system.val(any,p),a);
- end "<<";
-
- operator "<<"* (var a: longintSpecial; p: port in);
- begin
- if EnableTrace then trace('longint rec');end;
- BulkReceive(system.val(any,p),a);
- end "<<";
- type realSpecial= real;
- operator "<<"* (p: port out; a: realSpecial);
- begin
- if EnableTrace then trace('real send');end;
- BulkSend(system.val(any,p),a);
- end "<<";
-
- operator "<<"* (var a:realSpecial; p: port in);
- begin
- if EnableTrace then trace('real rec');end;
- BulkReceive(system.val(any,p),a);
- end "<<";
- type Pin = port in; Pout = port out;
-
- operator ">>"* (pout: Pout; pin: Pin);
- begin
- Connect(system.val(any, pout), system.val(any, pin), 0);
- end ">>";
-
- operator ">>"* (cellPort: Pout; netPort: Pout);
- begin
- Delegate(system.val(any, cellPort), system.val(any, netPort));
- end ">>";
-
- operator ">>"* (netPort: Pin; cellPort: Pin);
- begin
- Delegate(system.val(any, netPort), system.val(any, cellPort));
- end ">>";
- end ActiveCellsRuntime.
- System.FreeDownTo FoxSemanticChecker ~
|