Metamorphic programming

Hypothetical Essays on Ybymarian Technology

    A metamorphic code is one that has the peculiar characteristic of changing itself independently of the programmer. For this, a new type of variable will be introduced that can be called ‘logical variable.’ Roughly speaking, the idea is that the program’s lines of code are stored in their own variables. In this way, changing code variables alters its behavior.

    1. Initial concepts of metamorphic programming

    A logical variable can contain a command, function, or value. To identify a logical variable, it may be followed by a symbol. In this work the character “@” will be used for this. Let’s look at the logical variable named VAR as an example.

VAR@ = #PRINT → VAR contains “PRINT” command
VAR@ = #SIN → VAR contains the “SIN” function
VAR@ = “H” → VAR contains the character “H”
VAR@ = 10 → VAR contains the numerical value 10

    A matrix, or vector, of these variables contains a sequence of commands and values. Note that the “#” flag indicates a function or command. Numeric or alphanumeric constants do not need to be preceded by symbols.

    Let’s look at an example of a one-dimensional vector or matrix of logical variables:

VAR@[0] = #PRINT
VAR@[1] = #SIN
VAR@[2] = 10

    This sequence forms a command line:

VAR@[0]VAR@[0]VAR@[0]
PRINTSIN10

    The resulting command line will print the sine value of 10 as a standard output. We can use a command to call a logical variable, such as:

CALL VAR@

    This command will cause the contents of VAR@ to be executed. In this case, the sine value of 10 will be printed on the standard device (screen, for example). This feature, in itself, would not add anything to what current programming languages can do, as it is merely an “eval command ()” broken down into its factors instead of a complete string. The programs remain rigid.

    The objective of metamorphic programming is to enable commands contained in logical variables to be created, deleted, and changed by data and information that is inserted into the system. This is relatively easy. The question is how to make the resulting sequence of commands make sense and prevent the system from crashing or going into an infinite loop, which can occur, for example, in the case of nested or recurring commands. An example:

VAR@[0] = #PRINT
VAR@[1] = #SIN
VAR@[2] = 10
VAR@[3] = #CALL
VAR@[4] = VAR@

    If you call the variable, this sequence of commands within VAR@ will cause the instructions contained in VAR@ to execute indefinitely. To avoid this, one of the rules may be to prevent a logical variable from calling itself. This is the easy and crude solution.

    Let’s focus on the objective of metamorphic programming, which is to develop artificial intelligence; such a situation means that the usual commands in conventional programming languages may not be suitable. Even so, the “input → processing → output” scheme will be maintained here, where the result (output) will be used by another command in a sequence of indefinite and variable length.

    Let’s say we have a command that adds two 16-bit values and delivers the result limited to 16 bits as well. Let’s look at the sequence below (note that the “&” flag was used to indicate data input or output).

