Modern Pascal Chaining
Modern Pascal supports a feature introduced in Turbo Pascal 3.0, CHAIN.Concept
One of the greatest benefits of CHAINing, is only the relative functionality is in memory. This is useful for performance and scaling, as the chain variables are kept in a private region of memory for instant access by the next (or even a later) script for the current instance. This means you do not have a lot of bloat in memory as found with PHP and other script engines. Quicker parsing, means quicker response, means more satisfied clients.Prerequisites
Before proceeding to call the CHAIN.* methods, you need to know that the CHAIN unit (uses chains) is always loaded, just like the system (uses system) unit is always loaded. You can store base data types (Byte, Char, Word, String, Extended, etc) and you can store individual elements of a Record, Union and Class, but not the actual Record, Union or Class. Your next script will different memory addresses available (due to the way computers work) from script to script, so you will need to allocate your Record, Union or Class objects then retrieve the values of their elements.Overview
Chaining allows for tighter product security, for example you cannot run script paycheck.p without first going through the login.p script. Chaining reduces the memory footprint of your scripts, as you are not loading and parsing sections of code that are not going to be used currently in the operational workflow. Chaining can also allow you to run other peoples modules or products from your menu or product for example.There are five methods to manage the passing of variables in the chain object:
- Chain.Store('VariableName', VariableItself);
- Chain.Retrieve('VariableName', VariableItself);
- Chain.VarExists('VariableName'):Boolean;
- Chain.Release('VariableName');
- Chain.ReadBoolean('VariableName'):Boolean;
- Chain.ReadByteBoolean('VariableName'):ByteBool;
- Chain.ReadWordBool('VariableName'):WordBool;
- Chain.ReadLongBool('VariableName'):LongBool;
- Chain.ReadChar('VariableName'):Char;
- Chain.ReadShortint('VariableName'):Int8;
- Chain.ReadSmallint('VariableName'):Int16;
- Chain.ReadLongint('VariableName'):Int32;
- Chain.ReadLargeint('VariableName'):Int64;
- Chain.ReadByte('VariableName'):UInt8;
- Chain.ReadWord('VariableName'):UInt16;
- Chain.ReadLongWord('VariableName'):UInt32;
- Chain.ReadLargeWord('VariableName'):UInt64;
- Chain.ReadSingle('VariableName'):Single;
- Chain.ReadDouble('VariableName'):Double;
- Chain.ReadExtended('VariableName'):Extended;
- Chain.ReadCurrency('VariableName'):Currency;
- Chain.ReadString('VariableName'):String;
- Chain.Clear;
Executing an actual CHAIN
There is one method to execute another script:- Chain.Run('Filename');
When you call Chain.Run(), the path to the filename is the path of the script engine is currently. So you make sure you have physical or relative path information as part of the filename.
CHAIN1.P
var B:Boolean; I:Longint; I6:Int64; begin B:=True; I:=1234; I6:=143; Chain.Store('B',B); Chain.Store('I',I); Chain.Store('I6',I6); Writeln(SizeOf(B)+SizeOf(I)+SizeOf(I6)); Chain.Run('chain2'); end.CHAIN2.P
var NewNamedBool:Boolean; begin Chain.Retrieve('B',NewNamedBool); Writeln('Hello World ',NewNamedBool); Chain.Run('chain3'); end.CHAIN3.P
var B:Boolean; I:Longint; I6:Int64; begin Chain.Retrieve('B',B); Chain.Retrieve('I',I); Chain.Retrieve('I6',I6); Writeln(B); Writeln(I); Writeln(I6); end.
Output
13 Hello World True True 1234 143