PAGE #2A - Introducing Interjections
The notion of interjections can be called the use of "non-generic code".
InterjectCode is a procedure which is compiled and executed *before* compile-time, that is, at precompile-time. It outputs the code that resides in its "parameter space".
Take the following snippet as example:
Program Test1;
begin
InterjectCode( writeln('Cool!'); );
end.
At precompile-time the above program Test1 precompiles to the following:
Program Test1;
begin
writeln('Cool!');
end.
It can then compile normally as usual.
Interjections are methods similar to functions, but do not return values, rather they return code.
They are made up of code too; which we call "compile code", unlike "runtime code" as everything else.
Unlike procedures they cannot be called at compile-time. Rather, they are methods that have to do it before, at precompile-time.
All interjections start of with the moniker "Interjection".
Then we give the name of the interjection.
They too may have a parameter list just like regular compile methods.
As precompile-time methods, they denote their boundaries using the words "start"/"stop" rather than the words "begin"/"end" for compile-time methods.
A programmer may find himself inside of an "InterjectCode" call and want to "jump out" into the compiler. One does that by using the following syntax: we write "***" to enter and exit compiler code. We give below an example of this use with an interjection:
Program Test2;
Interjection TestMe( _str : string );
start
InterjectCode(
writeln( 'The given string is ', _str );
);
stop;
begin
InterjectCode( ***TestMe( 'Hello' );*** );
InterjectCode( ***TestMe( 'GoodBye' );*** );
end.
At precompile-time the above program Test2 precompiles to the following:
Program Test2;
begin
writeln( 'The given string is Hello' );
writeln( 'The given string is GoodBye' );
end.
The following program takes the above Test2 and augments it to Test3, to demonstrate that we can "nest" interjections:
Program Test3;
Interjection TestMeAgain( _int : integer );
start
if _int = 5 then
InterjectCode(
writeln( 'Thank you! I like my strings in fives!' );
)
else
InterjectCode(
writeln( 'No thanks! I like my strings in fives ONLY!' );
);
stop;
Interjection TestMe( _str : string );
start
InterjectCode(
writeln( 'The given string is ', _str );
InterjectCode( ***TestMeAgain( length(_str) );*** );
);
stop;
begin
InterjectCode( ***TestMe( 'Hello' );*** );
InterjectCode( ***TestMe( 'GoodBye' );*** );
end.
At precompile-time the above program Test3 precompiles to the following:
Program Test3;
begin
writeln( 'The given string is Hello' );
writeln( 'Thank you! I like my strings in fives!' );
writeln( 'The given string is GoodBye' );
writeln( 'No thanks! I like my strings in fives ONLY!' );
end.
------------------------------------------------------------------
PAGE #2B - Solving the object/class war
The following solves the problem of how to change between an "object" to a "class" in one fluent motion, using the idea of interjections.
By using interjections the programmer may decide, at compile-time, whether his records are objects or classes with the ease of changing the value of *only* one variable.
Notice: Below we use the notion of etypes, and the typeof function, which returns the type of the given parameter.
Program Ending_Object_Class_War;
interface
uses
Classes;
const
typeofrec : etype = object; // Can be set to either object or class depending on programmers wish on compilation
implementation
Interjection MakeIt( var _x : typeofrec );
start
case typeof(_x) of
object: InterjectCode( New(_x); );
class: InterjectCode( _x.Create; );
end;
stop;
Interjection UnMakeIt( var _x : typeofrec );
start
case typeof(_x) of
object: InterjectCode( Dispose(_x); );
class: InterjectCode( _x.Free; );
end;
stop;
type
some_record_type = typeofrec
Procedure WriteItOut;
end;
Procedure some_record_type.WriteItOut;
begin
writeln( 'Programmer can decide whether this "some_rec" is an object or class at compile-time with one easy switch of the value typeofrec!' );
writeln( 'Right now some_record_type is ', str(typeof(self)) ); // Outputs whether self is object or class
end;
var
some_rec : some_record_type;
begin
InterjectCode( ***MakeIt( some_rec );*** ); // Makes some_rec as object/class
some_rec.WriteItOut; // Writes message to screen
InterjectCode( ***UnMakeIt( some_rec );*** ); // UnMakes some_rec as object/class
end.
If typeofrec equals "object" then the previous code precompiles to:
Program Ending_Object_Class_War;
interface
uses
Classes;
implementation
type
some_record_type = object
Procedure WriteItOut;
end;
Procedure some_record_type.WriteItOut;
begin
writeln( 'Programmer can decide whether this "some_rec_type" is an object or class at compile-time with one easy switch of the value typeofrec!' );
writeln( 'Right now some_record_type is object' ); // Outputs whether self is object or class
end;
var
some_rec : some_record_type;
begin
New( some_rec ); // Makes some_rec as object/class
some_rec.WriteItOut; // Writes message to screen
Dispose( some_rec ); // Makes some_rec as object/class
end.
If typeofrec equals "class" then the above code precompiles to:
Program Ending_Object_Class_War;
interface
uses
Classes;
implementation
type
some_record_type = class
Procedure WriteItOut;
end;
Procedure some_record_type.WriteItOut;
begin
writeln( 'Programmer can decide whether this "some_rec_type" is an object or class at compile-time with one easy switch of the value typeofrec!' );
writeln( 'Right now some_record_type is class' ); // Outputs whether self is object or class
end;
var
some_rec : some_record_type;
begin
some_rec.Create; // Makes some_rec as object/class
some_rec.WriteItOut; // Writes message to screen
some_rec.Free; // Makes some_rec as object/class
end.
The output of the first above is:
Programmer can decide whether this "some_rec_type" is an object or class at compile-time with one easy switch of the value typeofrec!
Right now some_record_type is objectThe output of the second above is:
Programmer can decide whether this "some_rec_type" is an object or class at compile-time with one easy switch of the value typeofrec!
Right now some_record_type is class