Soma@[0] = #ADC
Soma@[1] = &Input1
Soma@[2] = &Input2
Soma@[3] = #OUT
Soma@[4] = &Output1

   This sequence of commands causes the system to add the values of “Input1” and “Input2” using the (#ADC
function) and then directs the result (#OUT) to “Output1”. The structure is basically as follows,

    1. Operation to be performed
    2. Definition of entry ports
    3. Output command
    4. Definition of output ports

    If this structure is maintained, the system will most likely not crash due to any command error. A programming code with this philosophy may be formed by a variable number of blocks with this structure. However, inputs and outputs must be defined before the sequence of blocks. See the suggestion below:

    DEF &Input1 as input = Keyboard;
    DEF &Input2 as input = Mouse;
    DEF &Output1 as output = Video;


    DEF Add@ as logical_variable;


        Add@[0] = #ADC
        Add@[1] = &Input1
        Add@[2] = &Input2
        Add@[3] = #OUT
        Add@[4] = &Output1


    CALL Add@;


    END ROUTINE;

    As it stands, the routine takes a value from the keyboard, another from the mouse, adds the two, and returns the result on the video monitor. The structure remains rigid. Let us also note that inputs and outputs depend on the hardware, only changing as it changes. Because of this, for now, we will consider the input and output definitions as invariant values.

    Continuing the reasoning, we will associate a numerical value with each command. Thus, we will have:

    1 = #ADC
    2 = #SUB
    3 = #OUT
    4 = &Input1
    5 = &Input2
    6 = &Output1
    7 = CALL

    In this way, the numerical values contained in the sequence would be as follows:

Add@[0] = #ADC ;value 1
Add@[1] = &Input1 ;value 4
Add@[2] = &Input2 ;value 5
Add@[3] = #OUT ;value 3
Add@[4] = &Output1 ;value 6

    Let’s suppose the inputs are numeric. So, for example, if we have 2 in &Input1 and 3 in &Input2, then 5 will be sent to &Output1. Let’s add one more line to the code:

Add@[0] = #ADC ;value 1
Add@[1] = &Input1 ;value 4
Add@[2] = &Input2 ;value 5
Add@[3] = #OUT ;value 3
Add@[4] = &Output1 ;value 6

    Note that the value contained in the Add@[0] position will vary depending on the value of &Input1. In this position is the
#ADC command, whose associated number is 1. If we enter the same values, we will have:

Add@[0] = #ADC ;Add command
Add@[1] = &Input1 ;1st entry value (2)
Add@[2] = &Input2 ;2nd entry value (3)
Add@[3] = #OUT ;Output command
Add@[4] = &Output1 ;Output value (5)
Add@[0] = (&Input1) ;Put ”&Input1” value in Add@[0] (SUB command)
CALL Add@ ;Execute

    * Code after first run:

Add@[0] = #SUB ;Add command
Add@[1] = &Input1 ;1st entry value
Add@[2] = &Input2 ;2nd entry value
Add@[3] = #OUT ;Output command
Add@[4] = &Output1 ;Output value
Add@[0] = &Input1 ;Put ”&Input1” value in Add@[0]

    Let us observe that an input value changed the program code. This is the primary concept of metamorphic programming.

    2. Structure of a metamorphic language

    A metamorphic code is basically formed by vectors or strings of variable size where each position may contain a numeric value (quantitative), an alphanumeric value or character (qualitative), or an execution value (command or function). The number of vectors is also variable and can change at run time. We can, for example, create the vector of the code illustrated above (already with the variable definers):

DEF &Input1 as input = Keyboard;
DEF &Input2 as input = Mouse;
DEF &Output1 as output = Video;

VECTOR[1] = Add@ {
0 = #ADC
1 = &Input1
2 = &Input2
3 = #OUT
4 = &Output1
0 = &Input1
}

    Note that the definers are outside the vector, which means they cannot be changed. There may be commands located outside the vectors; in this case, their structure will be rigid, similar to the known structured codes. In any case, we can see that metamorphic codes will be very different from other types of code, including their types of commands and variables.

    A basic question to resolve is how the system will work if an entered value does not correspond to any command or variable definer. Let’s say the value is 50. In the example, there is no command associated with this number. Let’s see what happens.

    Original code:

DEF &Input1 as input = Keyboard;
DEF &Input2 as input = Mouse;
DEF &Output1 as output = Video;

VECTOR[1] = Add@ {
0 = #ADC
1 = &Input1
2 = &Input2
3 = #OUT
4 = &Output1
0 = &Input1
}
&Input1 = 50
&Input2 = 40

    After the first run (without variable definers):

VECTOR[1] = Add@ {
0 = %50
1 = %50
2 = %40
3 = #OUT
4 = %90
0 = %50
}
(&Input1) = 50
(&Input2) = 40

    In the example, the identifier “%” was used to indicate a numeric value. Note that there is no more addition command, leaving only the output command. This will happen whenever the code is as illustrated. A better way to treat variables contained in vectors is to keep them of the same type after they are created. Thus, indices 0 and 3 will always be commands, and indices 1, 2, and 4 will be input or output values. A list of commands must be associated with each numeric value, and a substitution rule will be used when there is no command corresponding to the number entered.

    So, after running with these rules, the code will look like this:

VECTOR[1] = Add@ {
0 = #NEW COMMAND
1 = &Input1
2 = &Input2
3 = #OUT
4 = &Output1
0 = &Input1
}
(&Input1) = 50
(&Input2) = 40
(&Output1) = 90

    However, the numerical variables inserted do not have a specific position within the vector, which is not desirable. So let’s create a position for each one:

VECTOR[1] = Add@ {
0 = #NEW COMMAND
1 = &Input1
2 = &Input2
3 = #OUT
4 = &Output1
5 = VAL (&Input1)
6 = VAL (&Input2)
7 = VAL (&Output1)
0 = VAL (&Input1)
}

    Thus, the values of &Input1, &Input2 and &Output1 will be stored in positions 5, 6, and 7, respectively, and positions 1, 2, and 4 continue with their input and output function. Note that in the last line, which reassigns position 0, the value (&Input1) is in parentheses to indicate that this is not an input position but a simple reassignment of value to the position, which will result in the command changing. Likewise, in positions 5, 6, and 7, the descriptors are in parentheses for the same reason.

    So far, we have defined four types of data that can be inserted into vector positions:

    Identifier # → command or function.
    Identifier & → data input or output.
    Identifier % → numerical or quantitative value.
    Identifier $ → descriptive or qualitative value.

    Types cannot be changed once defined; otherwise, the code will become useless. Changing the content of the vector indices also changes the behavior of the code; however, the same value will mean different things depending on the identifier. For example, the value 5 in an index could mean:

    2.1. Exclusive commands of a metamorphic language

    #5 → AND command (logical AND operator)
    &5 → data input (say, &Input1)
    %5 → integer numeric value 5
    $5 → character ‘A’

    Among the possible commands, there are two that are special and, one could say, exclusive to metamorphic codes. These are the commands #INC and #EXC, which mean “Include” and “Exclude.” Let’s look at the example below to see what these commands do.

VECTOR[1] = Add@ {
    0 = &Input1
    1 = #OUT
    2 = &Output1
    3 = #INC
    4 = 0
    5 = "#ADC"

    }

    After the first run:

VECTOR[1] = Adda@ {
    0 = #ADC
    1 = &Input1
    2 = #OUT
    3 = &Output1
    4 = #INC
    5 = 0
    6 = "#ADC"
    }

    And for the #EXC command:

VECTOR[1] = Add@ {
    0 = &Input1
    1 = #OUT
    2 = &Output1
    3 = #EXC
    4 = 0
    }

    After the first run:

VECTOR[1] = Add@ {
    0 = #OUT
    1 = &Output1
    2 = #EXC
    3 = 0
    }

    2.2. Command examples

    Change commands

INC – Includes a cell in the vector.
EXC – Deletes a cell from the vector.
SUBS – Replaces a cell in the vector.

    Operation commands

ADC – Adds the next two cells.
SBC – Subtracts the next cell from the next.
MULT – Multiplies the next two cells.
DIV – Divides the next cell by the next.
REST – Returns the remainder of dividing the next cell by the next.
AND – Performs logical AND operation between the following two cells.
OR – Performs logical OR operation between the following two cells.
XOR – Performs XOR logical operation between the following two cells.
NOT – Inverts the logical condition of the next cell.

    Input/Output Commands

DEF &xxx AS INPUT = DISP → Assigns <DISP> to xxx as input
DEF &yyy AS OUTPUT = DISP → Assigns <DISP> to yyy as output

    Creation and execution commands:

VECTOR [num] = zzz@ → Creates vector number <num> with name <zzz>
CALL zzz@ → Executes the vector <zzz>

    3. Structure of a metamorphic vector

    Each index of the vector must have a fixed size, say 32 bits. Some of these must be reserved to define which type of logic variable is contained in it. Reserving 4 bits will define up to 16 types, leaving 28 bits for an integer numeric value from 0 to 268,436,455 (or –134,217,728 to 134,217,727, or any other representable value).

    In each position of the vector, a command, a function, a numeric value, an alphanumeric character, a variable descriptor, etc. can be stored. For each of them there is a specific ID, which cannot be changed once it is created. An example of IDs:

00 – Marks the beginning of the vector
01 – Command
02 – Function
03 – Data output marker
04 – Data entry marker
05 – Unsigned integer value (0 to 268,436,455)
06 – Signed integer value (–134,217,728 to +134,217,727)
07 – Exponent
08 – First half of the mantissa
09 – Second half of the mantissa
10 – Imaginary exponent
11 – First half of the imaginary mantissa
12 – Second half of the imaginary mantissa
13 – Alphanumeric character
14 – Ideographic character
15 – Mark the end of the vector

    As agreed, the four ID bits cannot be modified once created; only the remaining 28 bits are variable.

    In some cases, some cells can be grouped, such as the IDs 7, 8, and 9, to compose a floating point number, or in the case of the ADC command, they can be grouped with the following two values. Such groups can form a block (whose structure cannot be modified) or a sequence of flexible structures.

Rolar para cima