Proposing 4 New Ideas - #2 Interjections lazarus / 64-FPC development ---------------------------------------------------------------------- IndigoBoy83 · 2019-03-22 12:33 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Program Test1;begin  InterjectCode( writeln('Cool!'); );end. At precompile-time the above program Test1 precompiles to the following: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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 classend; 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/classend. If typeofrec equals "object" then the previous code precompiles to: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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 classend; 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/classend. If typeofrec equals "class" then the above code precompiles to: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i 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 classend; 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/classend. 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 object The 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 ---------------------------------------------------------------------- marcov · 2019-03-22 13:00 This is basically a wooly redefinition of preprocessor, and the standard answer to that is: sure! Use any external preprocessor you want (but we won't implement it) ---------------------------------------------------------------------- Leledumbo · 2019-03-22 19:18 Yep, this is no stronger than a preprocessor. I believe GNU M4 is capable of doing all that you describe already, albeit with different syntax.